\" > ".$fn;
+ $cmd[]="/bin/echo >> ".$fn;
+ $cmd[]="/bin/cat doc/txt/".$q." >> ".$fn;
+ foreach ($cmd as $c)
+ {
+ echo $c."\n";
+ exec($c);
+ }
+ echo "\n";
+ }
+}
+?>
diff --git a/build-tools/release.php b/build-tools/release.php
new file mode 100644
index 0000000..d0f234a
--- /dev/null
+++ b/build-tools/release.php
@@ -0,0 +1,103 @@
+#!/usr/bin/php -q
+
+
diff --git a/build.php b/build.php
new file mode 100644
index 0000000..4fe33c1
--- /dev/null
+++ b/build.php
@@ -0,0 +1,241 @@
+Version.$_FREENATS->Release;
+
+for ($i=1; $i ".$BuildDir."/server/base/sql/schema.sql";
+$cmd[]="echo \"-- No DROP TABLES - suitable for upgrade\" >> ".$BuildDir."/server/base/sql/schema.sql";
+$cmd[]="./build-tools/dbdump.sh ".$_FREENATS_DB_SERVER." ".$_FREENATS_DB_DATABASE." ".$_FREENATS_DB_USERNAME." ".$_FREENATS_DB_PASSWORD." >> ".$BuildDir."/server/base/sql/schema.sql";
+
+$cmd[]="echo \"-- FreeNATS ".$Build_ID." Schema\" > ".$BuildDir."/server/base/sql/schema.drop.sql";
+$cmd[]="echo \"-- With DROP TABLES - will clean database\" > ".$BuildDir."/server/base/sql/schema.drop.sql";
+$cmd[]="./build-tools/dbdump.sh ".$_FREENATS_DB_SERVER." ".$_FREENATS_DB_DATABASE." ".$_FREENATS_DB_USERNAME." ".$_FREENATS_DB_PASSWORD." drop >> ".$BuildDir."/server/base/sql/schema.drop.sql";
+
+$cmd[]="echo \"-- FreeNATS ".$Build_ID." Schema\" > ".$BuildDir."/server/base/sql/schema.upgrade.sql";
+$cmd[]="echo \"-- Experimental Upgrade SQL - run after schema.sql (not drop!)\" >> ".$BuildDir."/server/base/sql/schema.upgrade.sql";
+$cmd[]="echo \"-- Both will generate many many errors - run with --force, ignore errors\" >> ".$BuildDir."/server/base/sql/schema.upgrade.sql";
+//$cmd[]="./dbupg.sh freenats fn >> ".$BuildDir."/server/base/sql/schema.upgrade.sql";
+$cmd[]="php build-tools/myrug.cli.php -h=".$_FREENATS_DB_SERVER." -u=".$_FREENATS_DB_USERNAME." -p=".$_FREENATS_DB_PASSWORD." ".$_FREENATS_DB_DATABASE." >> ".$BuildDir."/server/base/sql/schema.upgrade.sql";
+
+$cmd[]="cp -Rf ".$BuildDir."/server/base/sql/* ./sql/latest/";
+
+$Build_File = "";
+if (!$Config_Dummy) // Compress File
+{
+ if ($Config_Zip)
+ {
+ $Build_File = $BuildDir.".zip";
+ $cmd[]="cd ".$Config_Dir." && zip -r ".$Build_ID.".zip ".$Build_ID;
+ }
+ else
+ {
+ $Build_File = $BuildDir.".tar";
+ $cmd[]="tar -c -C ".$Config_Dir." ".$Build_ID." > ".$Build_File;
+ $cmd[]="gzip ".$Build_File;
+ $Build_File.=".gz";
+ }
+}
+
+if ($Config_Clean)
+{
+ $cmd[]="rm -Rf ".$BuildDir;
+}
+
+if ($Config_Upload)
+{
+ $relscript="php build-tools/release.php ".$CompoundVersion." ".$Build_File;
+ if ($_FREENATS_UPLOAD_URL != "")
+ $relscript.=" ".$_FREENATS_UPLOAD_URL;
+ $cmd[]=$relscript;
+}
+
+foreach($cmd as $c)
+ {
+ echo $c."\n";
+ if ($Config_Exec === true) passthru($c);
+ }
+?>
\ No newline at end of file
diff --git a/doc/html/LICENCE.TXT b/doc/html/LICENCE.TXT
new file mode 100755
index 0000000..818433e
--- /dev/null
+++ b/doc/html/LICENCE.TXT
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. 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
+them 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 prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. 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.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey 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;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If 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 convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU 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 that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ 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.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+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.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ 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
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ 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 3 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, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program 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, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU 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 Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/doc/html/README.html b/doc/html/README.html
new file mode 100755
index 0000000..b162e75
--- /dev/null
+++ b/doc/html/README.html
@@ -0,0 +1,14 @@
+
+See install.html for the briefest of brief instructions. More (and up-to-date-ish) information
+is available at the project homepage www.purplepixie.org/freenats.
+
+
+Good luck!
+
+
diff --git a/doc/html/THIS_IS_NOT_VMWARE.html b/doc/html/THIS_IS_NOT_VMWARE.html
new file mode 100755
index 0000000..26bfc6e
--- /dev/null
+++ b/doc/html/THIS_IS_NOT_VMWARE.html
@@ -0,0 +1,7 @@
+
Updated: 20:35:41 06/02/2016
+
+This is NOT the VMWare Virtual Appliance it is just the PHP source code
+
+Go to: the download page and download the VM
+appliance if that is what you are after.
+
diff --git a/doc/html/install.html b/doc/html/install.html
new file mode 100755
index 0000000..dbb76a3
--- /dev/null
+++ b/doc/html/install.html
@@ -0,0 +1,76 @@
+
Updated: 20:35:41 06/02/2016
+
+
FreeNATS - Installation Documentation
+
+This brief installation document is the only documentation that comes with FreeNATS. For full up-to-date documentation and licence information visit the FreeNATS website at www.purplepixie.org/freenats.
+
+There are two methods of installation available; automatic where a script does all the work creating the relevant database tables or you can import the SQL manually.
+
+FreeNATS creates various tables in the database all prefixed with "fn".
+
+Install PHP Source Code
+
+Extract freenats-V.vv.sr.tar.gz
+"web" is the web interface directory and needs to be "published". Ideally the other dirs (base and bin) should be not published at all by apache but (a) it should be safe to call any of those scripts anyway and (b) there are .htaccess files in the dirs.
+If you have moved web somewhere (so the base dir is not ../base from the web dir) will need to edit the include.php file in the web dir and give it the base location (WITH TRAILING SLASH!).
+
+You can do this automatically by running the "shell-install.sh" script in the root folder (copying and moving that is - not the DB setup etc).
+
+Edit the base/config.inc.php file and put in your MySQL connection settings.
+
+
+Upgrading
+
+You can upgrade your system (files only - not schema) by using the "shell-install.sh" script. This will copy all files bar specific system config (the includes and config.inc files).
+
+Feel free to try the experimental upgrade process to update the schema either by manually importing the
+"schema.sql" and "schema.upgrade.sql" (one will create any missing tables and the other will
+update any pre-existing tables) or by using the firstrun script (you will need to rename it from firstrun-.php and
+then browse to it).
+Expect lots of errors with the update as it will try to recreate tables/fields/keys already in existance - don't
+worry too much about it. You should be able to see any "serious" errors.
+
+Upgrading Virtual Appliance
+
+Virtual Appliance users should use the "vm-upgrade.sh" script which will run the upgrade script with the correct default locations.
+Please note this will only upgrade FreeNATS - you should check for rPath upgrades through it's admin console.
+
+Automatic Installation
+
+Rename the web/firstrun-.php file to web/firstrun.php
+
+Navigate to http://your.freenats.url/firstrun.php
+
+Follow the instructions
+
+Manual Installation
+
+In the base/sql dir there are various .sql files - schema, schema.drop, schema.upgrade, default and example
+
+You will need to run/import schema (the database table structure) and default (the admin user and some necessary default settings) for the system to work.
+
+The example.sql file contains optional example node and group data and is recommended.
+
+The schema.drop contains if table exists drop queries before trying to create the table so will clean out any
+existing junk if required.
+The schema.upgrade contains upgrade instructions (see above) and not used for a fresh install. If you want to
+upgrade you will need to run mysql (with --force) on schema.sql, upgrade.sql and default.sql in that order.
+The Tester Script
+
+The tester script must be run (via cron or whatever) at regular intervals to poll the nodes. The recommended setting is five minutes.
+It requires the working directory to be the bin dir on startup.
+
+There are two choices - either run bin/tester.sh which will test all enabled nodes waiting for each node/test in sequence and then raising the relevant
+alerts and emails etc. The other option is to run bin/test-threaded.sh which will fork a background process for each node to test. This is better but will
+send an alert email for each node that fails (rather than one with all the failures from that test run at the end). See the documentation for more information.
+
+On many PHP/Linux security setups many of the low level tests (such as ping for example) can require root or some other special privs. You can always run the tester script manually from the console in different environments to test the output.
+Please note that a script crash for lack of privs may not be caught gracefully and may result in stuck monitor scripts and/or just an open monitor record in the database stopping other monitors from running.
+
+In addition to the tester script you should run bin/cleanup.sh daily or so to clean out old sessions and data (inline with your retention settings). This doesn't
+require any special privs unlike the tester. See the documentation for more information.
+Troubleshooting
+
+See install.html for the briefest of brief instructions. More (and up-to-date-ish) information
+is available at the project homepage www.purplepixie.org/freenats.
+
+
+Good luck!
+
+
diff --git a/doc/txt/THIS_IS_NOT_VMWARE.txt b/doc/txt/THIS_IS_NOT_VMWARE.txt
new file mode 100755
index 0000000..1b1c8fe
--- /dev/null
+++ b/doc/txt/THIS_IS_NOT_VMWARE.txt
@@ -0,0 +1,5 @@
+This is NOT the VMWare Virtual Appliance it is just the PHP source code
+
+Go to: the download page and download the VM
+appliance if that is what you are after.
+
diff --git a/doc/txt/install.txt b/doc/txt/install.txt
new file mode 100755
index 0000000..04694c4
--- /dev/null
+++ b/doc/txt/install.txt
@@ -0,0 +1,74 @@
+
FreeNATS - Installation Documentation
+
+This brief installation document is the only documentation that comes with FreeNATS. For full up-to-date documentation and licence information visit the FreeNATS website at www.purplepixie.org/freenats.
+
+There are two methods of installation available; automatic where a script does all the work creating the relevant database tables or you can import the SQL manually.
+
+FreeNATS creates various tables in the database all prefixed with "fn".
+
+Install PHP Source Code
+
+Extract freenats-V.vv.sr.tar.gz
+"web" is the web interface directory and needs to be "published". Ideally the other dirs (base and bin) should be not published at all by apache but (a) it should be safe to call any of those scripts anyway and (b) there are .htaccess files in the dirs.
+If you have moved web somewhere (so the base dir is not ../base from the web dir) will need to edit the include.php file in the web dir and give it the base location (WITH TRAILING SLASH!).
+
+You can do this automatically by running the "shell-install.sh" script in the root folder (copying and moving that is - not the DB setup etc).
+
+Edit the base/config.inc.php file and put in your MySQL connection settings.
+
+
+Upgrading
+
+You can upgrade your system (files only - not schema) by using the "shell-install.sh" script. This will copy all files bar specific system config (the includes and config.inc files).
+
+Feel free to try the experimental upgrade process to update the schema either by manually importing the
+"schema.sql" and "schema.upgrade.sql" (one will create any missing tables and the other will
+update any pre-existing tables) or by using the firstrun script (you will need to rename it from firstrun-.php and
+then browse to it).
+Expect lots of errors with the update as it will try to recreate tables/fields/keys already in existance - don't
+worry too much about it. You should be able to see any "serious" errors.
+
+Upgrading Virtual Appliance
+
+Virtual Appliance users should use the "vm-upgrade.sh" script which will run the upgrade script with the correct default locations.
+Please note this will only upgrade FreeNATS - you should check for rPath upgrades through it's admin console.
+
+Automatic Installation
+
+Rename the web/firstrun-.php file to web/firstrun.php
+
+Navigate to http://your.freenats.url/firstrun.php
+
+Follow the instructions
+
+Manual Installation
+
+In the base/sql dir there are various .sql files - schema, schema.drop, schema.upgrade, default and example
+
+You will need to run/import schema (the database table structure) and default (the admin user and some necessary default settings) for the system to work.
+
+The example.sql file contains optional example node and group data and is recommended.
+
+The schema.drop contains if table exists drop queries before trying to create the table so will clean out any
+existing junk if required.
+The schema.upgrade contains upgrade instructions (see above) and not used for a fresh install. If you want to
+upgrade you will need to run mysql (with --force) on schema.sql, upgrade.sql and default.sql in that order.
+The Tester Script
+
+The tester script must be run (via cron or whatever) at regular intervals to poll the nodes. The recommended setting is five minutes.
+It requires the working directory to be the bin dir on startup.
+
+There are two choices - either run bin/tester.sh which will test all enabled nodes waiting for each node/test in sequence and then raising the relevant
+alerts and emails etc. The other option is to run bin/test-threaded.sh which will fork a background process for each node to test. This is better but will
+send an alert email for each node that fails (rather than one with all the failures from that test run at the end). See the documentation for more information.
+
+On many PHP/Linux security setups many of the low level tests (such as ping for example) can require root or some other special privs. You can always run the tester script manually from the console in different environments to test the output.
+Please note that a script crash for lack of privs may not be caught gracefully and may result in stuck monitor scripts and/or just an open monitor record in the database stopping other monitors from running.
+
+In addition to the tester script you should run bin/cleanup.sh daily or so to clean out old sessions and data (inline with your retention settings). This doesn't
+require any special privs unlike the tester. See the documentation for more information.
+Troubleshooting
+
+
diff --git a/freenats b/freenats
new file mode 160000
index 0000000..9e78964
--- /dev/null
+++ b/freenats
@@ -0,0 +1 @@
+Subproject commit 9e7896429a28c98492d3e3ac0f265c7192995ac4
diff --git a/pub/server/base/config.inc.php b/pub/server/base/config.inc.php
new file mode 100755
index 0000000..91729d7
--- /dev/null
+++ b/pub/server/base/config.inc.php
@@ -0,0 +1,51 @@
+
diff --git a/sql/latest/default.sql b/sql/latest/default.sql
new file mode 100755
index 0000000..3dcefd6
--- /dev/null
+++ b/sql/latest/default.sql
@@ -0,0 +1,48 @@
+-- default.sql
+-- FreeNATS Default Settings
+INSERT INTO fnuser(username,password,realname,userlevel) VALUES("admin",MD5("admin"),"Administrator",10);
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("site.name","FreeNATS");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("site.admin","");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("site.email","");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("site.enable.tester","1");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("site.enable.web","1");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("site.enable.adminsql","0");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("site.enable.interactive","1");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("site.popupmessage","0");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("site.graph.public","0");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("site.text.closed","Alert Closed");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("site.text.untested","Untested");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("site.text.passed","Passed");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("site.text.warning","Warning");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("site.text.failed","Failed");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("site.dtformat","H:i:s d/m/Y");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("site.include.tests","0");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("site.include.events","0");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("site.links.newwindow","1");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("log.level","5");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("freenats.firstrun","1");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("freenats.tracker","1");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("test.http.timeout","0");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("test.icmp.attempts","2");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("test.icmp.timeout","0");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("test.icmp.returnms","0");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("test.smtp.timeout","0");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("test.imap.timeout","0");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("test.mysql.timeout","0");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("test.tcp.timeout","0");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("test.udp.timeout","0");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("test.spawndelay","1");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("test.interval","0");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("retain.alert","0");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("retain.testrun","0");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("retain.record","0");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("retain.syslog","0");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("mail.fromname","");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("mail.smtphostname","");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("mail.smtpserver","");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("mail.smtppassword","");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("alert.body.footer","");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("alert.body.header","FreeNATS Alert,");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("alert.subject.long","** FreeNATS Alert **");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("alert.subject.short","FreeNATS Alert");
+
diff --git a/sql/latest/example.sql b/sql/latest/example.sql
new file mode 100755
index 0000000..b5c95bf
--- /dev/null
+++ b/sql/latest/example.sql
@@ -0,0 +1,3 @@
+-- example.sql
+-- FreeNATS Example Settings
+INSERT INTO fnnode(nodeid,nodename,nodedesc,hostname,nodeenabled,pingtest,weight) VALUES("freenats","FreeNATS","FreeNATS Server","127.0.0.1",1,1,10);
\ No newline at end of file
diff --git a/sql/latest/schema.drop.sql b/sql/latest/schema.drop.sql
new file mode 100755
index 0000000..f7e09dc
--- /dev/null
+++ b/sql/latest/schema.drop.sql
@@ -0,0 +1,494 @@
+-- With DROP TABLES - will clean database
+-- MySQL dump 10.14 Distrib 5.5.43-MariaDB, for Linux (x86_64)
+--
+-- Host: localhost Database: freenats
+-- ------------------------------------------------------
+-- Server version 5.5.43-MariaDB
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES utf8 */;
+/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
+/*!40103 SET TIME_ZONE='+00:00' */;
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
+
+--
+-- Table structure for table `fnalert`
+--
+
+DROP TABLE IF EXISTS `fnalert`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `fnalert` (
+ `alertid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `nodeid` varchar(64) NOT NULL,
+ `alertlevel` int(11) NOT NULL DEFAULT '0',
+ `openedx` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `closedx` bigint(20) unsigned NOT NULL DEFAULT '0',
+ PRIMARY KEY (`alertid`),
+ KEY `nodeid` (`nodeid`),
+ KEY `closedx` (`closedx`)
+) ENGINE=MyISAM AUTO_INCREMENT=2298 DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `fnalertaction`
+--
+
+DROP TABLE IF EXISTS `fnalertaction`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `fnalertaction` (
+ `aaid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `atype` varchar(32) NOT NULL,
+ `efrom` varchar(250) NOT NULL,
+ `etolist` text NOT NULL,
+ `esubject` int(11) NOT NULL DEFAULT '0',
+ `etype` int(11) NOT NULL DEFAULT '0',
+ `awarnings` tinyint(1) NOT NULL DEFAULT '0',
+ `adecrease` tinyint(1) NOT NULL DEFAULT '0',
+ `mdata` text NOT NULL,
+ `aname` varchar(120) NOT NULL,
+ `ctrdate` varchar(8) NOT NULL,
+ `ctrlimit` int(10) unsigned NOT NULL DEFAULT '0',
+ `ctrtoday` int(10) unsigned NOT NULL DEFAULT '0',
+ `scheduleid` bigint(20) unsigned NOT NULL DEFAULT '0',
+ PRIMARY KEY (`aaid`)
+) ENGINE=MyISAM AUTO_INCREMENT=9 DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `fnalertlog`
+--
+
+DROP TABLE IF EXISTS `fnalertlog`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `fnalertlog` (
+ `alid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `alertid` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `postedx` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `logentry` varchar(250) NOT NULL,
+ PRIMARY KEY (`alid`),
+ KEY `alertid` (`alertid`)
+) ENGINE=MyISAM AUTO_INCREMENT=49727 DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `fnconfig`
+--
+
+DROP TABLE IF EXISTS `fnconfig`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `fnconfig` (
+ `fnc_var` varchar(64) NOT NULL,
+ `fnc_val` varchar(64) NOT NULL,
+ PRIMARY KEY (`fnc_var`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `fneval`
+--
+
+DROP TABLE IF EXISTS `fneval`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `fneval` (
+ `evalid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `testid` varchar(128) NOT NULL,
+ `weight` int(11) NOT NULL DEFAULT '0',
+ `eoperator` varchar(32) NOT NULL,
+ `evalue` varchar(128) NOT NULL,
+ `eoutcome` int(11) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`evalid`),
+ KEY `testid` (`testid`)
+) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `fngroup`
+--
+
+DROP TABLE IF EXISTS `fngroup`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `fngroup` (
+ `groupid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `groupname` varchar(128) NOT NULL,
+ `groupdesc` varchar(250) NOT NULL,
+ `groupicon` varchar(64) NOT NULL,
+ `weight` int(10) unsigned NOT NULL DEFAULT '0',
+ PRIMARY KEY (`groupid`)
+) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `fngrouplink`
+--
+
+DROP TABLE IF EXISTS `fngrouplink`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `fngrouplink` (
+ `glid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `groupid` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `nodeid` varchar(64) NOT NULL,
+ PRIMARY KEY (`glid`),
+ KEY `groupid` (`groupid`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `fnlocaltest`
+--
+
+DROP TABLE IF EXISTS `fnlocaltest`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `fnlocaltest` (
+ `localtestid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `nodeid` varchar(64) NOT NULL,
+ `alertlevel` int(11) NOT NULL DEFAULT '-1',
+ `lastrunx` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `testtype` varchar(128) NOT NULL,
+ `testparam` varchar(250) DEFAULT NULL,
+ `testrecord` tinyint(1) NOT NULL DEFAULT '0',
+ `simpleeval` tinyint(1) NOT NULL DEFAULT '1',
+ `testname` varchar(64) NOT NULL,
+ `attempts` int(11) NOT NULL DEFAULT '0',
+ `timeout` int(11) NOT NULL DEFAULT '0',
+ `testenabled` tinyint(1) NOT NULL DEFAULT '1',
+ `testparam1` varchar(250) NOT NULL,
+ `testparam2` varchar(250) NOT NULL,
+ `testparam3` varchar(250) NOT NULL,
+ `testparam4` varchar(250) NOT NULL,
+ `testparam5` varchar(250) NOT NULL,
+ `testparam6` varchar(250) NOT NULL,
+ `testparam7` varchar(250) NOT NULL,
+ `testparam8` varchar(250) NOT NULL,
+ `testparam9` varchar(250) NOT NULL,
+ `lastvalue` float NOT NULL DEFAULT '0',
+ `testinterval` int(10) unsigned NOT NULL DEFAULT '0',
+ `nextrunx` bigint(20) unsigned NOT NULL DEFAULT '0',
+ PRIMARY KEY (`localtestid`),
+ KEY `nodeid` (`nodeid`)
+) ENGINE=MyISAM AUTO_INCREMENT=26 DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `fnlog`
+--
+
+DROP TABLE IF EXISTS `fnlog`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `fnlog` (
+ `logid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `postedx` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `modid` varchar(32) NOT NULL,
+ `catid` varchar(32) NOT NULL,
+ `username` varchar(64) NOT NULL,
+ `loglevel` int(11) NOT NULL DEFAULT '1',
+ `logevent` varchar(250) NOT NULL,
+ PRIMARY KEY (`logid`)
+) ENGINE=MyISAM AUTO_INCREMENT=96829571 DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `fnnalink`
+--
+
+DROP TABLE IF EXISTS `fnnalink`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `fnnalink` (
+ `nalid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `nodeid` varchar(64) NOT NULL,
+ `aaid` bigint(20) unsigned NOT NULL DEFAULT '0',
+ PRIMARY KEY (`nalid`)
+) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `fnnode`
+--
+
+DROP TABLE IF EXISTS `fnnode`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `fnnode` (
+ `nodeid` varchar(64) NOT NULL,
+ `nodename` varchar(128) NOT NULL,
+ `nodedesc` varchar(254) NOT NULL,
+ `hostname` varchar(254) NOT NULL,
+ `nodeenabled` tinyint(1) NOT NULL DEFAULT '0',
+ `pingtest` tinyint(1) NOT NULL DEFAULT '0',
+ `pingfatal` tinyint(1) NOT NULL DEFAULT '0',
+ `alertlevel` int(11) NOT NULL DEFAULT '-1',
+ `nodeicon` varchar(64) NOT NULL,
+ `weight` int(10) unsigned NOT NULL DEFAULT '0',
+ `nodealert` tinyint(1) NOT NULL DEFAULT '1',
+ `scheduleid` bigint(20) NOT NULL DEFAULT '0',
+ `lastrunx` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `testinterval` int(10) unsigned NOT NULL DEFAULT '5',
+ `nextrunx` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `nsenabled` tinyint(1) NOT NULL DEFAULT '0',
+ `nsurl` varchar(254) NOT NULL,
+ `nskey` varchar(128) NOT NULL,
+ `nspullenabled` tinyint(1) NOT NULL DEFAULT '0',
+ `nspushenabled` tinyint(1) NOT NULL DEFAULT '0',
+ `nspuship` varchar(128) NOT NULL,
+ `nsinterval` int(10) unsigned NOT NULL DEFAULT '15',
+ `nslastx` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `nsnextx` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `nspullalert` tinyint(1) NOT NULL DEFAULT '0',
+ `nsfreshpush` tinyint(1) NOT NULL DEFAULT '0',
+ `masterid` varchar(64) NOT NULL,
+ `masterjustping` tinyint(1) NOT NULL DEFAULT '1',
+ `ulink0` tinyint(1) NOT NULL DEFAULT '0',
+ `ulink0_title` varchar(254) NOT NULL DEFAULT 'VNC',
+ `ulink0_url` varchar(254) NOT NULL DEFAULT 'http://{HOSTNAME}:5800/',
+ `ulink1` tinyint(1) NOT NULL DEFAULT '0',
+ `ulink1_title` varchar(254) NOT NULL DEFAULT 'SSH',
+ `ulink1_url` varchar(254) NOT NULL DEFAULT 'ssh://{HOSTNAME}',
+ `ulink2` tinyint(1) NOT NULL DEFAULT '0',
+ `ulink2_title` varchar(254) NOT NULL DEFAULT 'Web',
+ `ulink2_url` varchar(254) NOT NULL DEFAULT 'http://{HOSTNAME}',
+ PRIMARY KEY (`nodeid`),
+ KEY `masterid` (`masterid`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `fnnstest`
+--
+
+DROP TABLE IF EXISTS `fnnstest`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `fnnstest` (
+ `nstestid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `nodeid` varchar(64) NOT NULL DEFAULT '',
+ `alertlevel` int(11) NOT NULL DEFAULT '-1',
+ `lastrunx` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `testtype` varchar(128) NOT NULL DEFAULT '',
+ `testdesc` varchar(250) DEFAULT NULL,
+ `testrecord` tinyint(1) NOT NULL DEFAULT '0',
+ `simpleeval` tinyint(1) NOT NULL DEFAULT '1',
+ `testname` varchar(64) NOT NULL DEFAULT '',
+ `testenabled` tinyint(1) NOT NULL DEFAULT '0',
+ `lastvalue` varchar(128) NOT NULL DEFAULT '',
+ `testalerts` tinyint(1) NOT NULL DEFAULT '1',
+ PRIMARY KEY (`nstestid`),
+ KEY `nodeid` (`nodeid`)
+) ENGINE=MyISAM AUTO_INCREMENT=43486 DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `fnrecord`
+--
+
+DROP TABLE IF EXISTS `fnrecord`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `fnrecord` (
+ `recordid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `testid` varchar(128) NOT NULL,
+ `alertlevel` int(11) NOT NULL DEFAULT '0',
+ `testvalue` float NOT NULL DEFAULT '0',
+ `recordx` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `nodeid` varchar(64) NOT NULL,
+ PRIMARY KEY (`recordid`),
+ KEY `testid` (`testid`),
+ KEY `recordx` (`recordx`)
+) ENGINE=MyISAM AUTO_INCREMENT=4768889 DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `fnreport`
+--
+
+DROP TABLE IF EXISTS `fnreport`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `fnreport` (
+ `reportid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `reportname` varchar(128) NOT NULL DEFAULT '',
+ `reporttests` text NOT NULL,
+ PRIMARY KEY (`reportid`)
+) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `fnrssfeed`
+--
+
+DROP TABLE IF EXISTS `fnrssfeed`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `fnrssfeed` (
+ `feedid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `feedkey` varchar(254) NOT NULL,
+ `feedname` varchar(254) NOT NULL,
+ `feedtype` varchar(32) NOT NULL,
+ `typeopt` varchar(254) NOT NULL,
+ `feedrange` varchar(32) NOT NULL,
+ `rangeopt` varchar(254) NOT NULL,
+ PRIMARY KEY (`feedid`)
+) ENGINE=MyISAM AUTO_INCREMENT=12 DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `fnscheditem`
+--
+
+DROP TABLE IF EXISTS `fnscheditem`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `fnscheditem` (
+ `scheditemid` bigint(20) NOT NULL AUTO_INCREMENT,
+ `scheduleid` bigint(20) NOT NULL DEFAULT '0',
+ `dayofweek` varchar(8) NOT NULL DEFAULT '',
+ `dayofmonth` int(11) NOT NULL DEFAULT '0',
+ `monthofyear` int(11) NOT NULL DEFAULT '0',
+ `year` int(11) NOT NULL DEFAULT '0',
+ `starthour` int(11) NOT NULL DEFAULT '0',
+ `startmin` int(11) NOT NULL DEFAULT '0',
+ `finishhour` int(11) NOT NULL DEFAULT '23',
+ `finishmin` int(11) NOT NULL DEFAULT '59',
+ PRIMARY KEY (`scheditemid`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `fnschedule`
+--
+
+DROP TABLE IF EXISTS `fnschedule`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `fnschedule` (
+ `scheduleid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `schedulename` varchar(128) NOT NULL DEFAULT '',
+ `defaultaction` tinyint(1) NOT NULL DEFAULT '1',
+ PRIMARY KEY (`scheduleid`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `fnsession`
+--
+
+DROP TABLE IF EXISTS `fnsession`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `fnsession` (
+ `sessionid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `sessionkey` varchar(128) NOT NULL,
+ `ipaddress` varchar(128) NOT NULL,
+ `username` varchar(64) NOT NULL,
+ `startx` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `updatex` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `userlevel` int(11) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`sessionid`)
+) ENGINE=MyISAM AUTO_INCREMENT=154 DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `fntestrun`
+--
+
+DROP TABLE IF EXISTS `fntestrun`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `fntestrun` (
+ `trid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `startx` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `finishx` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `routput` text NOT NULL,
+ `fnode` varchar(64) NOT NULL,
+ PRIMARY KEY (`trid`),
+ KEY `finishx` (`finishx`),
+ KEY `fnode` (`fnode`)
+) ENGINE=MyISAM AUTO_INCREMENT=3921917 DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `fnuser`
+--
+
+DROP TABLE IF EXISTS `fnuser`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `fnuser` (
+ `username` varchar(64) NOT NULL,
+ `password` varchar(64) NOT NULL,
+ `realname` varchar(128) NOT NULL,
+ `userlevel` int(11) NOT NULL DEFAULT '1',
+ PRIMARY KEY (`username`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `fnview`
+--
+
+DROP TABLE IF EXISTS `fnview`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `fnview` (
+ `viewid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `vtitle` varchar(128) NOT NULL DEFAULT '',
+ `vstyle` varchar(32) NOT NULL DEFAULT '',
+ `vpublic` tinyint(1) NOT NULL DEFAULT '0',
+ `vclick` varchar(32) NOT NULL DEFAULT '',
+ `vrefresh` int(11) NOT NULL DEFAULT '0',
+ `vlinkv` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `vcolumns` smallint(6) NOT NULL DEFAULT '0',
+ `vcolon` tinyint(1) NOT NULL DEFAULT '1',
+ `vdashes` tinyint(1) NOT NULL DEFAULT '1',
+ `vtimeago` tinyint(1) NOT NULL DEFAULT '1',
+ PRIMARY KEY (`viewid`)
+) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `fnviewitem`
+--
+
+DROP TABLE IF EXISTS `fnviewitem`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `fnviewitem` (
+ `viewitemid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `viewid` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `itype` varchar(128) NOT NULL DEFAULT '',
+ `ioption` varchar(250) NOT NULL DEFAULT '',
+ `icolour` tinyint(1) NOT NULL DEFAULT '1',
+ `itextstatus` tinyint(1) NOT NULL DEFAULT '0',
+ `idetail` smallint(5) unsigned NOT NULL DEFAULT '0',
+ `iweight` int(10) unsigned NOT NULL DEFAULT '0',
+ `isize` smallint(6) NOT NULL DEFAULT '0',
+ `igraphic` smallint(6) NOT NULL DEFAULT '0',
+ `iname` varchar(64) NOT NULL DEFAULT '',
+ PRIMARY KEY (`viewitemid`),
+ KEY `viewid` (`viewid`)
+) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
+
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
+
+-- Dump completed on 2016-02-06 20:35:41
diff --git a/sql/latest/schema.sql b/sql/latest/schema.sql
new file mode 100755
index 0000000..f0d005f
--- /dev/null
+++ b/sql/latest/schema.sql
@@ -0,0 +1,473 @@
+-- FreeNATS freenats-1.14.2a Schema
+-- No DROP TABLES - suitable for upgrade
+-- MySQL dump 10.14 Distrib 5.5.43-MariaDB, for Linux (x86_64)
+--
+-- Host: localhost Database: freenats
+-- ------------------------------------------------------
+-- Server version 5.5.43-MariaDB
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES utf8 */;
+/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
+/*!40103 SET TIME_ZONE='+00:00' */;
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
+
+--
+-- Table structure for table `fnalert`
+--
+
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `fnalert` (
+ `alertid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `nodeid` varchar(64) NOT NULL,
+ `alertlevel` int(11) NOT NULL DEFAULT '0',
+ `openedx` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `closedx` bigint(20) unsigned NOT NULL DEFAULT '0',
+ PRIMARY KEY (`alertid`),
+ KEY `nodeid` (`nodeid`),
+ KEY `closedx` (`closedx`)
+) ENGINE=MyISAM AUTO_INCREMENT=2298 DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `fnalertaction`
+--
+
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `fnalertaction` (
+ `aaid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `atype` varchar(32) NOT NULL,
+ `efrom` varchar(250) NOT NULL,
+ `etolist` text NOT NULL,
+ `esubject` int(11) NOT NULL DEFAULT '0',
+ `etype` int(11) NOT NULL DEFAULT '0',
+ `awarnings` tinyint(1) NOT NULL DEFAULT '0',
+ `adecrease` tinyint(1) NOT NULL DEFAULT '0',
+ `mdata` text NOT NULL,
+ `aname` varchar(120) NOT NULL,
+ `ctrdate` varchar(8) NOT NULL,
+ `ctrlimit` int(10) unsigned NOT NULL DEFAULT '0',
+ `ctrtoday` int(10) unsigned NOT NULL DEFAULT '0',
+ `scheduleid` bigint(20) unsigned NOT NULL DEFAULT '0',
+ PRIMARY KEY (`aaid`)
+) ENGINE=MyISAM AUTO_INCREMENT=9 DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `fnalertlog`
+--
+
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `fnalertlog` (
+ `alid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `alertid` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `postedx` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `logentry` varchar(250) NOT NULL,
+ PRIMARY KEY (`alid`),
+ KEY `alertid` (`alertid`)
+) ENGINE=MyISAM AUTO_INCREMENT=49727 DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `fnconfig`
+--
+
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `fnconfig` (
+ `fnc_var` varchar(64) NOT NULL,
+ `fnc_val` varchar(64) NOT NULL,
+ PRIMARY KEY (`fnc_var`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `fneval`
+--
+
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `fneval` (
+ `evalid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `testid` varchar(128) NOT NULL,
+ `weight` int(11) NOT NULL DEFAULT '0',
+ `eoperator` varchar(32) NOT NULL,
+ `evalue` varchar(128) NOT NULL,
+ `eoutcome` int(11) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`evalid`),
+ KEY `testid` (`testid`)
+) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `fngroup`
+--
+
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `fngroup` (
+ `groupid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `groupname` varchar(128) NOT NULL,
+ `groupdesc` varchar(250) NOT NULL,
+ `groupicon` varchar(64) NOT NULL,
+ `weight` int(10) unsigned NOT NULL DEFAULT '0',
+ PRIMARY KEY (`groupid`)
+) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `fngrouplink`
+--
+
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `fngrouplink` (
+ `glid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `groupid` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `nodeid` varchar(64) NOT NULL,
+ PRIMARY KEY (`glid`),
+ KEY `groupid` (`groupid`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `fnlocaltest`
+--
+
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `fnlocaltest` (
+ `localtestid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `nodeid` varchar(64) NOT NULL,
+ `alertlevel` int(11) NOT NULL DEFAULT '-1',
+ `lastrunx` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `testtype` varchar(128) NOT NULL,
+ `testparam` varchar(250) DEFAULT NULL,
+ `testrecord` tinyint(1) NOT NULL DEFAULT '0',
+ `simpleeval` tinyint(1) NOT NULL DEFAULT '1',
+ `testname` varchar(64) NOT NULL,
+ `attempts` int(11) NOT NULL DEFAULT '0',
+ `timeout` int(11) NOT NULL DEFAULT '0',
+ `testenabled` tinyint(1) NOT NULL DEFAULT '1',
+ `testparam1` varchar(250) NOT NULL,
+ `testparam2` varchar(250) NOT NULL,
+ `testparam3` varchar(250) NOT NULL,
+ `testparam4` varchar(250) NOT NULL,
+ `testparam5` varchar(250) NOT NULL,
+ `testparam6` varchar(250) NOT NULL,
+ `testparam7` varchar(250) NOT NULL,
+ `testparam8` varchar(250) NOT NULL,
+ `testparam9` varchar(250) NOT NULL,
+ `lastvalue` float NOT NULL DEFAULT '0',
+ `testinterval` int(10) unsigned NOT NULL DEFAULT '0',
+ `nextrunx` bigint(20) unsigned NOT NULL DEFAULT '0',
+ PRIMARY KEY (`localtestid`),
+ KEY `nodeid` (`nodeid`)
+) ENGINE=MyISAM AUTO_INCREMENT=26 DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `fnlog`
+--
+
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `fnlog` (
+ `logid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `postedx` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `modid` varchar(32) NOT NULL,
+ `catid` varchar(32) NOT NULL,
+ `username` varchar(64) NOT NULL,
+ `loglevel` int(11) NOT NULL DEFAULT '1',
+ `logevent` varchar(250) NOT NULL,
+ PRIMARY KEY (`logid`)
+) ENGINE=MyISAM AUTO_INCREMENT=96829571 DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `fnnalink`
+--
+
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `fnnalink` (
+ `nalid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `nodeid` varchar(64) NOT NULL,
+ `aaid` bigint(20) unsigned NOT NULL DEFAULT '0',
+ PRIMARY KEY (`nalid`)
+) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `fnnode`
+--
+
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `fnnode` (
+ `nodeid` varchar(64) NOT NULL,
+ `nodename` varchar(128) NOT NULL,
+ `nodedesc` varchar(254) NOT NULL,
+ `hostname` varchar(254) NOT NULL,
+ `nodeenabled` tinyint(1) NOT NULL DEFAULT '0',
+ `pingtest` tinyint(1) NOT NULL DEFAULT '0',
+ `pingfatal` tinyint(1) NOT NULL DEFAULT '0',
+ `alertlevel` int(11) NOT NULL DEFAULT '-1',
+ `nodeicon` varchar(64) NOT NULL,
+ `weight` int(10) unsigned NOT NULL DEFAULT '0',
+ `nodealert` tinyint(1) NOT NULL DEFAULT '1',
+ `scheduleid` bigint(20) NOT NULL DEFAULT '0',
+ `lastrunx` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `testinterval` int(10) unsigned NOT NULL DEFAULT '5',
+ `nextrunx` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `nsenabled` tinyint(1) NOT NULL DEFAULT '0',
+ `nsurl` varchar(254) NOT NULL,
+ `nskey` varchar(128) NOT NULL,
+ `nspullenabled` tinyint(1) NOT NULL DEFAULT '0',
+ `nspushenabled` tinyint(1) NOT NULL DEFAULT '0',
+ `nspuship` varchar(128) NOT NULL,
+ `nsinterval` int(10) unsigned NOT NULL DEFAULT '15',
+ `nslastx` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `nsnextx` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `nspullalert` tinyint(1) NOT NULL DEFAULT '0',
+ `nsfreshpush` tinyint(1) NOT NULL DEFAULT '0',
+ `masterid` varchar(64) NOT NULL,
+ `masterjustping` tinyint(1) NOT NULL DEFAULT '1',
+ `ulink0` tinyint(1) NOT NULL DEFAULT '0',
+ `ulink0_title` varchar(254) NOT NULL DEFAULT 'VNC',
+ `ulink0_url` varchar(254) NOT NULL DEFAULT 'http://{HOSTNAME}:5800/',
+ `ulink1` tinyint(1) NOT NULL DEFAULT '0',
+ `ulink1_title` varchar(254) NOT NULL DEFAULT 'SSH',
+ `ulink1_url` varchar(254) NOT NULL DEFAULT 'ssh://{HOSTNAME}',
+ `ulink2` tinyint(1) NOT NULL DEFAULT '0',
+ `ulink2_title` varchar(254) NOT NULL DEFAULT 'Web',
+ `ulink2_url` varchar(254) NOT NULL DEFAULT 'http://{HOSTNAME}',
+ PRIMARY KEY (`nodeid`),
+ KEY `masterid` (`masterid`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `fnnstest`
+--
+
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `fnnstest` (
+ `nstestid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `nodeid` varchar(64) NOT NULL DEFAULT '',
+ `alertlevel` int(11) NOT NULL DEFAULT '-1',
+ `lastrunx` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `testtype` varchar(128) NOT NULL DEFAULT '',
+ `testdesc` varchar(250) DEFAULT NULL,
+ `testrecord` tinyint(1) NOT NULL DEFAULT '0',
+ `simpleeval` tinyint(1) NOT NULL DEFAULT '1',
+ `testname` varchar(64) NOT NULL DEFAULT '',
+ `testenabled` tinyint(1) NOT NULL DEFAULT '0',
+ `lastvalue` varchar(128) NOT NULL DEFAULT '',
+ `testalerts` tinyint(1) NOT NULL DEFAULT '1',
+ PRIMARY KEY (`nstestid`),
+ KEY `nodeid` (`nodeid`)
+) ENGINE=MyISAM AUTO_INCREMENT=43486 DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `fnrecord`
+--
+
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `fnrecord` (
+ `recordid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `testid` varchar(128) NOT NULL,
+ `alertlevel` int(11) NOT NULL DEFAULT '0',
+ `testvalue` float NOT NULL DEFAULT '0',
+ `recordx` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `nodeid` varchar(64) NOT NULL,
+ PRIMARY KEY (`recordid`),
+ KEY `testid` (`testid`),
+ KEY `recordx` (`recordx`)
+) ENGINE=MyISAM AUTO_INCREMENT=4768889 DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `fnreport`
+--
+
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `fnreport` (
+ `reportid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `reportname` varchar(128) NOT NULL DEFAULT '',
+ `reporttests` text NOT NULL,
+ PRIMARY KEY (`reportid`)
+) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `fnrssfeed`
+--
+
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `fnrssfeed` (
+ `feedid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `feedkey` varchar(254) NOT NULL,
+ `feedname` varchar(254) NOT NULL,
+ `feedtype` varchar(32) NOT NULL,
+ `typeopt` varchar(254) NOT NULL,
+ `feedrange` varchar(32) NOT NULL,
+ `rangeopt` varchar(254) NOT NULL,
+ PRIMARY KEY (`feedid`)
+) ENGINE=MyISAM AUTO_INCREMENT=12 DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `fnscheditem`
+--
+
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `fnscheditem` (
+ `scheditemid` bigint(20) NOT NULL AUTO_INCREMENT,
+ `scheduleid` bigint(20) NOT NULL DEFAULT '0',
+ `dayofweek` varchar(8) NOT NULL DEFAULT '',
+ `dayofmonth` int(11) NOT NULL DEFAULT '0',
+ `monthofyear` int(11) NOT NULL DEFAULT '0',
+ `year` int(11) NOT NULL DEFAULT '0',
+ `starthour` int(11) NOT NULL DEFAULT '0',
+ `startmin` int(11) NOT NULL DEFAULT '0',
+ `finishhour` int(11) NOT NULL DEFAULT '23',
+ `finishmin` int(11) NOT NULL DEFAULT '59',
+ PRIMARY KEY (`scheditemid`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `fnschedule`
+--
+
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `fnschedule` (
+ `scheduleid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `schedulename` varchar(128) NOT NULL DEFAULT '',
+ `defaultaction` tinyint(1) NOT NULL DEFAULT '1',
+ PRIMARY KEY (`scheduleid`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `fnsession`
+--
+
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `fnsession` (
+ `sessionid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `sessionkey` varchar(128) NOT NULL,
+ `ipaddress` varchar(128) NOT NULL,
+ `username` varchar(64) NOT NULL,
+ `startx` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `updatex` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `userlevel` int(11) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`sessionid`)
+) ENGINE=MyISAM AUTO_INCREMENT=154 DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `fntestrun`
+--
+
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `fntestrun` (
+ `trid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `startx` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `finishx` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `routput` text NOT NULL,
+ `fnode` varchar(64) NOT NULL,
+ PRIMARY KEY (`trid`),
+ KEY `finishx` (`finishx`),
+ KEY `fnode` (`fnode`)
+) ENGINE=MyISAM AUTO_INCREMENT=3921917 DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `fnuser`
+--
+
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `fnuser` (
+ `username` varchar(64) NOT NULL,
+ `password` varchar(64) NOT NULL,
+ `realname` varchar(128) NOT NULL,
+ `userlevel` int(11) NOT NULL DEFAULT '1',
+ PRIMARY KEY (`username`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `fnview`
+--
+
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `fnview` (
+ `viewid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `vtitle` varchar(128) NOT NULL DEFAULT '',
+ `vstyle` varchar(32) NOT NULL DEFAULT '',
+ `vpublic` tinyint(1) NOT NULL DEFAULT '0',
+ `vclick` varchar(32) NOT NULL DEFAULT '',
+ `vrefresh` int(11) NOT NULL DEFAULT '0',
+ `vlinkv` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `vcolumns` smallint(6) NOT NULL DEFAULT '0',
+ `vcolon` tinyint(1) NOT NULL DEFAULT '1',
+ `vdashes` tinyint(1) NOT NULL DEFAULT '1',
+ `vtimeago` tinyint(1) NOT NULL DEFAULT '1',
+ PRIMARY KEY (`viewid`)
+) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Table structure for table `fnviewitem`
+--
+
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `fnviewitem` (
+ `viewitemid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `viewid` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `itype` varchar(128) NOT NULL DEFAULT '',
+ `ioption` varchar(250) NOT NULL DEFAULT '',
+ `icolour` tinyint(1) NOT NULL DEFAULT '1',
+ `itextstatus` tinyint(1) NOT NULL DEFAULT '0',
+ `idetail` smallint(5) unsigned NOT NULL DEFAULT '0',
+ `iweight` int(10) unsigned NOT NULL DEFAULT '0',
+ `isize` smallint(6) NOT NULL DEFAULT '0',
+ `igraphic` smallint(6) NOT NULL DEFAULT '0',
+ `iname` varchar(64) NOT NULL DEFAULT '',
+ PRIMARY KEY (`viewitemid`),
+ KEY `viewid` (`viewid`)
+) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;
+/*!40101 SET character_set_client = @saved_cs_client */;
+/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
+
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
+
+-- Dump completed on 2016-02-06 20:35:41
diff --git a/sql/latest/schema.upgrade.sql b/sql/latest/schema.upgrade.sql
new file mode 100755
index 0000000..b358df2
--- /dev/null
+++ b/sql/latest/schema.upgrade.sql
@@ -0,0 +1,486 @@
+-- FreeNATS freenats-1.14.2a Schema
+-- Experimental Upgrade SQL - run after schema.sql (not drop!)
+-- Both will generate many many errors - run with --force, ignore errors
+-- myrug -- PurplePixie Systems
+-- http://www.purplepixie.org/myrug
+--
+-- SHOW TABLES
+-- Table: fnalert
+-- DESCRIBE fnalert
+ALTER TABLE `fnalert` CHANGE `alertid` `alertid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fnalert` ADD `alertid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fnalert` ADD PRIMARY KEY( `alertid` );
+ALTER TABLE `fnalert` CHANGE `nodeid` `nodeid` varchar(64) NOT NULL;
+ALTER TABLE `fnalert` ADD `nodeid` varchar(64) NOT NULL;
+CREATE INDEX `nodeid` ON `fnalert` ( `nodeid` );
+ALTER TABLE `fnalert` CHANGE `alertlevel` `alertlevel` int(11) NOT NULL DEFAULT '0';
+ALTER TABLE `fnalert` ADD `alertlevel` int(11) NOT NULL DEFAULT '0';
+ALTER TABLE `fnalert` CHANGE `openedx` `openedx` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnalert` ADD `openedx` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnalert` CHANGE `closedx` `closedx` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnalert` ADD `closedx` bigint(20) unsigned NOT NULL DEFAULT '0';
+CREATE INDEX `closedx` ON `fnalert` ( `closedx` );
+--
+-- Table: fnalertaction
+-- DESCRIBE fnalertaction
+ALTER TABLE `fnalertaction` CHANGE `aaid` `aaid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fnalertaction` ADD `aaid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fnalertaction` ADD PRIMARY KEY( `aaid` );
+ALTER TABLE `fnalertaction` CHANGE `atype` `atype` varchar(32) NOT NULL;
+ALTER TABLE `fnalertaction` ADD `atype` varchar(32) NOT NULL;
+ALTER TABLE `fnalertaction` CHANGE `efrom` `efrom` varchar(250) NOT NULL;
+ALTER TABLE `fnalertaction` ADD `efrom` varchar(250) NOT NULL;
+ALTER TABLE `fnalertaction` CHANGE `etolist` `etolist` text NOT NULL;
+ALTER TABLE `fnalertaction` ADD `etolist` text NOT NULL;
+ALTER TABLE `fnalertaction` CHANGE `esubject` `esubject` int(11) NOT NULL DEFAULT '0';
+ALTER TABLE `fnalertaction` ADD `esubject` int(11) NOT NULL DEFAULT '0';
+ALTER TABLE `fnalertaction` CHANGE `etype` `etype` int(11) NOT NULL DEFAULT '0';
+ALTER TABLE `fnalertaction` ADD `etype` int(11) NOT NULL DEFAULT '0';
+ALTER TABLE `fnalertaction` CHANGE `awarnings` `awarnings` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnalertaction` ADD `awarnings` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnalertaction` CHANGE `adecrease` `adecrease` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnalertaction` ADD `adecrease` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnalertaction` CHANGE `mdata` `mdata` text NOT NULL;
+ALTER TABLE `fnalertaction` ADD `mdata` text NOT NULL;
+ALTER TABLE `fnalertaction` CHANGE `aname` `aname` varchar(120) NOT NULL;
+ALTER TABLE `fnalertaction` ADD `aname` varchar(120) NOT NULL;
+ALTER TABLE `fnalertaction` CHANGE `ctrdate` `ctrdate` varchar(8) NOT NULL;
+ALTER TABLE `fnalertaction` ADD `ctrdate` varchar(8) NOT NULL;
+ALTER TABLE `fnalertaction` CHANGE `ctrlimit` `ctrlimit` int(10) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnalertaction` ADD `ctrlimit` int(10) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnalertaction` CHANGE `ctrtoday` `ctrtoday` int(10) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnalertaction` ADD `ctrtoday` int(10) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnalertaction` CHANGE `scheduleid` `scheduleid` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnalertaction` ADD `scheduleid` bigint(20) unsigned NOT NULL DEFAULT '0';
+--
+-- Table: fnalertlog
+-- DESCRIBE fnalertlog
+ALTER TABLE `fnalertlog` CHANGE `alid` `alid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fnalertlog` ADD `alid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fnalertlog` ADD PRIMARY KEY( `alid` );
+ALTER TABLE `fnalertlog` CHANGE `alertid` `alertid` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnalertlog` ADD `alertid` bigint(20) unsigned NOT NULL DEFAULT '0';
+CREATE INDEX `alertid` ON `fnalertlog` ( `alertid` );
+ALTER TABLE `fnalertlog` CHANGE `postedx` `postedx` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnalertlog` ADD `postedx` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnalertlog` CHANGE `logentry` `logentry` varchar(250) NOT NULL;
+ALTER TABLE `fnalertlog` ADD `logentry` varchar(250) NOT NULL;
+--
+-- Table: fnconfig
+-- DESCRIBE fnconfig
+ALTER TABLE `fnconfig` CHANGE `fnc_var` `fnc_var` varchar(64) NOT NULL;
+ALTER TABLE `fnconfig` ADD `fnc_var` varchar(64) NOT NULL;
+ALTER TABLE `fnconfig` ADD PRIMARY KEY( `fnc_var` );
+ALTER TABLE `fnconfig` CHANGE `fnc_val` `fnc_val` varchar(64) NOT NULL;
+ALTER TABLE `fnconfig` ADD `fnc_val` varchar(64) NOT NULL;
+--
+-- Table: fneval
+-- DESCRIBE fneval
+ALTER TABLE `fneval` CHANGE `evalid` `evalid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fneval` ADD `evalid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fneval` ADD PRIMARY KEY( `evalid` );
+ALTER TABLE `fneval` CHANGE `testid` `testid` varchar(128) NOT NULL;
+ALTER TABLE `fneval` ADD `testid` varchar(128) NOT NULL;
+CREATE INDEX `testid` ON `fneval` ( `testid` );
+ALTER TABLE `fneval` CHANGE `weight` `weight` int(11) NOT NULL DEFAULT '0';
+ALTER TABLE `fneval` ADD `weight` int(11) NOT NULL DEFAULT '0';
+ALTER TABLE `fneval` CHANGE `eoperator` `eoperator` varchar(32) NOT NULL;
+ALTER TABLE `fneval` ADD `eoperator` varchar(32) NOT NULL;
+ALTER TABLE `fneval` CHANGE `evalue` `evalue` varchar(128) NOT NULL;
+ALTER TABLE `fneval` ADD `evalue` varchar(128) NOT NULL;
+ALTER TABLE `fneval` CHANGE `eoutcome` `eoutcome` int(11) NOT NULL DEFAULT '0';
+ALTER TABLE `fneval` ADD `eoutcome` int(11) NOT NULL DEFAULT '0';
+--
+-- Table: fngroup
+-- DESCRIBE fngroup
+ALTER TABLE `fngroup` CHANGE `groupid` `groupid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fngroup` ADD `groupid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fngroup` ADD PRIMARY KEY( `groupid` );
+ALTER TABLE `fngroup` CHANGE `groupname` `groupname` varchar(128) NOT NULL;
+ALTER TABLE `fngroup` ADD `groupname` varchar(128) NOT NULL;
+ALTER TABLE `fngroup` CHANGE `groupdesc` `groupdesc` varchar(250) NOT NULL;
+ALTER TABLE `fngroup` ADD `groupdesc` varchar(250) NOT NULL;
+ALTER TABLE `fngroup` CHANGE `groupicon` `groupicon` varchar(64) NOT NULL;
+ALTER TABLE `fngroup` ADD `groupicon` varchar(64) NOT NULL;
+ALTER TABLE `fngroup` CHANGE `weight` `weight` int(10) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fngroup` ADD `weight` int(10) unsigned NOT NULL DEFAULT '0';
+--
+-- Table: fngrouplink
+-- DESCRIBE fngrouplink
+ALTER TABLE `fngrouplink` CHANGE `glid` `glid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fngrouplink` ADD `glid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fngrouplink` ADD PRIMARY KEY( `glid` );
+ALTER TABLE `fngrouplink` CHANGE `groupid` `groupid` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fngrouplink` ADD `groupid` bigint(20) unsigned NOT NULL DEFAULT '0';
+CREATE INDEX `groupid` ON `fngrouplink` ( `groupid` );
+ALTER TABLE `fngrouplink` CHANGE `nodeid` `nodeid` varchar(64) NOT NULL;
+ALTER TABLE `fngrouplink` ADD `nodeid` varchar(64) NOT NULL;
+--
+-- Table: fnlocaltest
+-- DESCRIBE fnlocaltest
+ALTER TABLE `fnlocaltest` CHANGE `localtestid` `localtestid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fnlocaltest` ADD `localtestid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fnlocaltest` ADD PRIMARY KEY( `localtestid` );
+ALTER TABLE `fnlocaltest` CHANGE `nodeid` `nodeid` varchar(64) NOT NULL;
+ALTER TABLE `fnlocaltest` ADD `nodeid` varchar(64) NOT NULL;
+CREATE INDEX `nodeid` ON `fnlocaltest` ( `nodeid` );
+ALTER TABLE `fnlocaltest` CHANGE `alertlevel` `alertlevel` int(11) NOT NULL DEFAULT '-1';
+ALTER TABLE `fnlocaltest` ADD `alertlevel` int(11) NOT NULL DEFAULT '-1';
+ALTER TABLE `fnlocaltest` CHANGE `lastrunx` `lastrunx` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnlocaltest` ADD `lastrunx` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnlocaltest` CHANGE `testtype` `testtype` varchar(128) NOT NULL;
+ALTER TABLE `fnlocaltest` ADD `testtype` varchar(128) NOT NULL;
+ALTER TABLE `fnlocaltest` CHANGE `testparam` `testparam` varchar(250);
+ALTER TABLE `fnlocaltest` ADD `testparam` varchar(250);
+ALTER TABLE `fnlocaltest` CHANGE `testrecord` `testrecord` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnlocaltest` ADD `testrecord` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnlocaltest` CHANGE `simpleeval` `simpleeval` tinyint(1) NOT NULL DEFAULT '1';
+ALTER TABLE `fnlocaltest` ADD `simpleeval` tinyint(1) NOT NULL DEFAULT '1';
+ALTER TABLE `fnlocaltest` CHANGE `testname` `testname` varchar(64) NOT NULL;
+ALTER TABLE `fnlocaltest` ADD `testname` varchar(64) NOT NULL;
+ALTER TABLE `fnlocaltest` CHANGE `attempts` `attempts` int(11) NOT NULL DEFAULT '0';
+ALTER TABLE `fnlocaltest` ADD `attempts` int(11) NOT NULL DEFAULT '0';
+ALTER TABLE `fnlocaltest` CHANGE `timeout` `timeout` int(11) NOT NULL DEFAULT '0';
+ALTER TABLE `fnlocaltest` ADD `timeout` int(11) NOT NULL DEFAULT '0';
+ALTER TABLE `fnlocaltest` CHANGE `testenabled` `testenabled` tinyint(1) NOT NULL DEFAULT '1';
+ALTER TABLE `fnlocaltest` ADD `testenabled` tinyint(1) NOT NULL DEFAULT '1';
+ALTER TABLE `fnlocaltest` CHANGE `testparam1` `testparam1` varchar(250) NOT NULL;
+ALTER TABLE `fnlocaltest` ADD `testparam1` varchar(250) NOT NULL;
+ALTER TABLE `fnlocaltest` CHANGE `testparam2` `testparam2` varchar(250) NOT NULL;
+ALTER TABLE `fnlocaltest` ADD `testparam2` varchar(250) NOT NULL;
+ALTER TABLE `fnlocaltest` CHANGE `testparam3` `testparam3` varchar(250) NOT NULL;
+ALTER TABLE `fnlocaltest` ADD `testparam3` varchar(250) NOT NULL;
+ALTER TABLE `fnlocaltest` CHANGE `testparam4` `testparam4` varchar(250) NOT NULL;
+ALTER TABLE `fnlocaltest` ADD `testparam4` varchar(250) NOT NULL;
+ALTER TABLE `fnlocaltest` CHANGE `testparam5` `testparam5` varchar(250) NOT NULL;
+ALTER TABLE `fnlocaltest` ADD `testparam5` varchar(250) NOT NULL;
+ALTER TABLE `fnlocaltest` CHANGE `testparam6` `testparam6` varchar(250) NOT NULL;
+ALTER TABLE `fnlocaltest` ADD `testparam6` varchar(250) NOT NULL;
+ALTER TABLE `fnlocaltest` CHANGE `testparam7` `testparam7` varchar(250) NOT NULL;
+ALTER TABLE `fnlocaltest` ADD `testparam7` varchar(250) NOT NULL;
+ALTER TABLE `fnlocaltest` CHANGE `testparam8` `testparam8` varchar(250) NOT NULL;
+ALTER TABLE `fnlocaltest` ADD `testparam8` varchar(250) NOT NULL;
+ALTER TABLE `fnlocaltest` CHANGE `testparam9` `testparam9` varchar(250) NOT NULL;
+ALTER TABLE `fnlocaltest` ADD `testparam9` varchar(250) NOT NULL;
+ALTER TABLE `fnlocaltest` CHANGE `lastvalue` `lastvalue` float NOT NULL DEFAULT '0';
+ALTER TABLE `fnlocaltest` ADD `lastvalue` float NOT NULL DEFAULT '0';
+ALTER TABLE `fnlocaltest` CHANGE `testinterval` `testinterval` int(10) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnlocaltest` ADD `testinterval` int(10) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnlocaltest` CHANGE `nextrunx` `nextrunx` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnlocaltest` ADD `nextrunx` bigint(20) unsigned NOT NULL DEFAULT '0';
+--
+-- Table: fnlog
+-- DESCRIBE fnlog
+ALTER TABLE `fnlog` CHANGE `logid` `logid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fnlog` ADD `logid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fnlog` ADD PRIMARY KEY( `logid` );
+ALTER TABLE `fnlog` CHANGE `postedx` `postedx` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnlog` ADD `postedx` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnlog` CHANGE `modid` `modid` varchar(32) NOT NULL;
+ALTER TABLE `fnlog` ADD `modid` varchar(32) NOT NULL;
+ALTER TABLE `fnlog` CHANGE `catid` `catid` varchar(32) NOT NULL;
+ALTER TABLE `fnlog` ADD `catid` varchar(32) NOT NULL;
+ALTER TABLE `fnlog` CHANGE `username` `username` varchar(64) NOT NULL;
+ALTER TABLE `fnlog` ADD `username` varchar(64) NOT NULL;
+ALTER TABLE `fnlog` CHANGE `loglevel` `loglevel` int(11) NOT NULL DEFAULT '1';
+ALTER TABLE `fnlog` ADD `loglevel` int(11) NOT NULL DEFAULT '1';
+ALTER TABLE `fnlog` CHANGE `logevent` `logevent` varchar(250) NOT NULL;
+ALTER TABLE `fnlog` ADD `logevent` varchar(250) NOT NULL;
+--
+-- Table: fnnalink
+-- DESCRIBE fnnalink
+ALTER TABLE `fnnalink` CHANGE `nalid` `nalid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fnnalink` ADD `nalid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fnnalink` ADD PRIMARY KEY( `nalid` );
+ALTER TABLE `fnnalink` CHANGE `nodeid` `nodeid` varchar(64) NOT NULL;
+ALTER TABLE `fnnalink` ADD `nodeid` varchar(64) NOT NULL;
+ALTER TABLE `fnnalink` CHANGE `aaid` `aaid` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnnalink` ADD `aaid` bigint(20) unsigned NOT NULL DEFAULT '0';
+--
+-- Table: fnnode
+-- DESCRIBE fnnode
+ALTER TABLE `fnnode` CHANGE `nodeid` `nodeid` varchar(64) NOT NULL;
+ALTER TABLE `fnnode` ADD `nodeid` varchar(64) NOT NULL;
+ALTER TABLE `fnnode` ADD PRIMARY KEY( `nodeid` );
+ALTER TABLE `fnnode` CHANGE `nodename` `nodename` varchar(128) NOT NULL;
+ALTER TABLE `fnnode` ADD `nodename` varchar(128) NOT NULL;
+ALTER TABLE `fnnode` CHANGE `nodedesc` `nodedesc` varchar(254) NOT NULL;
+ALTER TABLE `fnnode` ADD `nodedesc` varchar(254) NOT NULL;
+ALTER TABLE `fnnode` CHANGE `hostname` `hostname` varchar(254) NOT NULL;
+ALTER TABLE `fnnode` ADD `hostname` varchar(254) NOT NULL;
+ALTER TABLE `fnnode` CHANGE `nodeenabled` `nodeenabled` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnnode` ADD `nodeenabled` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnnode` CHANGE `pingtest` `pingtest` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnnode` ADD `pingtest` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnnode` CHANGE `pingfatal` `pingfatal` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnnode` ADD `pingfatal` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnnode` CHANGE `alertlevel` `alertlevel` int(11) NOT NULL DEFAULT '-1';
+ALTER TABLE `fnnode` ADD `alertlevel` int(11) NOT NULL DEFAULT '-1';
+ALTER TABLE `fnnode` CHANGE `nodeicon` `nodeicon` varchar(64) NOT NULL;
+ALTER TABLE `fnnode` ADD `nodeicon` varchar(64) NOT NULL;
+ALTER TABLE `fnnode` CHANGE `weight` `weight` int(10) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnnode` ADD `weight` int(10) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnnode` CHANGE `nodealert` `nodealert` tinyint(1) NOT NULL DEFAULT '1';
+ALTER TABLE `fnnode` ADD `nodealert` tinyint(1) NOT NULL DEFAULT '1';
+ALTER TABLE `fnnode` CHANGE `scheduleid` `scheduleid` bigint(20) NOT NULL DEFAULT '0';
+ALTER TABLE `fnnode` ADD `scheduleid` bigint(20) NOT NULL DEFAULT '0';
+ALTER TABLE `fnnode` CHANGE `lastrunx` `lastrunx` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnnode` ADD `lastrunx` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnnode` CHANGE `testinterval` `testinterval` int(10) unsigned NOT NULL DEFAULT '5';
+ALTER TABLE `fnnode` ADD `testinterval` int(10) unsigned NOT NULL DEFAULT '5';
+ALTER TABLE `fnnode` CHANGE `nextrunx` `nextrunx` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnnode` ADD `nextrunx` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnnode` CHANGE `nsenabled` `nsenabled` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnnode` ADD `nsenabled` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnnode` CHANGE `nsurl` `nsurl` varchar(254) NOT NULL;
+ALTER TABLE `fnnode` ADD `nsurl` varchar(254) NOT NULL;
+ALTER TABLE `fnnode` CHANGE `nskey` `nskey` varchar(128) NOT NULL;
+ALTER TABLE `fnnode` ADD `nskey` varchar(128) NOT NULL;
+ALTER TABLE `fnnode` CHANGE `nspullenabled` `nspullenabled` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnnode` ADD `nspullenabled` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnnode` CHANGE `nspushenabled` `nspushenabled` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnnode` ADD `nspushenabled` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnnode` CHANGE `nspuship` `nspuship` varchar(128) NOT NULL;
+ALTER TABLE `fnnode` ADD `nspuship` varchar(128) NOT NULL;
+ALTER TABLE `fnnode` CHANGE `nsinterval` `nsinterval` int(10) unsigned NOT NULL DEFAULT '15';
+ALTER TABLE `fnnode` ADD `nsinterval` int(10) unsigned NOT NULL DEFAULT '15';
+ALTER TABLE `fnnode` CHANGE `nslastx` `nslastx` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnnode` ADD `nslastx` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnnode` CHANGE `nsnextx` `nsnextx` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnnode` ADD `nsnextx` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnnode` CHANGE `nspullalert` `nspullalert` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnnode` ADD `nspullalert` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnnode` CHANGE `nsfreshpush` `nsfreshpush` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnnode` ADD `nsfreshpush` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnnode` CHANGE `masterid` `masterid` varchar(64) NOT NULL;
+ALTER TABLE `fnnode` ADD `masterid` varchar(64) NOT NULL;
+CREATE INDEX `masterid` ON `fnnode` ( `masterid` );
+ALTER TABLE `fnnode` CHANGE `masterjustping` `masterjustping` tinyint(1) NOT NULL DEFAULT '1';
+ALTER TABLE `fnnode` ADD `masterjustping` tinyint(1) NOT NULL DEFAULT '1';
+ALTER TABLE `fnnode` CHANGE `ulink0` `ulink0` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnnode` ADD `ulink0` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnnode` CHANGE `ulink0_title` `ulink0_title` varchar(254) NOT NULL DEFAULT 'VNC';
+ALTER TABLE `fnnode` ADD `ulink0_title` varchar(254) NOT NULL DEFAULT 'VNC';
+ALTER TABLE `fnnode` CHANGE `ulink0_url` `ulink0_url` varchar(254) NOT NULL DEFAULT 'http://{HOSTNAME}:5800/';
+ALTER TABLE `fnnode` ADD `ulink0_url` varchar(254) NOT NULL DEFAULT 'http://{HOSTNAME}:5800/';
+ALTER TABLE `fnnode` CHANGE `ulink1` `ulink1` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnnode` ADD `ulink1` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnnode` CHANGE `ulink1_title` `ulink1_title` varchar(254) NOT NULL DEFAULT 'SSH';
+ALTER TABLE `fnnode` ADD `ulink1_title` varchar(254) NOT NULL DEFAULT 'SSH';
+ALTER TABLE `fnnode` CHANGE `ulink1_url` `ulink1_url` varchar(254) NOT NULL DEFAULT 'ssh://{HOSTNAME}';
+ALTER TABLE `fnnode` ADD `ulink1_url` varchar(254) NOT NULL DEFAULT 'ssh://{HOSTNAME}';
+ALTER TABLE `fnnode` CHANGE `ulink2` `ulink2` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnnode` ADD `ulink2` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnnode` CHANGE `ulink2_title` `ulink2_title` varchar(254) NOT NULL DEFAULT 'Web';
+ALTER TABLE `fnnode` ADD `ulink2_title` varchar(254) NOT NULL DEFAULT 'Web';
+ALTER TABLE `fnnode` CHANGE `ulink2_url` `ulink2_url` varchar(254) NOT NULL DEFAULT 'http://{HOSTNAME}';
+ALTER TABLE `fnnode` ADD `ulink2_url` varchar(254) NOT NULL DEFAULT 'http://{HOSTNAME}';
+--
+-- Table: fnnstest
+-- DESCRIBE fnnstest
+ALTER TABLE `fnnstest` CHANGE `nstestid` `nstestid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fnnstest` ADD `nstestid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fnnstest` ADD PRIMARY KEY( `nstestid` );
+ALTER TABLE `fnnstest` CHANGE `nodeid` `nodeid` varchar(64) NOT NULL;
+ALTER TABLE `fnnstest` ADD `nodeid` varchar(64) NOT NULL;
+CREATE INDEX `nodeid` ON `fnnstest` ( `nodeid` );
+ALTER TABLE `fnnstest` CHANGE `alertlevel` `alertlevel` int(11) NOT NULL DEFAULT '-1';
+ALTER TABLE `fnnstest` ADD `alertlevel` int(11) NOT NULL DEFAULT '-1';
+ALTER TABLE `fnnstest` CHANGE `lastrunx` `lastrunx` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnnstest` ADD `lastrunx` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnnstest` CHANGE `testtype` `testtype` varchar(128) NOT NULL;
+ALTER TABLE `fnnstest` ADD `testtype` varchar(128) NOT NULL;
+ALTER TABLE `fnnstest` CHANGE `testdesc` `testdesc` varchar(250);
+ALTER TABLE `fnnstest` ADD `testdesc` varchar(250);
+ALTER TABLE `fnnstest` CHANGE `testrecord` `testrecord` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnnstest` ADD `testrecord` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnnstest` CHANGE `simpleeval` `simpleeval` tinyint(1) NOT NULL DEFAULT '1';
+ALTER TABLE `fnnstest` ADD `simpleeval` tinyint(1) NOT NULL DEFAULT '1';
+ALTER TABLE `fnnstest` CHANGE `testname` `testname` varchar(64) NOT NULL;
+ALTER TABLE `fnnstest` ADD `testname` varchar(64) NOT NULL;
+ALTER TABLE `fnnstest` CHANGE `testenabled` `testenabled` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnnstest` ADD `testenabled` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnnstest` CHANGE `lastvalue` `lastvalue` varchar(128) NOT NULL;
+ALTER TABLE `fnnstest` ADD `lastvalue` varchar(128) NOT NULL;
+ALTER TABLE `fnnstest` CHANGE `testalerts` `testalerts` tinyint(1) NOT NULL DEFAULT '1';
+ALTER TABLE `fnnstest` ADD `testalerts` tinyint(1) NOT NULL DEFAULT '1';
+--
+-- Table: fnrecord
+-- DESCRIBE fnrecord
+ALTER TABLE `fnrecord` CHANGE `recordid` `recordid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fnrecord` ADD `recordid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fnrecord` ADD PRIMARY KEY( `recordid` );
+ALTER TABLE `fnrecord` CHANGE `testid` `testid` varchar(128) NOT NULL;
+ALTER TABLE `fnrecord` ADD `testid` varchar(128) NOT NULL;
+CREATE INDEX `testid` ON `fnrecord` ( `testid` );
+ALTER TABLE `fnrecord` CHANGE `alertlevel` `alertlevel` int(11) NOT NULL DEFAULT '0';
+ALTER TABLE `fnrecord` ADD `alertlevel` int(11) NOT NULL DEFAULT '0';
+ALTER TABLE `fnrecord` CHANGE `testvalue` `testvalue` float NOT NULL DEFAULT '0';
+ALTER TABLE `fnrecord` ADD `testvalue` float NOT NULL DEFAULT '0';
+ALTER TABLE `fnrecord` CHANGE `recordx` `recordx` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnrecord` ADD `recordx` bigint(20) unsigned NOT NULL DEFAULT '0';
+CREATE INDEX `recordx` ON `fnrecord` ( `recordx` );
+ALTER TABLE `fnrecord` CHANGE `nodeid` `nodeid` varchar(64) NOT NULL;
+ALTER TABLE `fnrecord` ADD `nodeid` varchar(64) NOT NULL;
+--
+-- Table: fnreport
+-- DESCRIBE fnreport
+ALTER TABLE `fnreport` CHANGE `reportid` `reportid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fnreport` ADD `reportid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fnreport` ADD PRIMARY KEY( `reportid` );
+ALTER TABLE `fnreport` CHANGE `reportname` `reportname` varchar(128) NOT NULL;
+ALTER TABLE `fnreport` ADD `reportname` varchar(128) NOT NULL;
+ALTER TABLE `fnreport` CHANGE `reporttests` `reporttests` text NOT NULL;
+ALTER TABLE `fnreport` ADD `reporttests` text NOT NULL;
+--
+-- Table: fnrssfeed
+-- DESCRIBE fnrssfeed
+ALTER TABLE `fnrssfeed` CHANGE `feedid` `feedid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fnrssfeed` ADD `feedid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fnrssfeed` ADD PRIMARY KEY( `feedid` );
+ALTER TABLE `fnrssfeed` CHANGE `feedkey` `feedkey` varchar(254) NOT NULL;
+ALTER TABLE `fnrssfeed` ADD `feedkey` varchar(254) NOT NULL;
+ALTER TABLE `fnrssfeed` CHANGE `feedname` `feedname` varchar(254) NOT NULL;
+ALTER TABLE `fnrssfeed` ADD `feedname` varchar(254) NOT NULL;
+ALTER TABLE `fnrssfeed` CHANGE `feedtype` `feedtype` varchar(32) NOT NULL;
+ALTER TABLE `fnrssfeed` ADD `feedtype` varchar(32) NOT NULL;
+ALTER TABLE `fnrssfeed` CHANGE `typeopt` `typeopt` varchar(254) NOT NULL;
+ALTER TABLE `fnrssfeed` ADD `typeopt` varchar(254) NOT NULL;
+ALTER TABLE `fnrssfeed` CHANGE `feedrange` `feedrange` varchar(32) NOT NULL;
+ALTER TABLE `fnrssfeed` ADD `feedrange` varchar(32) NOT NULL;
+ALTER TABLE `fnrssfeed` CHANGE `rangeopt` `rangeopt` varchar(254) NOT NULL;
+ALTER TABLE `fnrssfeed` ADD `rangeopt` varchar(254) NOT NULL;
+--
+-- Table: fnscheditem
+-- DESCRIBE fnscheditem
+ALTER TABLE `fnscheditem` CHANGE `scheditemid` `scheditemid` bigint(20) NOT NULL auto_increment;
+ALTER TABLE `fnscheditem` ADD `scheditemid` bigint(20) NOT NULL auto_increment;
+ALTER TABLE `fnscheditem` ADD PRIMARY KEY( `scheditemid` );
+ALTER TABLE `fnscheditem` CHANGE `scheduleid` `scheduleid` bigint(20) NOT NULL DEFAULT '0';
+ALTER TABLE `fnscheditem` ADD `scheduleid` bigint(20) NOT NULL DEFAULT '0';
+ALTER TABLE `fnscheditem` CHANGE `dayofweek` `dayofweek` varchar(8) NOT NULL;
+ALTER TABLE `fnscheditem` ADD `dayofweek` varchar(8) NOT NULL;
+ALTER TABLE `fnscheditem` CHANGE `dayofmonth` `dayofmonth` int(11) NOT NULL DEFAULT '0';
+ALTER TABLE `fnscheditem` ADD `dayofmonth` int(11) NOT NULL DEFAULT '0';
+ALTER TABLE `fnscheditem` CHANGE `monthofyear` `monthofyear` int(11) NOT NULL DEFAULT '0';
+ALTER TABLE `fnscheditem` ADD `monthofyear` int(11) NOT NULL DEFAULT '0';
+ALTER TABLE `fnscheditem` CHANGE `year` `year` int(11) NOT NULL DEFAULT '0';
+ALTER TABLE `fnscheditem` ADD `year` int(11) NOT NULL DEFAULT '0';
+ALTER TABLE `fnscheditem` CHANGE `starthour` `starthour` int(11) NOT NULL DEFAULT '0';
+ALTER TABLE `fnscheditem` ADD `starthour` int(11) NOT NULL DEFAULT '0';
+ALTER TABLE `fnscheditem` CHANGE `startmin` `startmin` int(11) NOT NULL DEFAULT '0';
+ALTER TABLE `fnscheditem` ADD `startmin` int(11) NOT NULL DEFAULT '0';
+ALTER TABLE `fnscheditem` CHANGE `finishhour` `finishhour` int(11) NOT NULL DEFAULT '23';
+ALTER TABLE `fnscheditem` ADD `finishhour` int(11) NOT NULL DEFAULT '23';
+ALTER TABLE `fnscheditem` CHANGE `finishmin` `finishmin` int(11) NOT NULL DEFAULT '59';
+ALTER TABLE `fnscheditem` ADD `finishmin` int(11) NOT NULL DEFAULT '59';
+--
+-- Table: fnschedule
+-- DESCRIBE fnschedule
+ALTER TABLE `fnschedule` CHANGE `scheduleid` `scheduleid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fnschedule` ADD `scheduleid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fnschedule` ADD PRIMARY KEY( `scheduleid` );
+ALTER TABLE `fnschedule` CHANGE `schedulename` `schedulename` varchar(128) NOT NULL;
+ALTER TABLE `fnschedule` ADD `schedulename` varchar(128) NOT NULL;
+ALTER TABLE `fnschedule` CHANGE `defaultaction` `defaultaction` tinyint(1) NOT NULL DEFAULT '1';
+ALTER TABLE `fnschedule` ADD `defaultaction` tinyint(1) NOT NULL DEFAULT '1';
+--
+-- Table: fnsession
+-- DESCRIBE fnsession
+ALTER TABLE `fnsession` CHANGE `sessionid` `sessionid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fnsession` ADD `sessionid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fnsession` ADD PRIMARY KEY( `sessionid` );
+ALTER TABLE `fnsession` CHANGE `sessionkey` `sessionkey` varchar(128) NOT NULL;
+ALTER TABLE `fnsession` ADD `sessionkey` varchar(128) NOT NULL;
+ALTER TABLE `fnsession` CHANGE `ipaddress` `ipaddress` varchar(128) NOT NULL;
+ALTER TABLE `fnsession` ADD `ipaddress` varchar(128) NOT NULL;
+ALTER TABLE `fnsession` CHANGE `username` `username` varchar(64) NOT NULL;
+ALTER TABLE `fnsession` ADD `username` varchar(64) NOT NULL;
+ALTER TABLE `fnsession` CHANGE `startx` `startx` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnsession` ADD `startx` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnsession` CHANGE `updatex` `updatex` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnsession` ADD `updatex` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnsession` CHANGE `userlevel` `userlevel` int(11) NOT NULL DEFAULT '0';
+ALTER TABLE `fnsession` ADD `userlevel` int(11) NOT NULL DEFAULT '0';
+--
+-- Table: fntestrun
+-- DESCRIBE fntestrun
+ALTER TABLE `fntestrun` CHANGE `trid` `trid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fntestrun` ADD `trid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fntestrun` ADD PRIMARY KEY( `trid` );
+ALTER TABLE `fntestrun` CHANGE `startx` `startx` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fntestrun` ADD `startx` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fntestrun` CHANGE `finishx` `finishx` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fntestrun` ADD `finishx` bigint(20) unsigned NOT NULL DEFAULT '0';
+CREATE INDEX `finishx` ON `fntestrun` ( `finishx` );
+ALTER TABLE `fntestrun` CHANGE `routput` `routput` text NOT NULL;
+ALTER TABLE `fntestrun` ADD `routput` text NOT NULL;
+ALTER TABLE `fntestrun` CHANGE `fnode` `fnode` varchar(64) NOT NULL;
+ALTER TABLE `fntestrun` ADD `fnode` varchar(64) NOT NULL;
+CREATE INDEX `fnode` ON `fntestrun` ( `fnode` );
+--
+-- Table: fnuser
+-- DESCRIBE fnuser
+ALTER TABLE `fnuser` CHANGE `username` `username` varchar(64) NOT NULL;
+ALTER TABLE `fnuser` ADD `username` varchar(64) NOT NULL;
+ALTER TABLE `fnuser` ADD PRIMARY KEY( `username` );
+ALTER TABLE `fnuser` CHANGE `password` `password` varchar(64) NOT NULL;
+ALTER TABLE `fnuser` ADD `password` varchar(64) NOT NULL;
+ALTER TABLE `fnuser` CHANGE `realname` `realname` varchar(128) NOT NULL;
+ALTER TABLE `fnuser` ADD `realname` varchar(128) NOT NULL;
+ALTER TABLE `fnuser` CHANGE `userlevel` `userlevel` int(11) NOT NULL DEFAULT '1';
+ALTER TABLE `fnuser` ADD `userlevel` int(11) NOT NULL DEFAULT '1';
+--
+-- Table: fnview
+-- DESCRIBE fnview
+ALTER TABLE `fnview` CHANGE `viewid` `viewid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fnview` ADD `viewid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fnview` ADD PRIMARY KEY( `viewid` );
+ALTER TABLE `fnview` CHANGE `vtitle` `vtitle` varchar(128) NOT NULL;
+ALTER TABLE `fnview` ADD `vtitle` varchar(128) NOT NULL;
+ALTER TABLE `fnview` CHANGE `vstyle` `vstyle` varchar(32) NOT NULL;
+ALTER TABLE `fnview` ADD `vstyle` varchar(32) NOT NULL;
+ALTER TABLE `fnview` CHANGE `vpublic` `vpublic` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnview` ADD `vpublic` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnview` CHANGE `vclick` `vclick` varchar(32) NOT NULL;
+ALTER TABLE `fnview` ADD `vclick` varchar(32) NOT NULL;
+ALTER TABLE `fnview` CHANGE `vrefresh` `vrefresh` int(11) NOT NULL DEFAULT '0';
+ALTER TABLE `fnview` ADD `vrefresh` int(11) NOT NULL DEFAULT '0';
+ALTER TABLE `fnview` CHANGE `vlinkv` `vlinkv` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnview` ADD `vlinkv` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnview` CHANGE `vcolumns` `vcolumns` smallint(6) NOT NULL DEFAULT '0';
+ALTER TABLE `fnview` ADD `vcolumns` smallint(6) NOT NULL DEFAULT '0';
+ALTER TABLE `fnview` CHANGE `vcolon` `vcolon` tinyint(1) NOT NULL DEFAULT '1';
+ALTER TABLE `fnview` ADD `vcolon` tinyint(1) NOT NULL DEFAULT '1';
+ALTER TABLE `fnview` CHANGE `vdashes` `vdashes` tinyint(1) NOT NULL DEFAULT '1';
+ALTER TABLE `fnview` ADD `vdashes` tinyint(1) NOT NULL DEFAULT '1';
+ALTER TABLE `fnview` CHANGE `vtimeago` `vtimeago` tinyint(1) NOT NULL DEFAULT '1';
+ALTER TABLE `fnview` ADD `vtimeago` tinyint(1) NOT NULL DEFAULT '1';
+--
+-- Table: fnviewitem
+-- DESCRIBE fnviewitem
+ALTER TABLE `fnviewitem` CHANGE `viewitemid` `viewitemid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fnviewitem` ADD `viewitemid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fnviewitem` ADD PRIMARY KEY( `viewitemid` );
+ALTER TABLE `fnviewitem` CHANGE `viewid` `viewid` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnviewitem` ADD `viewid` bigint(20) unsigned NOT NULL DEFAULT '0';
+CREATE INDEX `viewid` ON `fnviewitem` ( `viewid` );
+ALTER TABLE `fnviewitem` CHANGE `itype` `itype` varchar(128) NOT NULL;
+ALTER TABLE `fnviewitem` ADD `itype` varchar(128) NOT NULL;
+ALTER TABLE `fnviewitem` CHANGE `ioption` `ioption` varchar(250) NOT NULL;
+ALTER TABLE `fnviewitem` ADD `ioption` varchar(250) NOT NULL;
+ALTER TABLE `fnviewitem` CHANGE `icolour` `icolour` tinyint(1) NOT NULL DEFAULT '1';
+ALTER TABLE `fnviewitem` ADD `icolour` tinyint(1) NOT NULL DEFAULT '1';
+ALTER TABLE `fnviewitem` CHANGE `itextstatus` `itextstatus` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnviewitem` ADD `itextstatus` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnviewitem` CHANGE `idetail` `idetail` smallint(5) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnviewitem` ADD `idetail` smallint(5) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnviewitem` CHANGE `iweight` `iweight` int(10) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnviewitem` ADD `iweight` int(10) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnviewitem` CHANGE `isize` `isize` smallint(6) NOT NULL DEFAULT '0';
+ALTER TABLE `fnviewitem` ADD `isize` smallint(6) NOT NULL DEFAULT '0';
+ALTER TABLE `fnviewitem` CHANGE `igraphic` `igraphic` smallint(6) NOT NULL DEFAULT '0';
+ALTER TABLE `fnviewitem` ADD `igraphic` smallint(6) NOT NULL DEFAULT '0';
+ALTER TABLE `fnviewitem` CHANGE `iname` `iname` varchar(64) NOT NULL;
+ALTER TABLE `fnviewitem` ADD `iname` varchar(64) NOT NULL;
+--
diff --git a/src/node/posix/config.inc.php b/src/node/posix/config.inc.php
new file mode 100755
index 0000000..ef5418f
--- /dev/null
+++ b/src/node/posix/config.inc.php
@@ -0,0 +1,53 @@
+
\ No newline at end of file
diff --git a/src/node/posix/freenats-node.php b/src/node/posix/freenats-node.php
new file mode 100755
index 0000000..6002fa6
--- /dev/null
+++ b/src/node/posix/freenats-node.php
@@ -0,0 +1,499 @@
+
+
+ something
+
+
+ testname
+ Test Description
+ return value
+ suggested alert level
+
+
+*/
+
+class FreeNATS_XML_Node
+{
+var $xml="";
+var $Config;
+
+function AddLine($line)
+{
+$this->xml.=$line."\n";
+}
+
+function AddTest($name,$desc,$val,$lvl=-1)
+{
+$this->AddLine("");
+$this->AddLine(" ");
+$this->AddLine(" ".$name."");
+$this->AddLine(" ".$desc."");
+$this->AddLine(" ".$val."");
+$this->AddLine(" ".$lvl."");
+$this->AddLine(" ");
+$this->AddLine("");
+}
+
+function FreeNATS_XML_Node()
+{
+global $nodeCfg;
+$this->AddLine("");
+$this->Config=&$nodeCfg;
+}
+
+function Start()
+{
+$this->AddLine("");
+}
+
+function Stop()
+{
+$this->AddLine("");
+}
+
+function DataHeader($is_header=true)
+{
+if ($is_header) $this->AddLine(" ");
+else $this->AddLine(" ");
+}
+
+function HeaderItem($name,$value)
+{
+$this->AddLine(" <".$name.">".$value."".$name.">");
+}
+
+function ScreenOutput()
+{
+header("Content-type: text/xml");
+echo $this->xml;
+exit();
+}
+
+}
+
+$Node=new FreeNATS_XML_Node();
+$Node->Start();
+
+
+// How Were We Called
+$pull=false;
+
+if (isset($_SERVER['REMOTE_ADDR'])) // called via HTTP
+ {
+ $pull=true;
+ if ($nodeCfg['restrict_pull_ip']!="") // check IP
+ {
+ if ($_SERVER['REMOTE_ADDR']!=$nodeCfg['restrict_pull_ip'])
+ {
+ echo "Authorisation Failure: IP Address Denied";
+ exit();
+ }
+ }
+ if ($nodeCfg['nodekey']!="") // check authorisation
+ {
+ if ( !(isset($_REQUEST['nodekey'])) || ($_REQUEST['nodekey']!=$nodeCfg['nodekey']) )
+ {
+ echo "Authorisation Failure: Incorrect NODEKEY Configured";
+ exit();
+ }
+ }
+ if (isset($_REQUEST['noupdate']) && ($_REQUEST['noupdate']==1)) $fileUpdate=false;
+ }
+else // called via CLI
+ {
+ $a=1;
+ for ($a=1; $a<$argc; $a++)
+ {
+ switch($argv[$a])
+ {
+ case "-c": case "--c": case "-config": case "--config":
+ $configFile=$argv[++$a];
+ break;
+ case "-d": case "--d": case "-debug": case "--debug":
+ $pull=true; // output to the console
+ break;
+ case "--noupdate": case "-noupdate":
+ $fileUpdate=false;
+ break;
+ }
+ }
+ }
+
+if ($configFile!="") require($configFile);
+
+
+$Node->DataHeader();
+$Node->HeaderItem("name","FreeNATS Posix Node XML");
+$Node->HeaderItem("version",$nodeCfg['version']);
+if (!$pull) // we are pushing instead
+ $Node->HeaderItem("nodekey",$nodeCfg['nodekey']);
+$Node->DataHeader(false);
+
+// Node Type and Version Pseudo-Tests
+$Node->AddTest("fnn.version","FreeNATS Node Version",$nodeCfg['version'],0);
+$Node->AddTest("fnn.name","FreeNATS Node Type","Posix XML",0);
+
+//$Node->AddTest("bob.one","Bob One",10,0);
+//$Node->AddTest("bob.two","Bob Two",11,0);
+
+
+// Data from Uptime
+if ($nodeCfg['uptime'])
+{
+$uptime=exec("/usr/bin/uptime");
+
+$ut=preg_split("/\s+/",$uptime);
+//var_dump($ut);
+
+
+
+$Node->AddTest("uptime.1m","One Minute Load Average",substr($ut[count($ut)-3],0,strlen($ut[count($ut)-3])-1),0);
+$Node->AddTest("uptime.5m","Five Minute Load Average",substr($ut[count($ut)-2],0,strlen($ut[count($ut)-2])-1),0);
+$Node->AddTest("uptime.15m","Fifteen Minute Load Average",$ut[count($ut)-1],0);
+$Node->AddTest("uptime.users","Logged in Users",$ut[count($ut)-7],0);
+}
+
+// Data from Time
+if ($nodeCfg['systime'])
+{
+$nowx=time();
+$utf=date("Y-m-d H:i:s",$nowx);
+$dts=date("H:i:s d/m/Y",$nowx);
+$pasthour= (date("i",$nowx)*60)+date("s",$nowx);
+
+$Node->AddTest("systime.x","Node Time (Seconds Since Epoch)",$nowx,0);
+$Node->AddTest("systime.utf","Node Time (UTF)",$utf,0);
+$Node->AddTest("systime.dts","Note Time",$dts,0);
+$Node->AddTest("systime.sph","Seconds Past Hour",$pasthour,0);
+}
+
+// ------------------ DISK SPACE
+
+// Data from DF
+if ($nodeCfg['disk'])
+{
+ $result=array();
+ exec("/bin/df -P",$result);
+
+ // filesystem blocks used available use% mount
+ for ($a=1; $a4) // not a duff line
+ {
+ $filesystem=$parts[0];
+ $size=$parts[1]/1024;
+ $used=$parts[2]/1024;
+ $free=$parts[3]/1024;
+ $perc=substr($parts[4],0,(strlen($parts[4])-1));
+ $percfree=100-$perc;
+ $mount=$parts[5];
+
+ if ($perc >= 90) $alertlevel=2; // failed
+ else if ($perc >= 80) $alertlevel=1; // warning
+ else $alertlevel=0; // passed
+
+ //$nicefs=str_replace("/","_",$filesystem);
+ $name=$filesystem.".size";
+ $desc="Total Size of ".$filesystem." (".$mount.") (Mb)";
+ $Node->AddTest($name,$desc,round($size,2),$alertlevel);
+
+ $name=$filesystem.".used";
+ $desc="Space Used on ".$filesystem." (".$mount.") (Mb)";
+ $Node->AddTest($name,$desc,round($used,2),$alertlevel);
+
+ $name=$filesystem.".free";
+ $desc="Space Free on ".$filesystem." (".$mount.") (Mb)";
+ $Node->AddTest($name,$desc,round($free,2),$alertlevel);
+
+ $name=$filesystem.".perc";
+ $desc="Percentage Used on ".$filesystem." (".$mount.")";
+ $Node->AddTest($name,$desc,$perc,$alertlevel);
+
+ $name=$filesystem.".percfree";
+ $desc="Percentage Free on ".$filesystem." (".$mount.")";
+ $Node->AddTest($name,$desc,$percfree,$alertlevel);
+ }
+ }
+}
+
+
+
+// ------------------ RAM
+// Data from FREE
+if ($nodeCfg['memory'])
+{
+
+
+ $free=array();
+ exec("/usr/bin/free",$free);
+
+ //unset($this->mm_elements);
+
+ for ($fc=1; $fc< count($free); $fc++)
+ {
+ // Mem: Swap: -- total, used, free -- kb
+ $parts=preg_split("/\s+/",$free[$fc]);
+ $proc=false;
+ if ($parts[0]=="Mem:") { $proc=true; $type="System Memory"; $prefix="mem"; }
+ else if ($parts[0]=="Swap:") { $proc=true; $type="System Swap File"; $prefix="swap"; }
+ /*
+ else
+ {
+ echo $free[$fc]."\n";
+ exit();
+ }*/
+
+ if ($proc)
+ {
+ $total=round($parts[1]/1024,3);
+ $usedmb=round($parts[2]/1024,3);
+ $freemb=round($parts[3]/1024,3);
+ $used_perc=0;
+ $free_perc=0;
+ if ($total>0)
+ {
+ if ($used>0) $used_perc=round (($usedmb/$total)*100,2);
+ if ($free>0) $free_perc=round (($freemb/$total)*100,2);
+ }
+ $name=$prefix.".total";
+ $Node->AddTest($name,$type." Total (Mb)",$total,0);
+
+
+ $name=$prefix.".used"; // parts[2] used kb
+ $Node->AddTest($name,$type." Used (Mb)",$usedmb,0);
+
+ $name=$prefix.".free"; // parts[3] free kb
+ $Node->AddTest($name,$type." Free (Mb)",$freemb,0);
+
+ $name=$prefix.".free.perc";
+ $Node->AddTest($name,$type." Free (%)",$free_perc,0);
+
+ $name=$prefix.".used.perc";
+ $Node->AddTest($name,$type." Used (%)",$used_perc,0);
+ } // end of if $proc
+
+ } // end of for
+
+}
+
+
+
+// ------------------ NETWORK USAGE
+// Data from /proc/net/dev
+if ($nodeCfg['net'])
+{
+$netarr=@file("/proc/net/dev");
+for($a=2; $aAddTest("net.".$dev.".rxt","Total Received on Interface ".$dev." (bytes)",$rx,0);
+ $Node->AddTest("net.".$dev.".txt","Total Sent on Interface ".$dev." (bytes)",$tx,0);
+ $Node->AddTest("net.".$dev.".trt","Total Passed on Interface ".$dev." (bytes)",$tt,0);
+
+ $trrx=0;
+ $trtx=0;
+ $trtt=0;
+ $trlvl=0;
+
+ $nowx=time();
+ // does the file exist
+ $fp=fopen($nodeCfg['tmp_dir']."fnnode.net.".$dev,"r");
+ if ($fp>0) // yes
+ {
+ $lastx=trim(fgets($fp,128));
+ $lrx=trim(fgets($fp,128));
+ $ltx=trim(fgets($fp,128));
+ $ltt=$lrx+$ltx;
+ // wrap checking and the like...
+ if ( ($lrx>$rx) ) //|| ($ltx>$tx) || ($ltt>$tt) )
+ {
+ $trlvl=-1; // untested
+ $diffx=0;
+ //echo "untested ".trim($lrx)."-$rx";
+ }
+ else // test it
+ {
+ $diffx=$nowx-$lastx;
+ if ($diffx>0)
+ {
+ $trrx=(($rx-$lrx)/$diffx)/1024;
+ $trtx=(($tx-$ltx)/$diffx)/1024;
+ $trtt=(($tt-$ltt)/$diffx)/1024;
+ }
+ if($trrx=="") $trrx=0;
+ if($trtx=="") $trtx=0;
+ if($trtt=="") $trtt=0;
+ }
+ }
+ else $trlvl=-1;
+ @fclose($fp);
+
+ // write my file
+ if ($fileUpdate)
+ {
+ //echo "Writing Files!\n";
+ $fp=fopen($nodeCfg['tmp_dir']."fnnode.net.".$dev,"w");
+ fputs($fp,$nowx."\n");
+ fputs($fp,$rx."\n");
+ fputs($fp,$tx."\n");
+ fclose($fp);
+ }
+
+ $Node->AddTest("net.".$dev.".rx","Receive Speed on ".$dev." (kbyte/s)",$trrx,$trlvl);
+ $Node->AddTest("net.".$dev.".tx","Transmit Speed on ".$dev." (kbyte/s)",$trtx,$trlvl);
+ $Node->AddTest("net.".$dev,"Combined Speed on ".$dev." (kbyte/s)",$trtt,$trlvl);
+ $Node->AddTest("net.".$dev.".elapsed","Speed Sample Time on ".$dev." (secs)",$diffx,$trlvl);
+ }
+}
+
+// ------------------ PROCESS INFORMATION
+if ($nodeCfg['process'])
+ {
+ $ps=array();
+ exec("/bin/ps -e -w",$ps);
+
+ $pdata=array();
+ //foreach($ps as $psl)
+ for ($z=1; $z$val)
+ {
+ $Node->AddTest("ps.".$key,"Number of ".$key." Processes",$val,0);
+ }
+ }
+
+
+// ------------------ END OF TEST DATA
+
+
+// End FreeNATS Data
+$Node->Stop();
+
+if ($pull)
+ {
+ // Output Data to Screen
+ $Node->ScreenOutput();
+ }
+else // push
+ {
+ // PHP 5 Required
+ $data=array( "nodeid" => $nodeCfg['nodeid'],
+ "nodekey" => $nodeCfg['nodekey'],
+ "xml" => $Node->xml );
+ $data=http_build_query($data);
+
+ $request=array( "http" => array( "method" => "POST",
+ "header" => "Content-type: application/x-www-form-urlencoded", "content" => $data ) );
+ $context=stream_context_create($request);
+ $fp=fopen($nodeCfg['push_target'],'rb',false,$context);
+ if ($fp<=0)
+ {
+ echo "Push Failed to open URL\n";
+ exit();
+ }
+ $serverdata=@stream_get_contents($fp);
+
+ if ($serverdata===false)
+ {
+ echo "Push Data is FALSE\n";
+ exit();
+ }
+
+ if ($serverdata!="1")
+ {
+ echo "Server Returned Error: ".$serverdata."\n";
+ exit();
+ }
+
+ echo "Push Succeeded\n";
+ }
+
+?>
diff --git a/src/node/win32/node.vbs b/src/node/win32/node.vbs
new file mode 100644
index 0000000..356677b
--- /dev/null
+++ b/src/node/win32/node.vbs
@@ -0,0 +1,314 @@
+' REM FreeNATS Windows Node Bogeroo
+'
+' This file is part of FreeNATS
+'
+' FreeNATS is (C) Copyright 2008-2010 PurplePixie Systems
+'
+' FreeNATS 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 3 of the License, or
+' (at your option) any later version.
+'
+' FreeNATS 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 FreeNATS. If not, see www.gnu.org/licenses
+'
+' For more information see www.purplepixie.org/freenats
+'
+' Release: 3 Alpha 06/04/2010
+
+PushData=0
+PullData=1
+PushURL=""
+NodeID=""
+NodeKey="" 'for post only
+strComputer="."
+wmiUser=""
+wmiPass=""
+wmiDomain=""
+wmiSimple=1
+
+Set colNamedArguments= WScript.Arguments.Named
+
+If colNamedArguments.Exists("nooutput") Then
+ PullData=0
+End If
+If colNamedArguments.Exists("pushurl") Then
+ PushData=1
+ PushURL=colNamedArguments.Item("pushurl")
+End If
+If colNamedArguments.Exists("nodeid") Then
+ NodeID=colNamedArguments.Item("nodeid")
+End If
+If colNamedArguments.Exists("nodekey") Then
+ NodeKey=colNamedArguments.Item("nodekey")
+End If
+If colNamedArguments.Exists("host") Then
+ strComputer=colNamedArguments.Item("host")
+End If
+If colNamedArguments.Exists("user") Then
+ wmiUser=colNamedArguments.Item("user")
+ wmiSimple=0
+End If
+If colNamedArguments.Exists("pass") Then
+ wmiPass=colNamedArguments.Item("pass")
+End If
+If colNamedArguments.Exists("domain") Then
+ wmiDomain=colNamedArguments.Item("domain")
+ wmiSimple=0
+End If
+
+OutputBuffer = ""
+
+OB ""
+OB ""
+OB " "
+OB " FreeNATS VBS Node XML"
+OB " 0.03"
+OB " "
+
+
+
+
+
+
+Function OB(text)
+ OutputBuffer = OutputBuffer & text & vbCrLf
+End Function
+
+Function DumpOB()
+ Wscript.Echo OutputBuffer
+End Function
+
+alloweds = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890!$%^*()[]{}?/+=-_ "
+
+Function SafeString(text)
+ text = Replace(text,"&","+")
+ output = ""
+ For position = 1 to Len(text)
+ character = Mid(text,position,1)
+ pos = InStr(alloweds,character)
+ If pos > 0 Then
+ output = output & character
+ Else
+ output = output & "_"
+ End If
+ Next
+ SafeString = output
+End Function
+
+If wmiSimple = 1 Then
+ Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
+Else
+ set objLocator = CreateObject("WbemScripting.SWbemLocator")
+ set objWMIService = objLocator.ConnectServer(strComputer,"root/cimv2",wmiUser,wmiPass)
+ objWMIService.Security_.impersonationlevel=3 ' at level 3 you are impersonating the pope
+End If
+
+
+set objRefresher = CreateObject("WbemScripting.Swbemrefresher")
+Set objProcessor = objRefresher.AddEnum (objWMIService, "Win32_PerfFormattedData_PerfOS_Processor").objectSet
+
+Set colRunningServices = objWMIService.ExecQuery("Select * from Win32_Service")
+Set memItems = objRefresher.AddEnum (objWMIService, "Win32_PerfFormattedData_PerfOS_Memory").objectSet
+Set colOperatingSystems = objWMIService.ExecQuery ("Select * from Win32_OperatingSystem")
+
+Set colRunningProcesses = objWMIService.ExecQuery("Select * from Win32_Process")
+
+Set WshNetwork = WScript.CreateObject("WScript.Network")
+AddTest "system.name","Computer Name",SafeString(WshNetwork.ComputerName),0
+
+
+objRefresher.Refresh ' No I don't really get it either
+WScript.Sleep 2000 ' but unless you do this you get even
+objRefresher.Refresh ' weirder than usual values.
+
+int ServiceRunning=0
+int Alert=0
+For Each objService in colRunningServices
+ If objService.State = "Running" Then
+ ServiceRunning=1
+ Alert=0
+ Else
+ Alert=1
+ ServiceRunning=0
+ End If
+ TName = Replace(objService.Name," ","_")
+ TestName="srv." & SafeString(TName)
+ AddTest TestName, SafeString(objService.DisplayName) & " Service", ServiceRunning, Alert
+Next
+
+
+intThresholdViolations = 0
+
+
+Set colDisks = objWMIService.ExecQuery ("Select * from Win32_LogicalDisk")
+
+For Each objDisk in colDisks
+
+DiskSpace = objDisk.FreeSpace / 1024 / 1024
+DiskSize = objDisk.Size / 1024 / 1024
+DiskUsed = DiskSize - DiskSpace
+DiskUsedPerc = ( DiskUsed / DiskSize ) * 100
+DiskInDrive = 1
+If IsNull(DiskSpace) Then
+ DiskSpace = "0"
+ DiskUsed = "0"
+ DiskUsedPerc = "0.00"
+ DiskInDrive = 0
+End If
+DiskSpace = Round(DiskSpace,2)
+DiskUsed = Round(DiskUsed,2)
+DiskUsedPerc = Round(DiskUsedPerc,2)
+
+alertlevel = 0
+If DiskUsedPerc > 80 Then
+ alertlevel = 1
+End If
+If DiskUsedPerc > 90 Then
+ alertlevel = 2
+End If
+
+
+If DiskInDrive = 1 Then
+TestName= "disk.free." & Left(objDisk.DeviceID,1)
+AddTest TestName,"Space Free On " & objDisk.DeviceID & " (Mb)", DiskSpace, alertlevel
+TestName= "disk.used." & Left(objDisk.DeviceID,1)
+AddTest TestName,"Space Used On " & objDisk.DeviceID & " (Mb)", DiskUsed, alertlevel
+TestName= "disk.used.perc." & Left(objDisk.DeviceID,1)
+AddTest TestName,"Percent Disk Usage On " & objDisk.DeviceID & " (%)", DiskUsedPerc, alertlevel
+End If
+
+Next
+
+
+
+For Each objItem in objProcessor
+
+ If objItem.Name = "_Total" Then
+ AddTest "proc.load","Processor Load (%)",objItem.PercentProcessorTime,0
+ End If
+Next
+
+
+
+For Each objOS in colOperatingSystems
+ dtmBootup = objOS.LastBootUpTime
+ dtmLastBootupTime = WMIDateStringToDate(dtmBootup)
+ dtmSystemUptime = DateDiff("h", dtmLastBootUpTime, Now)
+ AddTest "uptime","Uptime (Hours)",dtmSystemUptime,0
+Next
+
+Function WMIDateStringToDate(dtmBootup)
+ WMIDateStringToDate = CDate(Mid(dtmBootup, 5, 2) & "/" & _
+ Mid(dtmBootup, 7, 2) & "/" & Left(dtmBootup, 4) _
+ & " " & Mid (dtmBootup, 9, 2) & ":" & _
+ Mid(dtmBootup, 11, 2) & ":" & Mid(dtmBootup,13, 2))
+End Function
+
+
+
+
+For Each objItem in memItems
+ TestName="mem."
+ If Len(objItem.Name) > 0 Then
+ TestName = TestName & objItem.Name & "."
+ End If
+ TestName = TestName & "free"
+
+ AddTest TestName,"Memory Available (Kilobytes)",objItem.AvailableKBytes,0
+
+Next
+
+' Running Processes
+
+Dim ProcArr(1024)
+Dim CountArr(1024)
+ProcCount=0
+pName=""
+pDesc=""
+ProcCount = 0
+
+ For Each objProc in colRunningProcesses
+ 'Wscript.Echo objProc.ProcessID & " " & objProc.Name & vbCrLf
+ pName = objProc.Name
+ NewProc = 1 ' Assume New Until Checked
+ FoundPos = 0
+ For ProcTmp = 0 To ProcCount
+ If ( ProcArr(ProcTmp) = pName ) Then ' Exists
+ NewProc = 0
+ FoundPos = ProcTmp
+ 'ProcTmp = UBound(ProcArr)+1
+ End If
+ Next
+
+ If NewProc = 0 Then ' Not a New Process
+ CountArr(FoundPos) = CountArr(FoundPos) + 1
+ Else ' Does Not Exist
+ ProcArr(ProcCount) = pName
+ CountArr(ProcCount) = 1
+ ProcCount = ProcCount + 1
+ End If
+
+
+ Next
+
+
+For ProcTmp = 0 To ProcCount-1
+' Wscript.Echo ProcArr(ProcTmp) & " " & CountArr(ProcTmp)
+ AddTest "proc." & SafeString(ProcArr(ProcTmp)), ProcArr(ProcTmp) & " Process", CountArr(ProcTmp), 0
+Next
+
+'Set listProc = Nothing
+'set objWMIService = Nothing
+
+
+
+' Close Off
+
+OB ""
+
+Function AddTest(testname,testdesc,testvalue,alertlevel)
+ OB ""
+ OB " " & testname & ""
+ OB " " & testdesc & ""
+ OB " " & testvalue & ""
+ OB " " & alertlevel & ""
+ OB ""
+End Function
+
+If PullData=1 Then
+ DumpOB()
+End If
+
+If PushData=1 Then
+ ' Push Da Data
+ WScript.Echo
+ WScript.Echo "Pushing Data..."
+ WScript.Echo "URL : " & PushURL
+ WScript.Echo "NodeID: " & NodeID
+ WScript.Echo "Key : " & NodeKey
+
+ Set objHTTP = CreateObject("Microsoft.XMLHTTP")
+ objHTTP.open "POST", PushURL, False
+
+ objHTTP.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
+ http_request = "nodeid=" & Escape(NodeID) & "&nodekey=" & Escape(NodeKey) & "&xml=" & Escape(OutputBuffer)
+ objHTTP.send http_request
+
+ response = objHTTP.responseText
+
+ Set objHTTP = Nothing
+
+ If Right(response,1) = "1" Then
+ WScript.Echo "Post Successful"
+ Else
+ WScript.Echo "Encountered An Error:"
+ WScript.Echo response
+ End If
+
+End If
\ No newline at end of file
diff --git a/src/node/win32/push.bat b/src/node/win32/push.bat
new file mode 100755
index 0000000..72cdc95
--- /dev/null
+++ b/src/node/win32/push.bat
@@ -0,0 +1,2 @@
+@ECHO OFF
+cscript node.vbs //nologo /pushurl:http://YOUR_NATS_WEB_URL/nodeside.push.php /nodeid:nodeid /nodekey:SomeKey
diff --git a/src/server/base/.htaccess b/src/server/base/.htaccess
new file mode 100755
index 0000000..ff2beb8
--- /dev/null
+++ b/src/server/base/.htaccess
@@ -0,0 +1,2 @@
+order deny,allow
+deny from all
diff --git a/src/server/base/config.inc.php b/src/server/base/config.inc.php
new file mode 100755
index 0000000..3c13dcc
--- /dev/null
+++ b/src/server/base/config.inc.php
@@ -0,0 +1,64 @@
+
diff --git a/src/server/base/eval.inc.php b/src/server/base/eval.inc.php
new file mode 100755
index 0000000..ba426c9
--- /dev/null
+++ b/src/server/base/eval.inc.php
@@ -0,0 +1,66 @@
+DB->Query($q);
+//echo $q;
+while ($row=$NATS->DB->Fetch_Array($r))
+ {
+ //echo "\n".$row['eoperator']."\n";
+ $nl=0;
+ switch ($row['eoperator'])
+ {
+ case "ET":
+ if ($row['evalue']==$value) $nl=$row['eoutcome'];
+ break;
+ case "GT":
+ if ($row['evalue']<$value) $nl=$row['eoutcome'];
+ break;
+ case "LT":
+ if ($row['evalue']>$value) $nl=$row['eoutcome'];
+ break;
+ }
+ if ($nl>$lvl) $lvl=$nl;
+ }
+$NATS->DB->Free($r);
+return $lvl;
+}
+
+function eval_operator_text($operator)
+{
+switch($operator)
+ {
+ case "ET": return "Equal To";
+ case "GT": return "Greater Than";
+ case "LT": return "Less Than";
+
+ default: return "Unknown";
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/src/server/base/freenats.inc.php b/src/server/base/freenats.inc.php
new file mode 100755
index 0000000..e29770e
--- /dev/null
+++ b/src/server/base/freenats.inc.php
@@ -0,0 +1,1081 @@
+Tests=new TNATS_Tests(); // need this available during the include phase pre-start
+ }
+
+function Start()
+ {
+ if ($this->init) return 0;
+ global $BaseDir,$fnSkipSiteIncludes;
+ if ( (!isset($BaseDir)) || ($BaseDir=="") ) $BaseDir="./";
+ $this->DB=new TNATS_DB();
+ $this->Cfg=new TNATS_Cfg();
+ $this->DB->Connect();
+ $this->Cfg->Load($this->DB);
+ // Site Includes
+ // Tests
+ if ( (!isset($fnSkipSiteIncludes)) || ($fnSkipSiteIncludes === false) )
+ {
+
+ if ($this->Cfg->Get("site.include.tests",0)==1)
+ {
+ foreach(glob($BaseDir."site/tests/*.php") as $phpfile)
+ {
+ $this->Event("Including ".$phpfile,10,"NATS","Start");
+ include_once($phpfile);
+ }
+ }
+ // Events
+ if ($this->Cfg->Get("site.include.events",0)==1)
+ {
+ foreach(glob($BaseDir."site/events/*.php") as $phpfile)
+ {
+ $this->Event("Including ".$phpfile,10,"NATS","Start");
+ include_once($phpfile);
+ }
+ }
+ }
+
+ // RSS
+ $this->RSS = new NATS_RSS();
+
+ // Language
+ $this->Lang=new TNATS_Lang();
+ if (isset($_COOKIE['fn_lang']) && ($_COOKIE['fn_lang']!="") ) $l=$_COOKIE['fn_lang'];
+ else $l=$this->Cfg->Get("site.language","");
+ $this->Lang->Load($l);
+
+
+ $this->init=true;
+ }
+
+function Stop()
+ {
+ $t=$this->Cfg->Get("freenats.tracker","");
+ if ( ($t>0) && ($t!="") )
+ {
+ $day=date("Ymd");
+ if ($this->Cfg->Get("freenats.tracker.last","")!=$day)
+ {
+ $this->Cfg->Set("freenats.tracker.last",$day);
+ $this->PhoneHome();
+ }
+ }
+
+ $this->DB->Disconnect();
+ $this->init=false;
+ }
+
+function Event($logevent,$loglevel=1,$modid="NONE",$catid="NONE")
+ {
+ global $NATS_Session;
+ if ((isset($NATS_Session))&&($NATS_Session->auth)) $username=$NATS_Session->username;
+ else $username="";
+ $l=$this->Cfg->Get("log.level");
+ //echo "** $l **\n";
+ if ( $l=="" ) $l=10; // debug logging if no variable
+ if ( $l < $loglevel ) return false;
+ if (strlen($logevent)>249) $logevent=substr($logevent,0,245)."...";
+ $q="INSERT INTO fnlog(postedx,modid,catid,loglevel,logevent,username) VALUES(".time().",";
+ $q.="\"".ss($modid)."\",\"".ss($catid)."\",".ss($loglevel).",\"".ss($logevent)."\",\"".ss($username)."\")";
+ //echo $q;
+ $this->DB->Query($q,false);
+ }
+
+function AlertAction($nodeid,$alertlevel,$change,$alerttext)
+ {
+ //echo "Called for node: ".$nodeid."\n";
+ if ($change==0) return false; // no change
+ if (trim($alerttext)=="") return false; // no text so a bogus event i.e. -1 to 0
+ //echo $nodeid.":".$alertlevel.":".$change.":".$alerttext."\n";
+ // get all the alertactions for this node id
+ $q="SELECT aaid FROM fnnalink WHERE nodeid=\"".ss($nodeid)."\"";
+ $r=$this->DB->Query($q);
+ while ($arow=$this->DB->Fetch_Array($r))
+ {
+ // get details for this alert action
+ $aq="SELECT * FROM fnalertaction WHERE aaid=".$arow['aaid']." LIMIT 0,1";
+
+ $ar=$this->DB->Query($aq);
+ $aa=$this->DB->Fetch_Array($ar);
+ $this->DB->Free($ar);
+
+ // UGGGGGGGG continue!!
+ // if the type is blank or disabled skip
+ if ( ($aa['atype']=="") || ($aa['atype']=="Disabled") ) continue;
+ // if warnings aren't set and it is a warning skip
+ if ( ($aa['awarnings']==0) && ($alertlevel==1) ) continue;
+ // if decreases aren't set and it is a decrease skip
+ if ( ($aa['adecrease']==0) && ($change<1) ) continue;
+ // if has a schedule and it dictates not to run now then skip
+ if (($aa['scheduleid']!=0)&&(!run_x_in_schedule(time(),$aa['scheduleid']))) continue;
+
+ // made it this far
+
+ $ndata=$nodeid.": ".$alerttext;
+ $this->ActionAddData($arow['aaid'],$ndata);
+
+ /* // spun to ActionAddData
+ if ($aa['mdata']!="") $ndata=$aa['mdata']."\n".$nodeid.": ".$alerttext;
+ else $ndata=$nodeid.": ".$alerttext;
+ $uq="UPDATE fnalertaction SET mdata=\"".ss($ndata)."\" WHERE aaid=".$arow['aaid'];
+ //echo $uq."\n";
+ $this->DB->Query($uq);
+ */
+ }
+ }
+
+function ActionAddData($aaid, $newmdata)
+ {
+ $q="SELECT aaid,mdata FROM fnalertaction WHERE aaid=".ss($aaid)." LIMIT 0,1";
+ $r=$this->DB->Query($q);
+ if (!$row=$this->DB->Fetch_Array($r)) return false;
+ $this->DB->Free($r);
+
+ if ($row['mdata']!="") $ndata=$row['mdata']."\n".$newmdata;
+ else $ndata=$newmdata;
+
+ $uq="UPDATE fnalertaction SET mdata=\"".ss($ndata)."\" WHERE aaid=".$row['aaid'];
+ $this->DB->Query($uq);
+ return true;
+ }
+
+function ActionFlush()
+ {
+ global $allowed,$BaseDir; // allowed chars from screen in YA BODGE
+ $q="SELECT * FROM fnalertaction WHERE mdata!=\"\"";
+ $r=$this->DB->Query($q);
+ while ($row=$this->DB->Fetch_Array($r))
+ {
+
+ $doalert=true;
+
+ // clear mdata right at the start to get around duplicate emails whilst processing
+ $q="UPDATE fnalertaction SET mdata=\"\" WHERE aaid=".$row['aaid'];
+ $this->DB->Query($q);
+
+ if ($this->DB->Affected_Rows()<=0) // already flushed or failed to flush
+ {
+ $doalert=false;
+ $this->Event("Alert Action Already Flushed - Skipping",8,"Flush","Action");
+ }
+
+ // alert counter
+ $td=date("Ymd");
+ if ($td!=$row['ctrdate']) // new day or no flush record
+ {
+ $q="UPDATE fnalertaction SET ctrdate=\"".$td."\",ctrtoday=1 WHERE aaid=".$row['aaid'];
+ $this->DB->Query($q);
+ }
+ else
+ {
+
+ if ( ($row['ctrlimit']==0) || ($row['ctrlimit']>$row['ctrtoday']) ) // no limit or below
+ {
+ $q="UPDATE fnalertaction SET ctrtoday=ctrtoday+1 WHERE aaid=".$row['aaid'];
+ $this->DB->Query($q);
+ }
+ else // at or over limit
+ {
+ $this->Event("Alert Action Limit Reached - Skipping",2,"Flush","Action");
+ $doalert=false;
+ }
+
+ }
+
+
+ if ($row['atype']=="email")
+ {
+ if ($row['esubject']==0) $sub="";
+ else if ($row['esubject']==1) $sub=$this->Cfg->Get("alert.subject.short","FreeNATS Alert");
+ else $sub=$this->Cfg->Get("alert.subject.long","** FreeNATS Alert **");
+ $body="";
+ if ($row['etype']==0) $body=$row['mdata'];
+ else
+ {
+ $body=$this->Cfg->Get("alert.body.header","FreeNATS Alert,");
+ $body.="\r\n\r\n".$row['mdata']."\r\n\r\n";
+ $body.=$this->Cfg->Get("alert.body.footer","");
+ $body.="\r\n-- FreeNATS @ ".nicedt(time());
+ }
+ //$tolist=preg_split("[\n\r]",$row['etolist']);
+ $tolist=array();
+ $f=0;
+ $tolist[0]="";
+ for ($a=0; $aCfg->Get("mail.smtpserver","");
+ if ($smtpserver=="")
+ {
+ // mail() method - local delivery
+ $header="From: ".$row['efrom']."\r\n";
+ if ($doalert)
+ {
+ mail($toaddr,$sub,$body,$header);
+ $this->Event("Sent alert email to ".$toaddr,4,"Flush","Email");
+ }
+ }
+ else // use phpmailer direct SMTP delivery
+ {
+ include_once($BaseDir."phpmailer/class.phpmailer.php");
+ $fromname=$this->Cfg->Get("mail.fromname","");
+ if ($fromname=="") $fromname="FreeNATS";
+ $smtpusername=$this->Cfg->Get("mail.smtpusername",""); // removed .
+ if ($smtpusername!="") $smtpauth=true;
+ else $smtpauth=false;
+ $smtppassword=$this->Cfg->Get("mail.smtppassword",""); // removed .
+ $smtphostname=$this->Cfg->Get("mail.smtphostname",""); // removed .
+ $smtpsec=$this->Cfg->Get("mail.smtpsecure","");
+ $mail=new PHPMailer();
+ $mail->IsSMTP();
+ $mail->Host=$smtpserver;
+ $mail->From=$row['efrom'];
+ $mail->FromName=$fromname;
+ $mail->AddAddress($toaddr);
+ $mail->Subject=$sub;
+ $mail->Body=$body;
+ $mail->WordWrap=50;
+ if ($smtphostname!="") $mail->Hostname=$smtphostname;
+ if ($smtpauth)
+ {
+ $mail->SMTPAuth=true;
+ $mail->Username=$smtpusername;
+ $mail->Password=$smtppassword;
+ }
+ if ($smtpsec!="") $mail->SMTPSecure=$smtpsec;
+ if (!$mail->Send())
+ { // failed
+ $this->Event("phpMailer to ".$toaddr." failed",1,"Flush","Email");
+ $this->Event("phpMailer Error: ".$mail->ErrorInfo,1,"Flush","Email");
+ }
+ else
+ {
+ $this->Event("phpMailer Sent Email To ".$toaddr,4,"Flush","Email");
+ }
+ }
+
+ }
+ }
+
+
+
+ }
+ else if ($row['atype']=="url")
+ {
+ // url send
+ if ($row['etype']==0) $body=$row['mdata'];
+ else $body="FreeNATS Alert,\r\n".$row['mdata']."\r\n--FreeNATS @ ".nicedt(time());
+
+ $body=urlencode($body);
+ $tolist=array();
+ $f=0;
+ $tolist[0]="";
+ for ($a=0; $a0) fclose($fp);
+ else $this->Event("URL Alert Failed ".$url,1,"Flush","URL");
+ $this->Event("URL Alert ".$url,4,"Flush","URL");
+ }
+ }
+
+
+ }
+ else if ($row['atype']=="mqueue")
+ {
+ // message queue
+ $eventdata=array("aaid"=>$row['aaid'],"name"=>$row['aname'],"data"=>$row['mdata']);
+ $result=$this->EventHandler("alert_action",$eventdata);
+ if ($result===false) // put the data back into the queue
+ {
+ $q="UPDATE fnalertaction SET mdata=\"".$row['mdata']."\"+mdata WHERE aaid=".$row['aaid'];
+ $this->DB->Query($q);
+ if ($this->DB->Affected_Rows()<=0)
+ $this->Event("Persist MDATA Failed for AAID ".$row['aaid'],2,"Flush","MQueue");
+ }
+ else $this->Event("Queue Cleared for AAID ".$row['aaid']." by Handler",4,"Flush","MQueue");
+ }
+
+ }
+ }
+
+function GetAlerts()
+ {
+ $q="SELECT nodeid,alertlevel FROM fnalert WHERE closedx=0";
+ $r=$this->DB->Query($q);
+ $c=0;
+ $al=array();
+ while ($row=$this->DB->Fetch_Array($r))
+ {
+ $al[$c]['nodeid']=$row['nodeid'];
+ $al[$c]['alertlevel']=$row['alertlevel'];
+ $c++;
+ }
+ if ($c>0) return $al;
+ else return false;
+ }
+
+function SetAlerts($nodeid,$alertlevel,$alerts="")
+ {
+ if ($alerts=="") $alerts=array();
+ // get current alert level
+ $q="SELECT alertlevel,nodealert FROM fnnode WHERE nodeid=\"".ss($nodeid)."\"";
+ $r=$this->DB->Query($q);
+ $row=$this->DB->Fetch_Array($r);
+ $this->DB->Free($r);
+ $cal=$row['alertlevel'];
+
+ $eventdata=array("nodeid"=>$nodeid,"alertlevel"=>$alertlevel,
+ "oldalertlevel"=>$cal);
+ $this->EventHandler("set_alerts",$eventdata);
+
+ if ($alertlevel!=$cal)
+ {
+ // update table
+ $q="UPDATE fnnode SET alertlevel=".ss($alertlevel)." WHERE nodeid=\"".ss($nodeid)."\"";
+ $this->DB->Query($q);
+ }
+
+ // do not continue if node alert isn't set
+ if ($row['nodealert']!=1) return 0;
+ // or if untested
+ if ($alertlevel<0) return 0;
+
+ // ALERTS
+ // is there an existing alert for this node
+ $q="SELECT alertid,alertlevel FROM fnalert WHERE nodeid=\"".ss($nodeid)."\" AND closedx=0";
+ $r=$this->DB->Query($q);
+ if ($row=$this->DB->Fetch_Array($r))
+ { // yes there is
+ // if new alert level is 0 let's close it
+ if ($alertlevel==0)
+ {
+ $alertid=$row['alertid'];
+ $q="UPDATE fnalert SET closedx=".time()." WHERE alertid=".$row['alertid'];
+ $this->DB->Query($q);
+ $closetext=$this->Cfg->Get("site.text.closed","Alert Closed");
+ if (is_array($alerts)) $alerts[]=$closetext;
+ else
+ {
+ $alerts=array($alerts); // add as first element to new array
+ $alerts[]=$closetext;
+ }
+ $eventdata=array("nodeid"=>$nodeid);
+ $this->EventHandler("alert_close",$eventdata);
+ }
+ else
+ {
+ $alertid=$row['alertid'];
+ // otherwise update the alert to the new value (was: regardless, now just if not a 0)
+ $q="UPDATE fnalert SET alertlevel=".ss($alertlevel)." WHERE alertid=".$alertid;
+ $this->DB->Query($q);
+ }
+ }
+ else
+ { // no there's not
+ $cal=0; // the cal (current alert level) goes to zero if it's a new alert so alert_actions fire ok
+ if ($alertlevel>0) // only if an actual alert
+ {
+ $q="INSERT INTO fnalert(nodeid,alertlevel,openedx) VALUES(";
+ $q.="\"".ss($nodeid)."\",".ss($alertlevel).",".time().")";
+ $this->DB->Query($q);
+ $alertid=$this->DB->Insert_Id();
+ $eventdata=array("nodeid"=>$nodeid);
+ $this->EventHandler("alert_open",$eventdata);
+ }
+ }
+ // ALERT LOG with $alertid
+ $t=time();
+ $at="";
+ if (is_array($alerts))
+ {
+ foreach($alerts as $alert)
+ {
+ if (isset($alertid)) // misses on manual runs methinx
+ {
+ if ($at!="") $at.=", ";
+ $at.=$alert;
+ //echo $at."\n";
+ $iq="INSERT INTO fnalertlog(alertid,postedx,logentry) VALUES(";
+ $iq.=$alertid.",".$t.",\"".ss($alert)."\")";
+ //echo $iq;
+ $this->DB->Query($iq);
+ }
+ }
+ }
+
+ $this->AlertAction($nodeid,$alertlevel,$alertlevel-$cal,$at);
+
+
+
+ }
+
+function NodeAlertLevel($nodeid)
+ {
+ $q="SELECT alertlevel FROM fnnode WHERE nodeid=\"".ss($nodeid)."\"";
+ $r=$this->DB->Query($q);
+ if ($row=$this->DB->Fetch_Array($r)) return $row['alertlevel'];
+ else return -1;
+ }
+
+function GroupAlertLevel($groupid)
+ {
+ $lvl=-1;
+ $q="SELECT nodeid FROM fngrouplink WHERE groupid=\"".ss($groupid)."\"";
+ $r=$this->DB->Query($q);
+ while ($row=$this->DB->Fetch_Array($r))
+ {
+ $nl=$this->NodeAlertLevel($row['nodeid']);
+ if ($nl>$lvl) $lvl=$nl;
+ }
+ $this->DB->Free($r);
+ return $lvl;
+ }
+
+function PhoneHome($mode=0,$type="ping") // 0 - php, 1 - html, 2 - data
+{
+if ($mode<2)
+ {
+ $qs="?type=".$type."&data=v=".$this->Version;
+ if (isset($_SERVER['REMOTE_ADDR']))
+ $qs.=",ip=".$_SERVER['REMOTE_ADDR'];
+ $ploc="http://www.purplepixie.org/freenats/report/";
+ if ($mode==1) $ploc.="ping.html";
+ else $ploc.="ping.php";
+
+ $ploc.=$qs;
+
+ $lp=@fopen($ploc,"r");
+ if ($lp>0) @fclose($lp);
+ }
+else
+ {
+ // data post -- !!
+ }
+}
+
+function GetNode($nodeid)
+ {
+ $return_row=false;
+ $q="SELECT * FROM fnnode WHERE nodeid=\"".ss($nodeid)."\" LIMIT 0,1";
+ $r=$this->DB->Query($q);
+ if ($row=$this->DB->Fetch_Array($r))
+ $return_row=true;
+
+ $this->DB->Free($r);
+ if ($return_row) // found a valid
+ {
+ if ($row['nodename']!="") $row['name']=$row['nodename']; // make a "nice" name for it
+ else $row['name']=$row['nodeid'];
+
+ $row['alerttext']=oText($row['alertlevel']); // textual alert status
+
+ $row['lastrundt']=nicedt($row['lastrunx']); // text date-time last run
+ $row['lastrunago']=dtago($row['lastrunx'],false); // last run ago
+
+ // protection
+ $row['nskey']="";
+
+ return $row;
+ }
+ else
+ return false; // or failed
+ }
+
+function GetNodes()
+{
+ $out=array();
+ $q="SELECT * FROM fnnode";
+ $r=$this->DB->Query($q);
+
+ while ($row=$this->DB->Fetch_Array($r))
+ {
+ if ($row['nodename']!="") $row['name']=$row['nodename']; // make a "nice" name for it
+ else $row['name']=$row['nodeid'];
+
+ $row['alerttext']=oText($row['alertlevel']); // textual alert status
+
+ $row['lastrundt']=nicedt($row['lastrunx']); // text date-time last run
+ $row['lastrunago']=dtago($row['lastrunx'],false); // last run ago
+
+ // protection
+ $row['nskey']="";
+
+ $out[$row['nodeid']]=$row;
+ }
+ $this->DB->Free($r);
+
+ return $out;
+}
+
+
+function GetNodeTests($nodeid)
+ { // returns an array of testids for the node (enabled tests only)
+ $tests=array();
+
+ // local tests
+ $q="SELECT localtestid FROM fnlocaltest WHERE testenabled=1 AND nodeid=\"".ss($nodeid)."\" ORDER BY localtestid ASC";
+ $r=$this->DB->Query($q);
+ while ($row=$this->DB->Fetch_Array($r))
+ {
+ $tests[]="L".$row['localtestid'];
+ }
+ $this->DB->Free($r);
+
+ // nodeside
+ $q="SELECT nstestid FROM fnnstest WHERE testenabled=1 AND nodeid=\"".ss($nodeid)."\" ORDER BY testtype ASC";
+ $r=$this->DB->Query($q);
+ while ($row=$this->DB->Fetch_Array($r))
+ {
+ $tests[]="N".$row['nstestid'];
+ }
+ $this->DB->Free($r);
+
+ return $tests;
+ }
+
+function SetNode($nodeid,$data)
+ {
+ $q="UPDATE fnnode SET ";
+ $first=true;
+ foreach($data as $key => $val)
+ {
+ if ($first) $first=false;
+ else $q.=",";
+ $q.=ss($key)."=\"".ss($val)."\"";
+ }
+ $q.=" WHERE nodeid=\"".ss($nodeid)."\"";
+ $this->DB->Query($q);
+ if ($this->DB->Affected_Rows()>0) return true;
+
+ if ($this->DB->Error()) // query failed
+ {
+ $errstr1="Query Failed: ".$q;
+ $errstr2="Query Failed: ".$this->DB->Error_String();
+ $this->Event($errstr1,2,"Node","Set");
+ $this->Event($errstr1,2,"Node","Set");
+ return false;
+ }
+ return true; // query succeeded but nothing was updated
+ }
+
+function EnableNode($nodeid,$enabled=true)
+ {
+ if ($enabled) $ne=1;
+ else $ne=0;
+ $data=array("nodeenabled"=>$ne);
+ return $this->SetNode($nodeid,$data);
+ }
+
+function DisableNode($nodeid)
+ {
+ return $this->EnableNode($nodeid,false);
+ }
+
+function SetNodeSchedule($nodeid,$scheduleid)
+ {
+ $data=array("scheduleid"=>$scheduleid);
+ return $this->SetNode($nodeid,$data);
+ }
+
+function GetGroup($groupid)
+ {
+ $q="SELECT * FROM fngroup WHERE groupid=".ss($groupid)." LIMIT 0,1";
+ $r=$this->DB->Query($q);
+ if (!$row=$this->DB->Fetch_Array($r)) return false;
+
+ $this->DB->Free($r);
+ $row['alertlevel']=$this->GroupAlertLevel($groupid);
+ $row['alerttext']=oText($row['alertlevel']);
+ return $row;
+ }
+
+function GetGroups()
+{
+ $out=array();
+ $q="SELECT * FROM fngroup";
+ $r=$this->DB->Query($q);
+
+ while ($row=$this->DB->Fetch_Array($r))
+ {
+ $row['alertlevel']=$this->GroupAlertLevel($row['groupid']);
+ $row['alerttext']=oText($row['alertlevel']);
+ $out[$row['groupid']]=$row;
+ }
+
+ $this->DB->Free($r);
+ return $out;
+}
+
+function GetTest($testid,$protect=false)
+ {
+ if ($testid=="") return false;
+ $class=$testid[0];
+ if (is_numeric($class))
+ {
+ // test ID will stay the same
+ $class="L";
+ $anytestid=$testid;
+ }
+ else
+ {
+ //$testid=substr($testid,1); // as it will here also so direct use to graphs can be made
+ $anytestid=substr($testid,1); // the classless version
+ }
+
+ $q="";
+ switch($class)
+ {
+ case "L": // local tests
+ $q="SELECT * FROM fnlocaltest WHERE localtestid=".ss($anytestid)." LIMIT 0,1";
+ break;
+ case "N": // node-side test
+ $q="SELECT * FROM fnnstest WHERE nstestid=".ss($anytestid)." LIMIT 0,1";
+ break;
+ default:
+ return false; // can't lookup this class
+ }
+
+ if ($q=="") return false;
+
+ $r=$this->DB->Query($q);
+
+ if (!$row=$this->DB->Fetch_Array($r)) return false;
+
+ $row['class']=$class;
+ $row['testid']=$testid;
+ $row['anytestid']=$anytestid;
+ $row['alerttext']=oText($row['alertlevel']);
+ $row['lastrundt']=nicedt($row['lastrunx']);
+ $row['lastrunago']=dtago($row['lastrunx'],false);
+
+ if ($row['testname']!="") $row['name']=$row['testname'];
+ else
+ {
+ if ($class=="L")
+ {
+ $row['name']=lText($row['testtype']); // TODO OTHER TESTS
+ if ($row['testparam']!="") $row['name'].=" (".$row['testparam'].")";
+ }
+ else if ($class=="N")
+ {
+ if ($row['testdesc']!="") $row['name']=$row['testdesc'];
+ else $row['name']=$row['testtype'];
+ }
+ }
+
+ if ($protect&&($class=="L")) // module test protection
+ {
+ if ($this->Tests->Exists($row['testtype'])) // in the module register
+ {
+ $this->Tests->Tests[$row['testtype']]->Create();
+ $this->Tests->Tests[$row['testtype']]->instance->ProtectOutput($row);
+ }
+ }
+
+ $this->DB->Free($r);
+
+ return $row;
+ }
+
+
+function DeleteTest($testid)
+ {
+ if ($testid=="") return false;
+ $class=$testid[0];
+ if (is_numeric($class))
+ {
+ // test ID will stay the same
+ $class="L";
+ $anytestid=$testid;
+ }
+ else
+ {
+ $anytestid=substr($testid,1); // the classless version
+ }
+
+ $q="";
+ switch($class)
+ {
+ case "L": // local tests
+ $q="DELETE FROM fnlocaltest WHERE localtestid=".ss($anytestid);
+ break;
+ case "N": // node-side test
+ $q="DELETE FROM fnnstest WHERE nstestid=".ss($anytestid);
+ break;
+ default:
+ return false; // can't lookup this class
+ }
+
+ if ($q=="") return false;
+
+ $this->DB->Query($q);
+ $tests=$this->DB->Affected_Rows();
+
+ $rq="DELETE FROM fnrecord WHERE testid=\"".ss($testid)."\"";
+ $this->DB->Query($rq);
+ $records=$this->DB->Affected_Rows();
+
+ $eq="DELETE FROM fneval WHERE testid=\"".ss($testid)."\"";
+ $this->DB->Query($eq);
+ $eval=$this->DB->Affected_Rows();
+
+ $s="Deleted test ".$testid." (".$tests." tests, ".$records." records, ".$eval." evaluators)";
+ $this->Event($s,6,"Test","Delete");
+ }
+
+
+
+function InvalidateTest($testid,$rightnow=false)
+ {
+ $class=$testid[0];
+ if (is_numeric($class)) $class="L";
+ else $testid=substr($testid,1);
+ if ($rightnow)
+ {
+ $nextx=time();
+ $q="UPDATE ";
+ if ($class=="L") $q.="fnlocaltest";
+ // other ones here
+
+ $q.=" SET nextrunx=".$nextx." WHERE ";
+
+ if ($class=="L") $q.="localtestid=".$testid;
+ // other ones here
+
+ $this->DB->Query($q);
+ return true;
+ }
+ // otherwise use it's interval
+ $q="SELECT testinterval FROM ";
+
+ if ($class=="L") $q.="fnlocaltest WHERE localtestid=";
+ // other ones here
+
+ $q.=$testid;
+ $r=$this->DB->Query($q);
+ if ($row=$this->DB->Fetch_Array($r))
+ {
+ $this->DB->Free($r);
+ $nextx=next_run_x($row['testinterval']);
+ $q="UPDATE ";
+ if ($class=="L") $q.="fnlocaltest";
+ // other ones here
+
+ $q.=" SET nextrunx=".$nextx." WHERE ";
+
+ if ($class=="L") $q.="localtestid=".$testid;
+ // other ones here
+
+ $this->DB->Query($q);
+ return true;
+ }
+ return false;
+ }
+
+function InvalidateNode($nodeid,$rightnow=false,$testsaswell=false)
+ {
+ if ($rightnow)
+ {
+ $nextx=time();
+ $q="UPDATE fnnode SET nextrunx=".$nextx." WHERE nodeid=\"".ss($nodeid)."\"";
+ $this->DB->Query($q);
+ if ($testsaswell)
+ {
+ $q="UPDATE fnlocaltest SET nextrunx=".$nextx." WHERE nodeid=\"".ss($nodeid)."\"";
+ $this->DB->Query($q);
+ }
+ return true;
+ }
+ // otherwise set to it's interval
+ $q="SELECT testinterval FROM fnnode WHERE nodeid=\"".ss($nodeid)."\"";
+ $r=$this->DB->Query($q);
+ if ($row=$this->DB->Fetch_Array($r))
+ {
+ $nextx=next_run_x($row['testinterval']);
+ $uq="UPDATE fnnode SET nextrunx=".$nextx." WHERE nodeid=\"".ss($nodeid)."\"";
+ $this->DB->Query($uq);
+ $this->DB->Free($r);
+ if ($testsaswell)
+ {
+ $uq="UPDATE fnlocaltest SET nextrunx=".$nextx." WHERE nodeid=\"".ss($nodeid)."\"";
+ $this->DB->Query($uq);
+ }
+ return true;
+ }
+ return false;
+ }
+
+
+function NodeSide_Pull($nodeid)
+ {
+ $eventdata=array("nodeid"=>$nodeid,"success"=>false);
+ $q="SELECT nsenabled,nspullenabled,nsurl,nskey,nsinterval FROM fnnode WHERE nodeid=\"".ss($nodeid)."\" LIMIT 0,1";
+ $r=$this->DB->Query($q);
+ if (!$row=$this->DB->Fetch_Array($r)) return false;
+
+ $this->DB->Free($r);
+
+ $url=$row['nsurl'];
+ if ($row['nskey']!="") $url.="?nodekey=".$row['nskey'];
+ //echo $url."\n";
+ $this->Event("NodeSide_Pull Started for ".$nodeid,10,"Node","Pull");
+
+ $xmlobj=new TNodeXML();
+
+ $fp=@fopen($url,"r");
+ if ($fp<=0)
+ {
+ $this->Event("Pull Failed URL ".$url,1,"Node","Pull");
+ $this->EventHandler("nodeside_pull",$eventdata);
+ return false;
+ }
+ $xml="";
+ while (!feof($fp))
+ {
+ $xml.=fgets($fp,4096);
+ }
+ if ($xml=="")
+ {
+ $this->EventHandler("nodeside_pull",$eventdata);
+ return false;
+ }
+
+ //echo $xml;
+
+ $result=$xmlobj->Parse($xml);
+
+ if ($xmlobj->Error()!="")
+ {
+ $this->Event("NodeXML Error: ".$xmlobj->Error(),1,"Node","Pull");
+ $this->EventHandler("nodeside_pull",$eventdata);
+ return false;
+ }
+ $this->Event("NodeSide_Pull Fetched ".$xmlobj->Tests." tests for ".$nodeid,10,"Node","Pull");
+ // Now just to actually process it...
+ $eventdata['success']=true;
+ $this->EventHandler("nodeside_pull",$eventdata);
+ $this->NodeSide_Process($nodeid,$xmlobj);
+ return true;
+ }
+
+function NodeSide_Process($nodeid,&$xmlobj)
+ { // nodeid + takes a TNodeXML Object
+ $alvl=0;
+ $this->Event("NodeSide_Process for ".$nodeid,10,"Node","Pull");
+ $q="SELECT * FROM fnnstest WHERE nodeid=\"".ss($nodeid)."\"";
+ $r=$this->DB->Query($q);
+ $tests=array();
+ while ($row=$this->DB->Fetch_Array($r))
+ {
+ $tests[$row['testtype']]=$row;
+ if (isset($xmlobj->Catalogue[$row['testtype']]))
+ { // this test is in the DB and catalogue
+ $tests[$row['testtype']]['incat']=true;
+ if ($row['testenabled']==1) // it is enabled - so we test it
+ {
+ if ($row['simpleeval']==1) $level=$xmlobj->Catalogue[$row['testtype']]['ALERTLEVEL']; // use provided level
+ else $level=nats_eval("N".$row['nstestid'],$xmlobj->Catalogue[$row['testtype']]['VALUE']);
+ $dbs="Nodeside ".$row['testtype']." on ".$row['nodeid']." = ".$level;
+ if ($level==0) $debuglev=8;
+ else if ($level>0) $debuglev=5;
+ else $debuglev=2;
+ $this->Event($dbs,$debuglev,"Node","Process");
+
+ if ($level>$alvl) $alvl=$level;
+
+ if ($row['testrecord']==1) // record it
+ {
+ $testvalue=$xmlobj->Catalogue[$row['testtype']]['VALUE'];
+ $testvalue=str_replace(",",".",$testvalue);
+ if (!is_numeric($testvalue)) $testvalue=0;
+ $iq="INSERT INTO fnrecord(testid,alertlevel,recordx,nodeid,testvalue) VALUES(";
+ $iq.="\"N".$row['nstestid']."\",".$level.",".time().",\"".$row['nodeid']."\",".$testvalue.")";
+ $this->DB->Query($iq);
+ if ($this->DB->Affected_Rows()<=0)
+ $this->Event("Nodeside ".$row['testtype']." Failed to Record",1,"Node","Process");
+ }
+
+ // We don't do any alerting here - the tester will do that for us!
+ $uq="UPDATE fnnstest SET lastrunx=".time().",lastvalue=\"".ss($xmlobj->Catalogue[$row['testtype']]['VALUE'])."\",alertlevel=".$level." ";
+ $uq.="WHERE nstestid=".$row['nstestid'];
+ $this->DB->Query($uq);
+ if ($this->DB->Affected_Rows()<=0)
+ $this->Event("Nodeside ".$row['testtype']." Failed to Update or Same Values",5,"Node","Process");
+
+ }
+
+ // check to see if the desc has changed
+ if ($row['testdesc']!=$xmlobj->Catalogue[$row['testtype']]['DESC'])
+ {
+ $duq="UPDATE fnnstest SET testdesc=\"".ss($xmlobj->Catalogue[$row['testtype']]['DESC'])."\" WHERE nstestid=".$row['nstestid'];
+ $this->DB->Query($duq);
+ }
+
+ }
+ else
+ {
+ // test in the DB but NOT in the catalogue
+ //$xmlobj->Catalogue[$row['testtype']]['incat']=false;
+ if ($row['testenabled']==1)
+ { // enabled so shown in lists etc
+ // Update it to show failed status
+ $this->Event("No nodeside data for test N".$row['nstestid'],3,"Node","Process");
+ $uq="UPDATE fnnstest SET alertlevel=2,lastvalue=-1 WHERE nstestid=".$row['nstestid'];
+ $this->DB->Query($uq);
+ $alvl=2;
+ if ($row['testrecord']==1) // record it
+ {
+ $testvalue=-1;
+ $iq="INSERT INTO fnrecord(testid,alertlevel,recordx,nodeid,testvalue) VALUES(";
+ $iq.="\"N".$row['nstestid']."\",2,".time().",\"".$row['nodeid']."\",".$testvalue.")";
+ $this->DB->Query($iq);
+ if ($this->DB->Affected_Rows()<=0)
+ $this->Event("Nodeside ".$row['testtype']." Failed to Record",1,"Node","Process");
+ }
+ }
+ else // not enabled so simply delete
+ {
+ $this->DeleteTest("N".$row['nstestid']);
+ }
+ }
+ }
+ $this->DB->Free($r);
+
+
+ // and finally we look for new tests i.e. in the cat but not in the DB
+ foreach($xmlobj->Catalogue as $val)
+ {
+ $key=$val['NAME'];
+ if (!isset($tests[$key])) // not in the DB
+ {
+ $q="INSERT INTO fnnstest(nodeid,testtype,testdesc,lastvalue,lastrunx,alertlevel) ";
+ $q.="VALUES(\"".ss($nodeid)."\",\"".$key."\",\"".ss($val['DESC'])."\",\"".ss($val['VALUE'])."\",".time().",".ss($val['ALERTLEVEL']).")";
+ //echo $q." ";
+ $this->DB->Query($q);
+ }
+ }
+
+ $eventdata=array("nodeid"=>$nodeid,"alertlevel"=>$alvl);
+ $this->EventHandler("nodeside_process",$eventdata);
+
+
+ }
+
+
+function AddEventHandler($event,$function)
+{
+ if (!isset($this->EventHandlers[$event])) $this->EventHandlers[$event]=array();
+ $this->EventHandlers[$event][]=$function;
+}
+
+function EventHandler($event,$data)
+{
+ $res=false;
+ if ( isset($data) && is_array($data) ) $data['event']=$event;
+
+ if (isset($this->EventHandlers[$event])) // handler(s) exist
+ {
+ for($a=0; $aEventHandlers[$event]); $a++)
+ {
+ if (function_exists($this->EventHandlers[$event][$a]))
+ {
+ $this->Event("Event ".$event." -> ".$this->EventHandlers[$event][$a],6,"Event","Handler");
+ if($this->EventHandlers[$event][$a]($data)) $res=true; // persist true only
+ }
+ else
+ {
+ $t="Illegal Handler ".$this->EventHandlers[$event][$a]." for ".$event;
+ $this->Event($t,2,"Event","Handler");
+ //return false;
+ }
+ }
+ }
+ else return $res;
+}
+
+function StripGPC($data)
+{
+ if (get_magic_quotes_gpc()) return stripslashes($data);
+ else return $data;
+}
+
+function PageError($code,$desc)
+{
+$this->PageErrors[]=array( "code" => $code, "desc" => $desc );
+}
+
+}
+?>
diff --git a/src/server/base/help.inc.php b/src/server/base/help.inc.php
new file mode 100755
index 0000000..8c1bcc8
--- /dev/null
+++ b/src/server/base/help.inc.php
@@ -0,0 +1,214 @@
+Lang->Item("help.".strtoupper($id));
+$o="";
+$mode="text";
+$linktext=false;
+for ($a=0; $a";
+ $o.=$linktxt;
+ if ($html) $o.="";
+ $mode="text";
+ }
+
+ else if ( $mode=="link" ) // in a link
+ {
+ if ($linktext) $linktxt.=$c;
+ else $linkid.=$c;
+ }
+
+ else // in text
+ $o.=$c;
+ }
+return $o;
+}
+
+function hlink($id,$size=16)
+{
+global $NATS;
+if (isset($NATS->Lang->items["help.".strtoupper($id)]))
+ return "";
+
+return "Lang->Item("nohelp")." (".$id.")\">";
+}
+
+function ph($id,$size=16)
+{
+echo hlink($id,$size);
+}
+?>
\ No newline at end of file
diff --git a/src/server/base/lang/English.en.lang.php b/src/server/base/lang/English.en.lang.php
new file mode 100755
index 0000000..ae418a7
--- /dev/null
+++ b/src/server/base/lang/English.en.lang.php
@@ -0,0 +1,608 @@
+website. It is recommended you check regularly. You are currently running version";
+$lang['monitor.alerts']="Monitoring Alerts";
+$lang['no.monitor.alerts']="No Monitoring Alerts";
+$lang['check.updates']="Check for Updates";
+$lang['monitoring']="Monitoring";
+$lang['nodes.configured']="Nodes Configured";
+$lang['node.groups']="Node Groups";
+$lang['common.tasks']="Common Tasks";
+$lang['add.nodes']="Add Nodes";
+$lang['email.alerting']="Email Alerting";
+$lang['configure.tests']="Configure Tests";
+$lang['test.summaries']="Test Summaries";
+$lang['monitored.nodes']="Monitored Nodes";
+$lang['freenats.news']="FreeNATS News";
+
+// nodes already
+$lang['node']="Node";
+$lang['options']="Options";
+$lang['move']="Move";
+$lang['edit']="Edit Options";
+$lang['delete']="Delete";
+$lang['create.node']="Create Node";
+$lang['config']="Configuration";
+$lang['move.before']="Move Before";
+$lang['go']="Go";
+$lang['refresh.weight']="Refresh Weighting";
+
+$lang['node.groups']="Node Groups";
+$lang['create.group']="Create Group";
+
+$lang['views']="Views";
+$lang['create.view']="Create New View";
+$lang['reports']="Availability Reports";
+$lang['create.report']="Create a New Service Availability Report";
+
+$lang['config.summary']="Configuration Summary / Overview";
+$lang['configuration']="Configuration";
+$lang['nodeid']="Node ID";
+$lang['name']="Name";
+$lang['hostname']="Hostname";
+$lang['schedule']="Schedule";
+$lang['enabled']="Enabled";
+$lang['ping']="Ping";
+$lang['required']="Required";
+$lang['interval']="Interval";
+$lang['nodeside']="Nodeside";
+
+// Time Periods
+$lang['today']="Today";
+$lang['last.24h']="Last 24 Hours";
+$lang['custom']="Custom";
+$lang['ago']="ago";
+$lang['never']="never";
+
+// User Preferences
+$lang['user.pref']="User Preferences";
+$lang['change.password']="Change Password";
+$lang['current']="Current";
+$lang['new']="New";
+$lang['confirm']="Confirm";
+$lang['pass.change.ok']="Password Changed";
+$lang['pass.change.fail']="Password Change Failed";
+
+// Administration Settings
+$lang['admin.interface']="Administration Interface";
+$lang['user.admin']="User Administration";
+$lang['event.log']="System Event Log";
+$lang['alert.actions']="Alert Actions";
+$lang['variables']="System Variables";
+$lang['sessions']="Test Sessions";
+$lang['schedules']="Test and Alert Schedules";
+$lang['file.manager']="File Manager";
+$lang['sql.console']="SQL Console";
+$lang['dns.console']="DNS Query Console";
+$lang['backup.restore']="Backup and Restore";
+$lang['sys.status']="System Status Report";
+$lang['sys.info']="System Information";
+
+$lang['tests.alerting']="Tests and Alerting";
+$lang['tools']="Tools";
+$lang['logs.info']="Logs and System Information";
+
+$lang['ul.admin']="Administrator";
+$lang['ul.power']="Power User";
+$lang['ul.normal']="Normal User";
+$lang['ul.disabled']="Disabled";
+
+$lang['aae.short']="Short";
+$lang['aae.long']="Long";
+
+$lang['unknown']="Unknown";
+
+$lang['aae.sub.blank']="Blank";
+$lang['aae.sub.short']="Short";
+$lang['aae.sub.long']="Long";
+
+$lang['aatype.email']="Email";
+$lang['aatype.mqueue']="Message Queue";
+$lang['aatype.url']="URL";
+$lang['aatype.disabled']="Disabled";
+
+$lang['real.name']="Real Name";
+$lang['user.level']="User Level";
+$lang['create.user']="Create User";
+
+$lang['save']="Save";
+
+$lang['sessions.for']="Node test sessions for";
+$lang['sessions.running']="Running Test Sessions";
+$lang['sessions.running.for']="Running Test Sessions for";
+$lang['sessions.not.running']="No running test sessions";
+$lang['sessions.previous']="Previous Test Sessions for";
+$lang['sessions.previous.none']="No Previous Test Sessions";
+$lang['sessions.stillrunning']="Still Running";
+$lang['started']="Started";
+$lang['finished']="Finished";
+$lang['node.filter']="Node Filter";
+$lang['output']="Output";
+$lang['allnodes']="All Nodes";
+
+$lang['test.run']="Test Run";
+$lang['testrun.manual.close']="Manually Close Test Session";
+$lang['testrun.manual.close.detail']="Are you sure you want to do this? Only close sessions that you're sure aren't still running in the background. This does not kill processes - just marks the test session as complete.";
+$lang['testrun.del.yes']="Yes - Delete";
+$lang['testrun.del.cancel']="No - Cancel";
+$lang['testrun.session.closed']="Test Session Closed";
+$lang['testrun.fetch.error']="Error Fetching Testrun Data";
+
+$lang['confirm.action']="Confirm Action";
+
+
+$lang['alert.actions']="Alert Actions";
+$lang['id']="ID";
+$lang['aa.name']="Action Name";
+$lang['aa.type']="Action Type";
+$lang['aa.create']="Create New Alert Action";
+$lang['aa.limit']="Action Limit";
+$lang['aa.counter']="Action Counter";
+$lang['aa.efrom']="Email From";
+$lang['aa.esubj']="Email Subject";
+$lang['aa.mtype']="Msg Type";
+$lang['aa.eto']="Email To or URL";
+$lang['aa.update']="Update Action";
+$lang['aa.test']="Test Action";
+$lang['aa.cancel']="Cancel Update";
+$lang['aa.delete']="Delete Action";
+$lang['aa.testflush']="Alert Action Tested & Flushed";
+
+
+$lang['system.status']="System Status";
+$lang['status.size']="Table Sizes";
+$lang['status.tname']="Table Name";
+$lang['status.tsize']="Size (Rows)";
+$lang['status.tsize.kb']="Size (Kb)";
+$lang['status.tother']="Other Information";
+$lang['status.free']="Free";
+$lang['status.optimise']="Optimise";
+
+$lang['notes']="Notes";
+
+$lang['status.running']="Open/Running Test Sessions";
+$lang['status.run.warn']="Warning: Over 15 Minutes Old";
+$lang['status.run.error']="Error: Over 1 Hour Old";
+
+$lang['status.env.http']="Environment: PHP Web (Apache Module/PHP-CGI)";
+$lang['status.env.cli']="Environment: PHP CLI (Command-Line Binary)";
+
+$lang['status.disclaim']="Please note this merely displays FreeNATS software status - not the status of the underlying Virtual Machine (if applicable).
You should monitor disk space and performance for the VM via the relevant system (such as the rPath interface).
";
+
+$lang['warnings']="Warnings";
+$lang['decreases']="Decreases";
+$lang['create']="Create";
+
+$lang['version.info']="Version Information";
+$lang['version']="Version";
+$lang['release']="Release";
+$lang['compound']="Compound";
+
+$lang['reg.modules']="Registered Test Modules";
+$lang['provides']="Provides";
+$lang['revision']="Revision";
+$lang['additional']="Additional";
+$lang['reg.events']="Registered Event Handlers";
+$lang['event']="Event";
+$lang['handlers']="Handler(s)";
+$lang['reg.languages']="Registered Languages";
+
+$lang['back.to.admin']="Back to Main System Settings Menu";
+
+$lang['save.user.fail']="Save User Failed or Nothing Changed";
+$lang['save.user.ok']="User Saved";
+$lang['create.user.fail']="Failed to Create User";
+$lang['create.user.ok']="User Created";
+$lang['delete.user']="Delete User";
+$lang['user.deleted']="User Deleted";
+$lang['save.var.ok']="Updated or Deleted Variable";
+$lang['save.var.fail']="Failed to Update Variable";
+$lang['new.var.ok']="Created Variable";
+$lang['new.var.fail']="Failed to Create Variable";
+$lang['optimised.ok']="Optimised Table";
+
+$lang['changes.ok']="Changes Saved";
+$lang['changes.fail']="Failed to Save Changes or Nothing Changed";
+$lang['delete.ok']="Deleted Ok";
+
+// System Event Log
+$lang['filter']="Filter";
+$lang['show']="Show";
+$lang['filter.log']="Filter Log Entries and Display";
+$lang['reset']="Reset";
+$lang['next']="Next";
+$lang['prev']="Previous";
+
+
+// Live Monitor
+$lang['live.monitor']="Live Monitor";
+$lang['mon.options']="options...";
+$lang['group.name']="Group Name";
+$lang['description']="Description";
+$lang['status']="Status";
+$lang['node.name']="Node Name";
+$lang['mon.std']="standard";
+$lang['mon.grp']="groups";
+$lang['mon.nodes']="nodes";
+$lang['mon.alerting']="alerting";
+$lang['mon.hide']="...hide...";
+$lang['mon.goto.node']="Goto Node";
+$lang['mon.goto.node.page']="Goto Node Page";
+$lang['mon.popup.error']="Invalid or Illegal Node";
+
+// Node Page
+$lang['viewing.node']="Viewing Node";
+$lang['no.node']="No such node";
+$lang['enabled']="Enabled";
+$lang['alert']="Alert";
+$lang['yes']="Yes";
+$lang['no']="No";
+$lang['alert.history']="Alert History";
+$lang['summary']="Summary";
+$lang['links']="Links";
+$lang['opened']="Opened";
+$lang['edit.node.options']="Edit Node Options";
+$lang['nodeside.tests']="Nodeside Tests";
+
+$lang['local.tests']="Local Tests";
+$lang['history']="History";
+
+$lang['email.alerting']="Email Alerting";
+
+$lang['no.test']="No Tests Configured";
+
+// Edit Node Options
+$lang['node.editor']="Node Editor";
+$lang['editing']="Editing";
+$lang['node.settings']="Node Settings";
+$lang['show.hide.options']="Show / Hide Node Options";
+$lang['node.tests']="Node Tests";
+$lang['last.tested']="Last Tested";
+$lang['add.test']="Add Test";
+$lang['no.such.node']="No Such Node";
+$lang['create.test']="Create Test";
+$lang['update.alert.actions']="Update Alert Actions";
+$lang['add']="Add";
+
+$lang['add.nodeside']="Add Nodeside Monitor";
+
+$lang['web.time']="Web Time";
+$lang['web.size']="Web Size";
+$lang['host']="Simple DNS Host";
+$lang['remote.ping']="Remote Ping";
+$lang['test.loop']="Test Loop";
+$lang['test.random']="Test Random";
+
+$lang['node.id']="Node ID";
+$lang['node.icon']="Node Icon";
+$lang['default']="Default";
+$lang['show.hide.icons']="Show/Hide Icons";
+$lang['master.node']="Master Node";
+$lang['no.master']="No Master Node";
+$lang['master.skip']="Skip if Master";
+$lang['fails.ping']="Fails Ping";
+$lang['fails.any.test']="Fails Any Test";
+$lang['node.enabled']="Node Enabled";
+$lang['test.schedule']="Test Schedule";
+$lang['test.interval']="Test Interval";
+$lang['test.due']="Test Due";
+$lang['check.asap']="Check ASAP";
+$lang['alerts.active']="Alerts Active";
+$lang['ping.test']="Ping Test";
+$lang['require.ping']="Require Ping";
+$lang['nodeside.testing']="Nodeside Testing";
+$lang['node.key']="Node Key";
+$lang['pull.enabled']="Pull Enabled";
+$lang['pull.url']="Pull URL";
+$lang['pull.interval']="Pull Interval";
+$lang['push.enabled']="Push Enabled";
+$lang['push.ip']="Push IP";
+$lang['last.date']="Last Data";
+$lang['next.pull.due']="Next Pull Due";
+$lang['catalogue']="Catalogue";
+$lang['nodeside.monitors']="Nodeside Monitors";
+$lang['refresh.now']="Refresh Now";
+$lang['nodeside.pull.now']="Refresh (Pull) Now";
+$lang['utility.links']="Utility Links";
+$lang['title']="Title";
+$lang['url']="URL";
+$lang['debug.raw']="Debug Raw Output";
+$lang['last.data']="Last Data";
+$lang['save.settings']="Save Settings";
+$lang['cancel']="Cancel";
+
+$lang['nodeside.pull.disabled']="Nodeside Pull Disabled";
+
+$lang['minutes']="Minutes";
+$lang['now']="Now";
+$lang['edit.options']="Edit Options";
+
+$lang['save.ok']="Changes Saved";
+$lang['save.failed']="Changes Failed to Save or Nothing Changed";
+$lang['save.fail']=$lang['save.failed'];
+
+// Group
+$lang['group.settings']="Group Settings";
+
+
+// Test Editing
+$lang['local.test.editor']="Local Test Editor";
+$lang['editing.test']="Editing Test";
+$lang['test.settings']="Test Settings";
+$lang['test.type']="Test Type";
+$lang['test.options']="Test Options";
+
+$lang['full.url']="Full URL including prefix e.g. http://www.somehost.com/";
+$lang['host.ip']="Host or IP";
+$lang['host.desc']="Hostname or IP to ping (DNS resolution not timed)";
+$lang['value']="Value";
+$lang['value.desc']="Value for Test Loop or Max Value for Test Random";
+$lang['host']="Host";
+$lang['host.desc']="Hostname to resolve or IP address to do reverse lookup of";
+
+$lang['no.test.options']="No Options for Test";
+
+$lang['custom.name']="Custom Name";
+$lang['test.enabled']="Test Enabled";
+$lang['recorded']="Recorded";
+$lang['simple.eval']="Simple Evaluation";
+$lang['test.interval']="Test Interval";
+$lang['test.due']="Test Due";
+$lang['last.tested']="Last Tested";
+
+$lang['custom.attempts']="Custom Attempts";
+$lang['custom.timeout']="Custom Timeout";
+
+$lang['test.save']="Save Test Settings";
+$lang['abandon.changes']="Abandon Changes";
+
+$lang['seconds']="Seconds";
+
+$lang['passed']="Passed";
+$lang['untested']="Untested";
+$lang['warning']="Warning";
+$lang['failed']="Failed";
+$lang['failure']="Failure";
+
+$lang['test.evals']="Custom Test Evaluators";
+$lang['test.evals.simple']="Custom evaluators will not be parsed as Simple Evaluation is checked (above)";
+$lang['add.eval']="Add New";
+$lang['eval.equal']="Equal To";
+$lang['eval.lt']="Less Than";
+$lang['eval.gt']="Greater Than";
+$lang['eval.deleted']="Evaluator Deleted";
+
+
+$lang['edit.nodeside.test']="Nodeside Test Editor";
+$lang['ns.type']="Test Type / UID";
+$lang['nodeside.test']="Nodeside Test";
+$lang['test.alerts']="Test Alerts";
+$lang['last.checked']="Last Checked";
+$lang['last.result']="Last Result";
+$lang['last.value']="Last Value";
+$lang['save.changes']="Save Changes";
+
+$lang['result']="Result";
+
+$lang['edit.view']="Edit View";
+$lang['editing.view']="Editing View";
+$lang['no.such.view']="No Such View";
+$lang['preview']="Preview";
+$lang['linking']="Linking";
+$lang['unknown.action']="Unknown Action";
+$lang['expand.view.options']="Expand View Options";
+
+$lang['node.ping']="Node Ping";
+
+$lang['host.ip.lookup']="IP Address Lookup";
+
+// Group Editor
+$lang['group.editor']="Group Editor";
+$lang['no.group']="Group Not Found";
+$lang['group.id']="Group ID";
+$lang['group.name']="Group Name";
+$lang['group.icon']="Group Icon";
+$lang['group.save']="Save Group Settings";
+$lang['group.members']="Group Members";
+$lang['group.update']="Update Group Member List";
+$lang['group.updated']="Group Membership Updated";
+$lang['group']="Group";
+$lang['editing']="Editing";
+
+$lang['show.icons']="Show Icons";
+
+$lang['dns.host']="DNS Host Lookup";
+
+// Security Warnings
+$lang['sec.firstrun']="Security Warning: firstrun.php Script is Exposed";
+$lang['sec.firstrun.text']="The firstrun.php script in your web directory has not been renamed. This could be used to damage FreeNATS. Please rename to firstrun-.php.";
+$lang['sec.firstrun.ignore']="To stop this warning from being shown without renaming the script (not recommended) set site.firstrun.ignore to 1";
+
+// RSS
+$lang['rss.feed']="RSS Feed Management";
+$lang['rss.feed.name']="Feed Name";
+$lang['rss.feed.key']="Feed Key";
+$lang['rss.type']="Type of Feed";
+$lang['all.enabled.nodes']="All Enabled Nodes";
+$lang['one.node']="Single Node";
+$lang['rss.range']="Range/Scope of Feed";
+$lang['last.x.days']="Last X Days";
+$lang['last.x.alerts']="Last X Alerts";
+$lang['current.alerts']="Current Alerts";
+$lang['last.alerts.node']="Last Alert for Each Node";
+$lang['rss.feeds']="FreeNATS RSS Feeds";
+$lang['feed.url']="RSS Feed URL";
+$lang['feed.create']="Create New Feed";
+$lang['no.feeds']="No RSS Feeds Configured";
+$lang['open']="Open";
+$lang['closed']="Closed";
+
+
+$lang['help']="Help";
+// Help - Text support NATS_Help format strings i.e. {link} and {link|text} links
+$lang['nohelp'] = "Sorry no help is available";
+$lang['help.FREENATS'] = "FreeNATS is a network monitoring package";
+$lang['help.NODE'] = "A node is a system or device which you are monitoring. Note that nodes can have tests pointing to different physical devices and vice-versa";
+$lang['help.NODE:CREATE'] = "Create a new {node} with this {node:id|NodeID}";
+$lang['help.NODE:ID'] = "The NodeID is a unique text name for a {node}. Maximum length 60 chars and only normal characters allowed.";
+$lang['help.NODE:ENABLED'] = "The node is enabled for tests to be performed (and displayed in all applicable views)";
+$lang['help.NODE:ALERTACTIVE'] = "Alerts will be generated for this node and alert actions performed if selected";
+$lang['help.NODE:PINGTEST'] = "Do a ping (ICMP) test first before other tests - will always record results if enabled";
+$lang['help.NODE:REQUIREPING'] = "Require the ping to pass for other tests to even be tried - will always fail if {Node:PingTest|ping test} is disabled";
+$lang['help.NODE:MASTER'] = "Master Node to be Tested First";
+$lang['help.MASTERNODE:PING'] = "Tests required to pass on the {Node:Master|master node} for this node to be tested";
+$lang['help.NODE:TESTINTERVAL'] = "Interval (minutes) between tests on this node being carried out";
+$lang['help.NODESIDE'] = "Enable support for node-side scripts to gather data from this node";
+$lang['help.NODE:CHECKASAP'] = "Schedule node for immediate text in next test cycle";
+$lang['help.UTILLINKS'] = "Links to services on remote note for system administration";
+$lang['help.NODESIDE:KEY'] = "Key used to authenticate nodeside testing";
+$lang['help.NODESIDE:PULLENABLED'] = "Enable nodeside collection via http 'pull' from the node";
+$lang['help.NODESIDE:URL'] = "URL to 'pull' nodeside data from on the node";
+$lang['help.NODESIDE:INTERVAL'] = "Interval between 'pulling' (polling) data from the node";
+$lang['help.NODESIDE:PUSHENABLED'] = "Allow node to 'push' (post) data";
+$lang['help.NODESIDE:PUSHIP'] = "Limit node 'push' to this specific IP address for security";
+$lang['help.GROUP'] = "A group is a collection of one or more {node|nodes}. Note that nodes can be members of more than one group.";
+$lang['help.GROUP:CREATE'] = "Create a new {group} with this name";
+$lang['help.TEST:NAME'] = "A custom name can be assigned to the test for use in displays and alerts. If blank an automated name will be generated.";
+$lang['help.TEST:ATTEMPTS'] = "Number of times to attempt a test (will always try once). Defaults to 1 if zero or unset.";
+$lang['help.TEST:TIMEOUT'] = "Timeout value for the test - alters the defaults or system-wide variable settings for the relevant test (seconds)";
+$lang['help.TEST:SIMPLEEVALUATION'] = "Use simple pass/fail evaluation (i.e. if a web test returns any data it passes else it fails)";
+$lang['help.TEST:RECORDED'] = "Record the results of this test for historic reports";
+$lang['help.TEST:ENABLED'] = "Perform the test or not (will update nothing if disabled)";
+$lang['help.TEST:INTERVAL'] = "Interval (minutes) between this test being performed. Will only ever be tested as quickly as the {Node:TestInterval|node interval} is set to";
+$lang['help.TEST:TESTALERTS'] = "Test will generate an alert on failure";
+$lang['help.HISTORY:SHOULD'] = "A rough calculation based on configured polling times (i.e. test interval or node interval) from the start to finish (or now if sooner)";
+$lang['help.VIEW'] = "A view is a custom set of nodes/groups/tests which can be used in a variety of ways";
+$lang['help.VIEW:CREATE'] = "Creates a {view} of the specified name";
+$lang['help.VIEW:PUBLIC'] = "The view can be seen by people not logged into FreeNATS";
+$lang['help.VIEW:COLONS'] = "If text status is selected for a view item a colon will be displayed before it";
+$lang['help.VIEW:DASHES'] = "Display a dash before a test last run time where applicable";
+$lang['help.VIEW:TIMEAGO'] = "Use XX:XX ago or normal datetime for test details";
+$lang['help.VIEW:COLUMNS'] = "Display list-type elements in this number of columns (0 for off)";
+$lang['help.VIEW:REFRESH'] = "Send a http-equv to refresh the page after this many seconds (0 for off)";
+$lang['help.VIEW:USECOLOUR'] = "Use colour for status display as in normal FreeNATS display";
+$lang['help.VIEW:SHOWDETAIL'] = "Show details of the test/object(s) such as node tests";
+$lang['help.VIEW:TEXTSTATUS'] = "Textual status such as passed, failed etc";
+$lang['help.REPORT'] = "Reports show the %age of service availability in a specified period";
+$lang['help.BACKUP:TRUNCATE'] = "Clears tables first when restored back (recommended) otherwise duplicates may fail";
+$lang['help.SCHEDULE'] = "A schedule controls what times a node is tested and are managed through the admin page";
+$lang['help.SCHEDULE:DEFAULTACTION'] = "What will happen if no exceptions are matched (the opposite will happen if one is matched)";
+$lang['help.ALERTACTION'] = "An alert action is performed when a node fails a test, they are configured through the admin page";
+$lang['help.AACTION:WARNINGS'] = "The action is triggered for warning level events as well as failures (including downgrading from failure to warning if {AAction:Decreases|decreases} is set)";
+$lang['help.AACTION:DECREASES'] = "The action is triggered when the level goes down to closed (or {AAction:Warnings|warnings} if set)";
+$lang['help.AACTION:LIMIT'] = "Max times this action can run in any one day (0 = unlimited) to avoid flooding";
+$lang['help.AACTION:COUNTER'] = "Number of times this action has run in the day shown - you can manually reset this here";
+$lang['help.VARIABLE'] = "System variables are used to control the system environment. To delete a variable just save it with a blank name.";
+$lang['help.VAR:LOG.LEVEL'] = "The system log level - 10 is everything, 0 is fatal only. 5-6-ish is probably a good balance.";
+$lang['help.VAR:API.PUBLIC'] = "The API interface is available to public users if 1 (also see {Var:api.key|api.key})";
+$lang['help.VAR:API.KEY'] = "Require this key from public users as apikey when accessing the API ({Var:api.public|api.public} must be set)";
+$lang['help.VAR:ALERT.BODY.FOOTER'] = "Footer to go at the end of system generated alerts";
+$lang['help.VAR:ALERT.BODY.HEADER'] = "Header to go at the start of system generated alerts";
+$lang['help.VAR:ALERT.SUBJECT.LONG'] = "Subject for email alerts of long format";
+$lang['help.VAR:ALERT.SUBJECT.SHORT'] = "Subject for email alerts of short format";
+$lang['help.VAR:FREENATS.FIRSTRUN'] = "System variable to indicate first use of FreeNATS";
+$lang['help.VAR:SITE.ENABLE.TESTS'] = "Enable testing";
+$lang['help.VAR:SITE.ENABLE.WEB'] = "Enable web interface";
+$lang['help.VAR:SITE.ENABLE.TESTER'] = "Enable Tester to Run";
+$lang['help.VAR:SITE.GRAPH.PUBLIC'] = "Graphs are available to public users for views etc if 1 (also see {Var:site.graph.key|site.graph.key})";
+$lang['help.VAR:SITE.GRAPH.KEY'] = "Require this key from public users as graphkey ({Var:site.graph.public|site.graph.public} must be set)";
+$lang['help.VAR:SITE.ENABLE.INTERACTIVE'] = "Must be set (1) to allow interactive web sessions (like this one)";
+$lang['help.VAR:SITE.POPUPMESSAGE'] = "If set (1) will show a popup message when saving changes etc";
+$lang['help.VAR:SITE.DTFORMAT'] = "Site-wide custom date time format (in PHP format) i.e. Y-m-d H:i:s";
+$lang['help.VAR:SITE.TEXT.FAILED'] = "Text to show for a failed status (defaults to Failed if unset)";
+$lang['help.VAR:SITE.TEXT.PASSED'] = "Text to show for a passed status (defaults to Passed if unset)";
+$lang['help.VAR:SITE.TEXT.UNTESTED'] = "Text to show for untested items (defaults to Untested if unset)";
+$lang['help.VAR:SITE.TEXT.WARNING'] = "Text to show for a warning status (defaults to Warning if unset)";
+$lang['help.VAR:SITE.TEXT.CLOSED'] = "Text to indicate alert closed (defaults to Alert Closed if unset)";
+$lang['help.VAR:SITE.INCLUDE.EVENTS'] = "Include *.php in the server/site/events directory if 1";
+$lang['help.VAR:SITE.INCLUDE.TESTS'] = "Include *.php in the server/site/tests directory if 1";
+$lang['help.VAR:SITE.ENABLE.ADMINSQL'] = "Enables the admin SQL console if 1";
+$lang['help.VAR:SITE.LINKS.NEWWINDOW'] = "Opens {UtilLinks|utility links} in new window if 1";
+$lang['help.VAR:SITE.MONITOR.POPUPS'] = "Opens a popup status window in live monitor unless set to 0";
+$lang['help.VAR:SITE.FIRSTRUN.IGNORE'] = "Ignores the existance of the firstrun.php script (dangerous)";
+$lang['help.VAR:SITE.AUTH'] = "If set to http will use HTTP-AUTH otherwises uses standard login form";
+$lang['help.VAR:MAIL.FROMNAME'] = "Textual from name to be used in SMTP mail (defaults to FreeNATS if unset)";
+$lang['help.VAR:MAIL.SMTPSERVER'] = "SMTP server to relay mail through (can be ; seperated list) uses internal mail() if unset or blank";
+$lang['help.VAR:MAIL.SMTPUSERNAME'] = "Username for SMTP AUTH (AUTH only used if username is set or provided)";
+$lang['help.VAR:MAIL.SMTPPASSWORD'] = "Password for SMTP AUTH";
+$lang['help.VAR:MAIL.SMTPHOSTNAME'] = "Hostname for HELO in SMTP transactions (may be required for strict mail servers)";
+$lang['help.VAR:TEST.ICMP.TIMEOUT'] = "Timeout in seconds to wait for an ICMP response before declaring a failure in seconds (default 10)";
+$lang['help.VAR:TEST.ICMP.TRYTWICE'] = "Depreciated - replaced with {Var:test.icmp.attempts|test.icmp.attempts}";
+$lang['help.VAR:TEST.ICMP.ATTEMPTS'] = "Number of times the main "require ping" test will attempt before failing (default 2)";
+$lang['help.VAR:TEST.ICMP.RETURNMS'] = "If set (1) returns ping results in MilliSeconds (ms) (default 0)";
+$lang['help.VAR:TEST.HTTP.TIMEOUT'] = "Default timeout for HTTP/s streams used in web tests (uses system default if unset or <1)";
+$lang['help.VAR:TEST.IMAP.TIMEOUT'] = "Default timeout for IMAP tests in seconds (uses environment default if unset or 0)";
+$lang['help.VAR:TEST.SMTP.TIMEOUT'] = "Default timeout for SMTP tests in seconds (uses 20 seconds if 0 or unset)";
+$lang['help.VAR:TEST.MYSQL.TIMEOUT'] = "Default timeout for MySQL tests in seconds (uses environmental default if unset or 0)";
+$lang['help.VAR:TEST.SPAWNDELAY'] = "Delay in seconds between node test threads being spawned by test-threaded.sh (no delay if 0 or unset), can be a decimal";
+$lang['help.VAR:TEST.INTERVAL'] = "Delay in seconds between tests on a node (no delay if 0 or unset), can be a decimal";
+$lang['help.VAR:TEST.TCP.TIMEOUT'] = "Default timeout for TCP tests (system default if 0 or unset) (seconds)";
+$lang['help.VAR:TEST.UDP.TIMEOUT'] = "Default timeout for UDP tests (system default if 0 or unset) (seconds)";
+$lang['help.VAR:RETAIN.ALERT'] = "Days to retain alert records for (default 356 if 0 or unset). Retain forever with value -1.";
+$lang['help.VAR:RETAIN.RECORD'] = "Days to retain test result records for use in history and graphs (default 356 if 0 or unsert). Retain forever with value -1.";
+$lang['help.VAR:RETAIN.TESTRUN'] = "Days to retain test run records for (default 30 if 0 or unset). Retain forever with value -1.";
+$lang['help.VAR:RETAIN.SYSLOG'] = "Days to retain log entries for (default 30 if 0 or unset). Retain forever with value -1.";
+$lang['help.VAR:FREENATS.TRACKER'] = "Participate in the automated feedback process - 1 for yes low level, 2 for detailed, 0 for disabled (default 0)";
+$lang['help.VAR:FREENATS.TRACKER.USID'] = "Unique Site ID for FreeNATS tracker to anonymise data capture (only if {Var:freenats.tracker|freenats.tracker} set to 1";
+
+
+?>
\ No newline at end of file
diff --git a/src/server/base/lang/Italian.it.lang.php b/src/server/base/lang/Italian.it.lang.php
new file mode 100755
index 0000000..0061e10
--- /dev/null
+++ b/src/server/base/lang/Italian.it.lang.php
@@ -0,0 +1,504 @@
+sito. Effettuare questa verifica con regolarità. La versione che si sta utilizzando in questo momento è la";
+$lang['monitor.alerts'] = "Situazione controlli";
+$lang['no.monitor.alerts'] = "Nessuna segnalazione";
+$lang['monitoring'] = "Controlli";
+$lang['nodes.configured'] = "Nodi configurati";
+$lang['node.groups'] = "Gruppi di nodi";
+$lang['common.tasks'] = "Operazioni comuni";
+$lang['add.nodes'] = "Aggiungi nodo";
+$lang['email.alerting'] = "Email segnalazioni";
+$lang['configure.tests'] = "Configurazione controlli";
+$lang['test.summaries'] = "Riepilogo controlli";
+$lang['monitored.nodes'] = "Nodi controllati";
+$lang['node'] = "Nodo";
+$lang['options'] = "Opzioni";
+$lang['move'] = "Sposta";
+$lang['edit'] = "Modifica opzioni";
+$lang['delete'] = "Elimina";
+$lang['create.node'] = "Crea nodo";
+$lang['config'] = "Configurazione";
+$lang['move.before'] = "Sposta prima";
+$lang['go'] = "Vai";
+$lang['refresh.weight'] = "Aggiorna indici ordinamento";
+$lang['create.group'] = "Crea gruppo";
+$lang['views'] = "Viste";
+$lang['create.view'] = "Crea nuova vista";
+$lang['reports'] = "Report disponibilità";
+$lang['create.report'] = "Crea nuovo report di disponibilità servizio";
+$lang['config.summary'] = "Riepilogo configurazione";
+$lang['nodeid'] = "ID Nodo";
+$lang['name'] = "Nome";
+$lang['hostname'] = "Nome host";
+$lang['schedule'] = "Pianificazione";
+$lang['enabled'] = "Abilitato";
+$lang['ping'] = "Ping";
+$lang['required'] = "Obbligatorio";
+$lang['interval'] = "Intervallo";
+$lang['nodeside'] = "Remoto";
+$lang['today'] = "Oggi";
+$lang['last.24h'] = "Ultime 24 ore";
+$lang['custom'] = "Personalizzato";
+$lang['ago'] = "fa";
+$lang['never'] = "mai";
+$lang['user.pref'] = "Impostazioni utente";
+$lang['change.password'] = "Cambia password";
+$lang['current'] = "Attuale";
+$lang['new'] = "Nuova";
+$lang['confirm'] = "Conferma";
+$lang['pass.change.ok'] = "Password modificata";
+$lang['pass.change.fail'] = "Cambio password fallito";
+$lang['admin.interface'] = "Interfaccia amministrazione";
+$lang['user.admin'] = "Amministrazione utenti";
+$lang['event.log'] = "Registro eventi di sistema";
+$lang['alert.actions'] = "Segnalazioni";
+$lang['variables'] = "Variabili di sistema";
+$lang['sessions'] = "Sessioni di controllo";
+$lang['schedules'] = "Pianificazione controlli e segnalazioni";
+$lang['file.manager'] = "Gestore file";
+$lang['sql.console'] = "Console SQL";
+$lang['dns.console'] = "Console interrogazioni DNS";
+$lang['backup.restore'] = "Backup e ripristino";
+$lang['sys.status'] = "Riepilogo stato sistema";
+$lang['sys.info'] = "Informazioni di sistema";
+$lang['tests.alerting'] = "Controlli e Segnalazioni";
+$lang['tools'] = "Strumenti";
+$lang['logs.info'] = "Registro e informazioni di sistema";
+$lang['ul.admin'] = "Amministratore";
+$lang['ul.power'] = "Utente privilegiato";
+$lang['ul.normal'] = "Utente normale";
+$lang['ul.disabled'] = "Disabilitato";
+$lang['aae.short'] = "Breve";
+$lang['aae.long'] = "Lungo";
+$lang['unknown'] = "Sconosciuto";
+$lang['aae.sub.blank'] = "Vuoto";
+$lang['aae.sub.short'] = "Breve";
+$lang['aae.sub.long'] = "Lungo";
+$lang['aatype.email'] = "Email";
+$lang['aatype.mqueue'] = "Coda messaggio";
+$lang['aatype.url'] = "URL";
+$lang['aatype.disabled'] = "Disabilitato";
+$lang['real.name'] = "Nome reale";
+$lang['user.level'] = "Livello utente";
+$lang['create.user'] = "Crea utente";
+$lang['save'] = "Salva";
+$lang['sessions.for'] = "Sessione di controllo Nodo per";
+$lang['sessions.running'] = "Sessioni di controllo attive";
+$lang['sessions.running.for'] = "Sessione di controllo Nodo per";
+$lang['sessions.not.running'] = "Nessuna sessione di controllo attiva";
+$lang['sessions.previous'] = "Precedenti sessioni di controllo per";
+$lang['sessions.previous.none'] = "Nessuna precedente sessione di controllo";
+$lang['sessions.stillrunning'] = "Ancora attiva";
+$lang['started'] = "Iniziato";
+$lang['finished'] = "Terminato";
+$lang['node.filter'] = "Filtro Nodo";
+$lang['output'] = "Risultato";
+$lang['allnodes'] = "Tutti i Nodi";
+
+$lang['test.run'] = "Esecuzione controllo";
+$lang['testrun.manual.close'] = "Chiusura manuale controllo";
+$lang['testrun.manual.close.detail'] = "Confermi questa operazione? Chiudi solo le sessioni di controllo per le quali sei certo che non siano ancora in esecuzione in background. Questa azione non terminerà il processo, ma etichetterà la sessione di controllo come terminata.";
+$lang['testrun.del.yes'] = "Sì - Elimina";
+$lang['testrun.del.cancel'] = "No - Annulla";
+$lang['testrun.session.closed'] = "Sessione di controllo terminata";
+$lang['testrun.fetch.error'] = "Errore lettura dati controllo";
+$lang['confirm.action'] = "Conferma Azione";
+$lang['id'] = "ID";
+
+$lang['aa.name'] = "Nome Azione";
+$lang['aa.type'] = "Tipo Azione";
+$lang['aa.create'] = "Crea una nuova azione";
+$lang['aa.limit'] = "Limite Azione";
+$lang['aa.counter'] = "Contatore Azione";
+$lang['aa.efrom'] = "Email da";
+$lang['aa.esubj'] = "Oggetto Email";
+$lang['aa.mtype'] = "Tipo Messaggio";
+$lang['aa.eto'] = "Email o URL";
+$lang['aa.update'] = "Aggiorna Azione";
+$lang['aa.test'] = "Verifica Azione";
+$lang['aa.cancel'] = "Cancella Aggiornamento";
+$lang['aa.delete'] = "Elimina Azione";
+$lang['aa.testflush'] = "Azione verificata ed eseguita";
+
+$lang['system.status'] = "Stato Sistema";
+$lang['status.size'] = "Dimensioni Tabella";
+$lang['status.tname'] = "Nome Tabella";
+$lang['status.tsize'] = "Dimensione (Righe)";
+$lang['status.tsize.kb'] = "Dimensione (Kb)";
+$lang['status.tother'] = "Altre Informazioni";
+$lang['status.free'] = "Libero";
+$lang['status.optimise'] = "Ottimizza";
+
+$lang['notes'] = "Note";
+
+$lang['status.running'] = "Sessioni di controllo Aperte/Attive";
+$lang['status.run.warn'] = "Attenzione: dati di oltre 15 minuti fa";
+$lang['status.run.error'] = "Errore: dati di ontre 1 ora fa";
+
+$lang['status.env.http'] = "Ambiente: PHP Web (Apache Module/PHP-CGI)";
+$lang['status.env.cli'] = "Ambiente: PHP CLI (Command-Line Binary)";
+
+$lang['status.disclaim'] = "Viene indicato lo stato del software FreeNATS, non quello della macchina sulla quale viene eseguito.
Spazio su disco e prestazioni dell'eventuale sistema VM devono essere controllati tramite gli appositi strumenti dedicati.";
+
+$lang['warnings'] = "Allarmi";
+//$lang['decreases'] = "L'azione viene eseguita quando il livello di errore ritorna allo stato chiuso (o allarme se impostato)";
+$lang['decreases'] = "Rientro da allerta";
+$lang['create'] = "Crea";
+$lang['version.info'] = "Informazioni Versione";
+$lang['release'] = "Release";
+$lang['compound'] = "Composto";
+$lang['reg.modules'] = "Moduli di controllo registrati";
+$lang['provides'] = "Ambito";
+$lang['revision'] = "Revisione";
+$lang['additional'] = "Informazioni aggiuntive";
+$lang['reg.events'] = "Gestori eventi registrati";
+$lang['event'] = "Evento";
+$lang['handlers'] = "Gestore/i";
+$lang['reg.languages'] = "Lingue registrate";
+
+$lang['back.to.admin'] = "Ritorna a menu Impostazioni di Sistema";
+$lang['save.user.fail'] = "Registrazione utente fallita o nessun cambiamento";
+$lang['save.user.ok'] = "Utente salvato";
+$lang['create.user.fail'] = "Creazione utente fallita";
+$lang['create.user.ok'] = "Utente creato";
+$lang['delete.user'] = "Cancella utente";
+$lang['user.deleted'] = "Utente cancellato";
+$lang['save.var.ok'] = "Variabile salvata o cancellata";
+$lang['save.var.fail'] = "Aggiornamento variabile fallito";
+$lang['new.var.ok'] = "Variabile creata";
+$lang['new.var.fail'] = "Creazione nuova variabile fallita";
+$lang['optimised.ok'] = "Tabella ottimizzata";
+$lang['changes.ok'] = "Cambiamenti registrati";
+$lang['changes.fail'] = "Registrazione cambiamenti fallita o nessun cambiamento";
+$lang['delete.ok'] = "Cancellazione eseguita";
+
+// System Event Log
+$lang['filter'] = "Filtro";
+$lang['show'] = "Mostra";
+$lang['filter.log'] = "Applica filtro e mostra risultati";
+$lang['reset'] = "Azzera filtro";
+$lang['next'] = "Successivo";
+$lang['prev'] = "Precedente";
+
+//Live Monitor
+$lang['mon.options'] = "opzioni...";
+$lang['group.name'] = "Nome Gruppo";
+$lang['status'] = "Stato";
+$lang['node.name'] = "Nome nodo";
+$lang['mon.std'] = "standard";
+$lang['mon.grp'] = "gruppi";
+$lang['mon.nodes'] = "nodi";
+$lang['mon.alerting'] = "segnalazioni";
+$lang['mon.hide'] = "...nascondi...";
+$lang['mon.goto.node'] = "Vai al Nodo";
+$lang['mon.goto.node.page'] = "Vai alla pagina del Nodo";
+$lang['mon.popup.error'] = "Nodo non valido";
+
+// Node Page
+$lang['viewing.node'] = "Vista Nodo";
+$lang['no.node'] = "Nodo non trovato";
+$lang['alert'] = "Segnalazioni";
+$lang['yes'] = "Sì";
+$lang['no'] = "No";
+$lang['alert.history'] = "Storico Segnalazioni";
+$lang['summary'] = "Riepilogo";
+$lang['links'] = "Indirizzo collegamento";
+$lang['opened'] = "Aperto";
+$lang['edit.node.options'] = "Modifica opzioni nodo";
+$lang['nodeside.tests'] = "Controllo residente sul Nodo";
+$lang['local.tests'] = "Controllo locale";
+$lang['history'] = "Storico";
+$lang['no.test'] = "Nessun controllo definito";
+$lang['node.editor'] = "Configurazione Nodo";
+$lang['editing'] = "Modifica";
+$lang['node.settings'] = "Impostazioni nodo";
+$lang['show.hide.options'] = "Mostra / Nascondi Opzioni Nodo";
+$lang['node.tests'] = "Controlli Nodo";
+$lang['last.tested'] = "Ultimo Controllo";
+$lang['add.test'] = "Aggiungi Controllo";
+$lang['no.such.node'] = "Nodo non trovato";
+$lang['create.test'] = "Crea Controllo";
+$lang['update.alert.actions'] = "Aggiorna Segnalazioni";
+$lang['add'] = "Aggiungi";
+$lang['add.nodeside'] = "Aggiungi controllo remoto sul nodo";
+$lang['web.time'] = "Tempo Web";
+$lang['web.size'] = "Dati Web";
+$lang['host'] = "Verifica Host DNS";
+$lang['remote.ping'] = "Ping remoto";
+$lang['test.loop'] = "Ciclo test";
+$lang['test.random'] = "Test casuale";
+$lang['node.id'] = "ID Nodo";
+$lang['node.icon'] = "Icona Nodo";
+$lang['default'] = "Default";
+$lang['show.hide.icons'] = "Mostra / Nascondi Icone";
+$lang['master.node'] = "Nodo Master";
+$lang['no.master'] = "Nessun nodo Master";
+$lang['master.skip'] = "Salta se Master";
+$lang['fails.ping'] = "Errore su ping";
+$lang['fails.any.test'] = "Errore su qualsiasi controllo";
+$lang['node.enabled'] = "Nodo attivo";
+$lang['test.schedule'] = "Pianificazione controlli";
+$lang['test.interval'] = "Intervallo controlli";
+$lang['test.due'] = "Prossimo controllo";
+$lang['check.asap'] = "Controllo urgente";
+$lang['alerts.active'] = "Segnalazioni attive";
+$lang['ping.test'] = "Verifica Ping";
+$lang['require.ping'] = "Ping obbligatorio";
+$lang['nodeside.testing'] = "Controllo lato nodo";
+$lang['node.key'] = "Chiave Nodo";
+$lang['pull.enabled'] = "Attiva raccolta dati (pull)";
+$lang['pull.url'] = "Indirizzo pull";
+$lang['pull.interval'] = "Intervallo pull";
+$lang['push.enabled'] = "Attiva invio dati (push)";
+$lang['push.ip'] = "Indirizzo push";
+$lang['last.date'] = "Ultimi dati";
+$lang['next.pull.due'] = "Prossima raccolta (pull)";
+$lang['catalogue'] = "Serie";
+$lang['nodeside.monitors'] = "Controlli remoti";
+$lang['refresh.now'] = "Aggiorna adesso";
+$lang['nodeside.pull.now'] = "Esegui raccolta (pull) adesso";
+$lang['utility.links'] = "Collegamenti Servizi";
+$lang['title'] = "Titolo";
+$lang['url'] = "URL";
+$lang['debug.raw'] = "Debug dati output";
+$lang['last.data'] = "Ultimi dati";
+$lang['save.settings'] = "Salva configurazione";
+$lang['cancel'] = "Annulla";
+$lang['nodeside.pull.disabled'] = "Raccolta dati disabilitata";
+$lang['minutes'] = "Minuti";
+$lang['now'] = "Adesso";
+$lang['edit.options'] = "Modifica Opzioni";
+$lang['save.ok'] = "Cambiamenti registrati";
+$lang['save.failed'] = "Salvataggio fallito o nessun cambiamento";
+$lang['save.fail'] = $lang['save.failed'];
+$lang['group.settings'] = "Impostazioni Gruppo";
+$lang['local.test.editor'] = "Modifica controllo locale";
+$lang['editing.test'] = "Modifica controllo";
+$lang['test.settings'] = "Impostazioni controllo";
+$lang['test.type'] = "Tipo controllo";
+$lang['test.options'] = "Opzioni controlli";
+$lang['full.url'] = "URL completo e prefisso (es.: http://www.nomehost.com/)";
+$lang['host.ip'] = "Host o IP";
+$lang['host.desc'] = "Nome dell'host o indirizzo Ip sul quale effettuare il ping (risoluzione DNS non pianificata)";
+$lang['value'] = "Valore";
+$lang['value.desc'] = "Valore per il ciclo di controlli o valore massimo per il controllo casuale";
+$lang['no.test.options'] = "Nessuna opzione per il controllo";
+$lang['custom.name'] = "Nome personalizzato";
+$lang['test.enabled'] = "Controllo attivo";
+$lang['recorded'] = "Registrazione";
+$lang['simple.eval'] = "Verifica semplice";
+$lang['custom.attempts'] = "Numero di tentativi";
+$lang['custom.timeout'] = "Timeout personalizzato";
+$lang['test.save'] = "Salva impostazioni controllo";
+$lang['abandon.changes'] = "Annulla modifiche";
+$lang['seconds'] = "Secondi";
+$lang['passed'] = "Attivo";
+$lang['untested'] = "Non verificato";
+$lang['warning'] = "Attenzione";
+$lang['failed'] = "Fallito";
+$lang['failure'] = "Errore";
+$lang['test.evals'] = "Sistemi personalizzati controllo";
+$lang['test.evals.simple'] = "I sistemi personalizzati di controllo non verranno classificati come Verifica semplice se attivati (vedi sopra)";
+$lang['add.eval'] = "Aggiungi nuovo";
+$lang['eval.equal'] = "Uguale a";
+$lang['eval.lt'] = "Minore di";
+$lang['eval.gt'] = "Maggiore di";
+$lang['eval.deleted'] = "Controllo eliminato";
+$lang['edit.nodeside.test'] = "Editor controllo lato nodo";
+$lang['ns.type'] = "Tipo controllo / UID";
+$lang['nodeside.test'] = "Controllo lato nodo";
+$lang['test.alerts'] = "Verifica Segnalazioni";
+$lang['last.checked'] = "Ultimo controllo";
+$lang['last.result'] = "Ultimo risultato";
+$lang['last.value'] = "Ultimo valore";
+$lang['save.changes'] = "Salva cambiamenti";
+$lang['result'] = "Risultato";
+$lang['edit.view'] = "Modifica Vista";
+$lang['editing.view'] = "Modifica Vista";
+$lang['no.such.view'] = "Vista non trovata";
+$lang['preview'] = "Anteprima";
+$lang['linking'] = "Indirizzo Collegamento";
+$lang['unknown.action'] = "Azione non definita";
+$lang['expand.view.options'] = "Espandi Opzioni Vista";
+$lang['node.ping'] = "Ping su nodo";
+$lang['host.ip.lookup'] = "Controllo Indirizzo IP";
+$lang['group.editor'] = "Modifica Gruppo";
+$lang['no.group'] = "Gruppo non trovato";
+$lang['group.id'] = "ID Gruppo";
+$lang['group.icon'] = "Icona Gruppo";
+$lang['group.save'] = "Salva configurazione gruppo";
+$lang['group.members'] = "Elementi del Gruppo";
+$lang['group.update'] = "Aggiorna elementi Gruppo";
+$lang['group.updated'] = "Composizione gruppo aggiornata";
+$lang['group'] = "Gruppo";
+$lang['show.icons'] = "Mostra Icone";
+$lang['dns.host'] = "Verifica DNS";
+
+// Security Warnings
+$lang['sec.firstrun'] = "Avviso di sicurezza: lo script firstrun.php è accessibile dall'esterno";
+$lang['sec.firstrun.text'] = "Lo script firstrun.php della directory web non è stato rinominato. Ciò può causare problemi di sicurezza a FreeNATS. Si consiglia di rinominare lo script firstrun.php";
+$lang['sec.firstrun.ignore'] = "Per disabilitare la visualizzazione di questo avviso senza rinominare lo script (non consigliato), impostare l'opzione site.firstrun.ignore a 1";
+
+// RSS
+$lang['rss.feed'] = "Gestione Feed RSS";
+$lang['rss.feed.name'] = "Nome Feed";
+$lang['rss.feed.key'] = "Feed Key";
+$lang['rss.type'] = "Tipo di Feed";
+$lang['all.enabled.nodes'] = "Tutti i Nodi attivi";
+$lang['one.node'] = "Nodo Singolo";
+$lang['rss.range'] = "Intervallo RSS";
+$lang['last.x.days'] = "Ultimi X Giorni";
+$lang['last.x.alerts'] = "Ultime X Segnalazioni";
+$lang['current.alerts'] = "Segnalazioni attuali";
+$lang['last.alerts.node'] = "Ultima segnalazione per ciascun nodo";
+$lang['rss.feeds'] = "Feed RSS FreeNATS ";
+$lang['feed.url'] = "URL Feed RSS";
+$lang['feed.create'] = "Crea nuovo Feed";
+$lang['no.feeds'] = "Nessun Feed RSS Configurato";
+$lang['open'] = "Aperto";
+$lang['closed'] = "Chiuso";
+
+
+$lang['nohelp'] = "Guida non disponibile";
+$lang['help.FREENATS'] = "FreeNATS è uno strumento di controllo delle reti";
+$lang['help.NODE'] = "Un nodo è un sistema o un dispositivo che si desidera controllare. Un nodo può raggruppare controlli che fanno riferimento a dispositivi fisici diversi e viceversa";
+$lang['help.NODE:CREATE'] = "Crea un nuovo {node} con questo {node:id|NodeID}";
+$lang['help.NODE:ID'] = "Il NodeID è un testo univoco per {node}. Massima lunghezza 60 caratteri, sono permessi solo caratteri normali.";
+$lang['help.NODE:ENABLED'] = "Il nodo è attivato e utilizzato nei controlli (e presentato nelle viste, ove configurate)";
+$lang['help.NODE:ALERTACTIVE'] = "Gli allarmi verranno generati per questo nodo e le segnalazioni eseguite se selezionate";
+$lang['help.NODE:PINGTEST'] = "Effettua un controllo ping (ICMP) prima delle altre verifiche. Il risultato viene sempre registrato se l'opzione è attiva";
+$lang['help.NODE:REQUIREPING'] = "Impone il superamento del controllo ping, prima di effettuare le altre verifiche. Fallisce sempre se {Node:PingTest|ping test} è disabilitato";
+$lang['help.NODE:MASTER'] = "Nodo Master da controllare prima di questo";
+$lang['help.MASTERNODE:PING'] = "Il controllo deve essere superato su {Node:Master|master node} perché questo nodo venga controllato";
+$lang['help.NODE:TESTINTERVAL'] = "Intervallo (minuti) tra due esecuzioni del controllo su questo nodo";
+$lang['help.NODESIDE'] = "Attiva il supporto per script lato nodo per la raccolta dati da questo nodo";
+$lang['help.NODE:CHECKASAP'] = "Imposta il controllo di questo nodo nel prossimo ciclo di verifiche";
+$lang['help.UTILLINKS'] = "Collegamenti a servizi di amministrazione su nodo remoto";
+$lang['help.NODESIDE:KEY'] = "Chiave utilizzata per l'autenticazione nei controlli remoti";
+$lang['help.NODESIDE:PULLENABLED'] = "Attiva la raccolta di dati tramite 'http pull' dal nodo remoto";
+$lang['help.NODESIDE:URL'] = "URL per la raccolta dei dati 'pull' dal nodo remoto";
+$lang['help.NODESIDE:INTERVAL'] = "Intervallo per la comunicazione dei dati da/verso il nodo remoto";
+$lang['help.NODESIDE:PUSHENABLED'] = "Attiva l'invio dei dati ('push' tramite post) verso il nodo";
+$lang['help.NODESIDE:PUSHIP'] = "Limita per sicurezza l'invio dei dati 'push' a questo specifico indirizzo IP";
+$lang['help.GROUP'] = "Un gruppo è un insieme di uno o più nodi. Un nodo può appartenere a più di un gruppo. ";
+$lang['help.GROUP:CREATE'] = "Crea un nuovo {group} con questo nome";
+$lang['help.TEST:NAME'] = "Nome personalizzato attribuito al controllo in visualizzazioni e report. Se vuoto, verrà utilizzato un nome definito automaticamente.";
+$lang['help.TEST:ATTEMPTS'] = "Numero di volte che il controllo viene eseguito (sempre almeno una volta). Predefinito a 1 se uguale a zero o non impostato.";
+$lang['help.TEST:TIMEOUT'] = "Valore di timeout per il controllo: modifica i valori di default o di sistema per i controlli corrispondenti (secondi)";
+$lang['help.TEST:SIMPLEEVALUATION'] = "Usa una valutazione semplice passato/fallito (per esempio, un controllo web che restituisca qualsiasi dato viene considerato passato, altrimenti fallito).";
+$lang['help.TEST:RECORDED'] = "Registra il risultato di questo controllo sullo storico.";
+$lang['help.TEST:ENABLED'] = "Esegue/non esegue il controllo (nessuna registrazione se disabilitato).";
+$lang['help.TEST:INTERVAL'] = "Intervallo (minuti) tra due esecuzioni di questo controllo. La massima frequenza è quella a cui è impostato {Node:TestInterval|node interval}";
+$lang['help.TEST:TESTALERTS'] = "Il controllo genera un allarme in caso di fallimento";
+$lang['help.HISTORY:SHOULD'] = "Valore risultante dagli intervalli di rilevamento (cioè intervallo di controllo o intervallo di nodo) dall'inizio alla fine (o fino a questo momento)";
+$lang['help.VIEW'] = "Una vista è un insieme personalizzato di nodi/gruppi/controlli";
+$lang['help.VIEW:CREATE'] = "Crea una {view} con questo nome";
+$lang['help.VIEW:PUBLIC'] = "La vista è accessibile agli utenti senza effettuare l'accesso a FreeNATS";
+$lang['help.VIEW:COLONS'] = "Se per l'elemento di una vista è selezionata la modalità testo, viene mostrato il simbolo di due punti prima del valore";
+$lang['help.VIEW:DASHES'] = "Visualizza un trattino prima dell'orario di ultima esecuzione del controllo, ove applicabile";
+$lang['help.VIEW:TIMEAGO'] = "Utilizza XX:XX fa o il normale orario per i dati di dettaglio del controllo";
+$lang['help.VIEW:COLUMNS'] = "Visualizza gli elementi con questo numero di colonne (0 per disabilitare)";
+$lang['help.VIEW:REFRESH'] = "Invia una segnale http-equv per l'aggiornamento della pagina dopo questo intervallo in secondi (0 per disabilitare)";
+$lang['help.VIEW:USECOLOUR'] = "Utilizza i colori per la visualizzazione dello stato come nella visualizzazione standard di FreeNATS";
+$lang['help.VIEW:SHOWDETAIL'] = "Mostra i dettagli di controlli/oggetti, come i controlli dei nodi";
+$lang['help.VIEW:TEXTSTATUS'] = "Descrizione dello stato (passato, fallito, etc.)";
+$lang['help.REPORT'] = "Il report mostra la percentuale di disponibilità nel periodo specificato";
+$lang['help.BACKUP:TRUNCATE'] = "Azzera le tabelle prima del ripristino (consigliato) altrimenti la presenza di duplicati potrebbe causare errori";
+$lang['help.SCHEDULE'] = "Le pianificazioni definiscono quando i nodi vengono controllati; sono configurate nella pagina di amministrazione";
+$lang['help.SCHEDULE:DEFAULTACTION'] = "Azione standard se non si verificano eccezioni (l'opposto viene eseguito in caso di eccezioni)";
+$lang['help.ALERTACTION'] = "Una segnalazione viene attivata se fallisce un controllo su un nodo; sono configurati nella pagina di amministrazione";
+$lang['help.AACTION:WARNINGS'] = "L'azione è attivata sia per gli allarmi sia per gli errori (compreso il passaggio da errore ad allarme se {AAction:Decreases|decreases} è attivato";
+$lang['help.AACTION:DECREASES'] = "L'azione è attivata quando il livello passa dallo stato di errore a chiuso (o {AAction:Warnings|warnings} se impostato)";
+$lang['help.AACTION:LIMIT'] = "Numero massimo di volte che l'azione può essere ripetuta in un giorno (0 = illimitato) per evitare eccessi di segnalazioni";
+$lang['help.AACTION:COUNTER'] = "Numero di volte che l'azione è stata eseguita nel giorno indicato - è possibile azzerare manualmente questo valore";
+$lang['help.VARIABLE'] = "Le variabili di sistema sono usate per controllare le funzionalità dell'ambiente. Per cancellare una variabile è sufficiente attribuirle un nome vuoto ed effettuare il salvataggio.";
+$lang['help.VAR:LOG.LEVEL'] = "Livello del registro eventi - 10 equivale a tutto, 0 registra solo gli errori fatali. I valori 5-6 sono le impostazioni consigliate.";
+$lang['help.VAR:API.PUBLIC'] = "L'interfaccia API è accessibile agli utenti pubblici se il valore è impostato a 1 (si veda {Var:api.key|api.key})";
+$lang['help.VAR:API.KEY'] = "Chiave richiesta per gli utenti pubblici nell'utilizzo dell'API ({Var:api.public|api.public} deve essere definito)";
+$lang['help.VAR:ALERT.BODY.FOOTER'] = "Nota aggiunta in calce alle segnalazioni generate dal sistema";
+$lang['help.VAR:ALERT.BODY.HEADER'] = "Intestazione inserita nelle segnalazioni generate dal sistema";
+$lang['help.VAR:ALERT.SUBJECT.LONG'] = "Oggetto per le segnalazioni via Email in formato lungo";
+$lang['help.VAR:ALERT.SUBJECT.SHORT'] = "Oggetto per le segnalazioni via Email in formato breve";
+$lang['help.VAR:FREENATS.FIRSTRUN'] = "Variabile di sistema che indica il primo accesso a FreeNATS";
+$lang['help.VAR:SITE.ENABLE.TESTS'] = "Controlli attivi";
+$lang['help.VAR:SITE.ENABLE.WEB'] = "Interfaccia Web attiva";
+$lang['help.VAR:SITE.ENABLE.TESTER'] = "Attiva sistema di test";
+$lang['help.VAR:SITE.GRAPH.PUBLIC'] = "I grafici sono accessibili agli utenti pubblici nelle viste se impostato a 1 (si veda {Var:site.graph.key|site.graph.key})";
+$lang['help.VAR:SITE.GRAPH.KEY'] = "Chiave richiesta per gli utenti pubblici ({Var:site.graph.public|site.graph.public} deve essere attivo)";
+$lang['help.VAR:SITE.ENABLE.INTERACTIVE'] = "Deve essere attivo (1) per consentire sessioni web interattive (come questa)";
+$lang['help.VAR:SITE.POPUPMESSAGE'] = "Se attivo (1) verrà mostrato un messaggio di avviso durante i salvataggi";
+$lang['help.VAR:SITE.DTFORMAT'] = "Formato della data utilizzato nel sito (secondo lo standard PHP), per esempio Y-m-d H:i:s";
+$lang['help.VAR:SITE.TEXT.FAILED'] = "Testo da mostrare per lo stato di errore ([Failed] se non definito)";
+$lang['help.VAR:SITE.TEXT.PASSED'] = "Testo da mostrare per lo stato attivo ([Passed] se non definito)";
+$lang['help.VAR:SITE.TEXT.UNTESTED'] = "Testo da mostrare per gli elementi non verificati ([Untested] se non definito)";
+$lang['help.VAR:SITE.TEXT.WARNING'] = "Testo da mostrare per lo stato di allarme ([Warning] se non definito)";
+$lang['help.VAR:SITE.TEXT.CLOSED'] = "Testo da mostrare per lo stato di errore chiuso ([Closed] se non definito)";
+$lang['help.VAR:SITE.INCLUDE.EVENTS'] = "Includi file *.php nella directory server/site/events se 1";
+$lang['help.VAR:SITE.INCLUDE.TESTS'] = "Includi file *.php nella directory server/site/tests se 1";
+$lang['help.VAR:SITE.ENABLE.ADMINSQL'] = "Abilita la console di amministrazione SQL se 1";
+$lang['help.VAR:SITE.LINKS.NEWWINDOW'] = "Apre {UtilLinks|utility links} in una nuova finestra se 1";
+$lang['help.VAR:SITE.MONITOR.POPUPS'] = "Apre una finestra popup nel Monitor in Tempo Reale se 0";
+$lang['help.VAR:SITE.FIRSTRUN.IGNORE'] = "Ignora l'esistenza dello script firstrun.php (pericoloso)";
+$lang['help.VAR:SITE.AUTH'] = "Se impostato a to http usa HTTP-AUTH altrimenti usa il modulo di accesso normale";
+$lang['help.VAR:MAIL.FROMNAME'] = "Nome utilizzato come mittente nei messaggi di posta inviati tramite SMTP (default FreeNATS se non impostato)";
+$lang['help.VAR:MAIL.SMTPSERVER'] = "Server SMTP utilizzato per l'invio della posta (può essere una lista di elementi separati da ';'). Viene usato il sistema interno mail() se non impostato";
+$lang['help.VAR:MAIL.SMTPUSERNAME'] = "Nome utente per il servizio SMTP (vien usato protocollo con autenticazione solo se il nome viene indicato)";
+$lang['help.VAR:MAIL.SMTPPASSWORD'] = "Password per il servizio SMTP con autenticazione";
+$lang['help.VAR:MAIL.SMTPHOSTNAME'] = "Nome host per le transazioni SMTP (potrebbe essere richiesto da alcuni server di posta)";
+$lang['help.VAR:TEST.ICMP.TIMEOUT'] = "Intervallo di attesa in secondi per le richieste ICMP prima di restituire risultato negativo (default 10 secondi)";
+$lang['help.VAR:TEST.ICMP.TRYTWICE'] = "Obsoleto: sostituito con {Var:test.icmp.attempts|test.icmp.attempts}";
+$lang['help.VAR:TEST.ICMP.ATTEMPTS'] = "Numero di esecuzioni che il test ping principale effettua prima di restituire risultato negativo (default 2)";
+$lang['help.VAR:TEST.ICMP.RETURNMS'] = "Se impostato a (1), i risultati del test ping vengono forniti in millisecondi (ms) (default 0)";
+$lang['help.VAR:TEST.HTTP.TIMEOUT'] = "Timeout di default in secondi per gli stream HTTP utilizzati nelle verifiche web (utilizza valori di default se non definito o <1)";
+$lang['help.VAR:TEST.IMAP.TIMEOUT'] = "Timeout di default in secondi per i controlli IMAP (utilizza valori di default se non definito o 0)";
+$lang['help.VAR:TEST.SMTP.TIMEOUT'] = "Timeout di default in secondi per i controlli SMTP (impostato a 20 secondi se non definito o 0)";
+$lang['help.VAR:TEST.MYSQL.TIMEOUT'] = "Timeout di default in secondi per i controlli MySQL (utilizza valori di default se non definito o 0)";
+$lang['help.VAR:TEST.SPAWNDELAY'] = "Intervallo in secondi prima che i thread di controllo di un nodo vengano separati (nessun ritardo o se non definito o 0)";
+$lang['help.VAR:TEST.INTERVAL'] = "Intervallo in secondi tra due esecuzioni del controllo su un nodo (nessun ritardo se non definitio o 0); può una valore decimale";
+$lang['help.VAR:TEST.TCP.TIMEOUT'] = "Timeout di default in secondi per i controlli TCP (valore di sistema o 0 se non impostato)";
+$lang['help.VAR:TEST.UDP.TIMEOUT'] = "Timeout di default in secondi per i controlli UDP (valore di sistema o 0 se non impostato)";
+$lang['help.VAR:RETAIN.ALERT'] = "Giorni di conservazione dei dati di allerta (default 365 se 0 o non impostato). Conserva per sempre se -1.";
+$lang['help.VAR:RETAIN.RECORD'] = "Giorni di conservazione dei dati utilizzati in storici e grafici (default 365 se 0 o non impostato). Conserva per sempre se -1.";
+$lang['help.VAR:RETAIN.TESTRUN'] = "Giorni di conservazione dei dati di esecuzioni dei controlli (default 30 se 0 o non impostato). Conserva per sempre se -1.";
+$lang['help.VAR:RETAIN.SYSLOG'] = "Giorni di conservazione dei dati del registro eventi (default 30 se 0 o non impostato). Conserva per sempre se -1.";
+$lang['help.VAR:FREENATS.TRACKER'] = "Partecipa al sistema automatico di feedback: -1 sì con volume dati minimo, 2 sì dettagliato, 0 disabilitato (0 default).";
+$lang['help.VAR:FREENATS.TRACKER.USID'] = "Identificativo sito utilizzato da FreeNATS per registrazione anonima dei dati (solo se {Var:freenats.tracker|freenats.tracker} impostato a 1";
+?>
diff --git a/src/server/base/lang/Russian.ru.lang.php b/src/server/base/lang/Russian.ru.lang.php
new file mode 100755
index 0000000..04f618c
--- /dev/null
+++ b/src/server/base/lang/Russian.ru.lang.php
@@ -0,0 +1,588 @@
+сайте программы. Рекомендуем регулярно это делать. Ваша текущая версия";
+$lang['monitor.alerts']="События мониторинга";
+$lang['no.monitor.alerts']="Проишествий не было";
+$lang['check.updates']="Проверить обновления";
+$lang['monitoring']="Monitoring";
+$lang['nodes.configured']="Узлы";
+$lang['node.groups']="Группы узлов";
+$lang['common.tasks']="Общие задачи";
+$lang['add.nodes']="Все узлы";
+$lang['email.alerting']="Email оповещения";
+$lang['configure.tests']="Создать узел";
+$lang['test.summaries']="Отчёт за период:";
+$lang['monitored.nodes']="Список контроллируемых узлов:";
+
+// nodes already
+$lang['node']="Узел";
+$lang['options']="Настройки";
+$lang['move']="Переместить";
+$lang['edit']="Редактировать";
+$lang['delete']="Удалить";
+$lang['create.node']="Создать узел";
+$lang['config']="Настройки";
+$lang['move.before']="Двигать вверх";
+$lang['go']="Go";
+$lang['refresh.weight']="Refresh Weighting";
+
+$lang['node.groups']="Группы узлов";
+$lang['create.group']="Создать группу";
+
+$lang['views']="Графики";
+$lang['create.view']="Создать график";
+$lang['reports']="Доступные отчеты";
+$lang['create.report']="Создать новый отчёт";
+
+$lang['config.summary']="Configuration Summary / Overview";
+$lang['nodeid']="ID узла";
+$lang['name']="Имя";
+$lang['hostname']="Днс имя или ип";
+$lang['schedule']="Schedule";
+$lang['enabled']="Включен";
+$lang['ping']="Ping";
+$lang['required']="Required";
+$lang['interval']="Интервал";
+$lang['nodeside']="Nodeside";
+
+// Time Periods
+$lang['today']="Сегодня";
+$lang['last.24h']="Последние 24 часа";
+$lang['custom']="Задать период";
+$lang['ago']="ago";
+$lang['never']="never";
+
+// User Preferences
+$lang['user.pref']="Настройки пользователя";
+$lang['change.password']="Изменить пароль";
+$lang['current']="Текущий";
+$lang['new']="Новый";
+$lang['confirm']="Подтверждение";
+$lang['pass.change.ok']="Пароль изменен";
+$lang['pass.change.fail']="Пароль не изменен";
+
+// Administration Settings
+$lang['admin.interface']="Административная панель";
+$lang['user.admin']="Пользователи";
+$lang['event.log']="Системные события";
+$lang['alert.actions']="Alert Actions";
+$lang['variables']="Системные переменные";
+$lang['sessions']="Test Sessions";
+$lang['schedules']="Test and Alert Schedules";
+$lang['file.manager']="Файл-менеджер";
+$lang['sql.console']="SQL Console";
+$lang['dns.console']="DNS Query Console";
+$lang['backup.restore']="Backup and Restore";
+$lang['sys.status']="System Status Report";
+$lang['sys.info']="Информация о системе";
+
+$lang['tests.alerting']="Tests and Alerting";
+$lang['tools']="Инструменты";
+$lang['logs.info']="Logs and System Information";
+
+$lang['ul.admin']="Администратор";
+$lang['ul.power']="Продвинутый пользователь";
+$lang['ul.normal']="Обычный пользователь";
+$lang['ul.disabled']="Отключен";
+
+$lang['aae.short']="Короткий";
+$lang['aae.long']="Длинный";
+
+$lang['unknown']="Неизвестно";
+
+$lang['aae.sub.blank']="Пустой";
+$lang['aae.sub.short']="Короткий";
+$lang['aae.sub.long']="Длинный";
+
+$lang['aatype.email']="Email";
+$lang['aatype.mqueue']="Message Queue";
+$lang['aatype.url']="URL";
+$lang['aatype.disabled']="Disabled";
+
+$lang['real.name']="Настоящее имя";
+$lang['user.level']="Уровень доступа";
+$lang['create.user']="Создать";
+
+$lang['save']="Сохранить";
+
+$lang['sessions.for']="Node test sessions for";
+$lang['sessions.running']="Running Test Sessions";
+$lang['sessions.running.for']="Running Test Sessions for";
+$lang['sessions.not.running']="No running test sessions";
+$lang['sessions.previous']="Previous Test Sessions for";
+$lang['sessions.previous.none']="No Previous Test Sessions";
+$lang['sessions.stillrunning']="Still Running";
+$lang['started']="Запущено";
+$lang['finished']="Завершено";
+$lang['node.filter']="Фильтр";
+$lang['output']="Выаод";
+$lang['allnodes']="Все";
+
+$lang['test.run']="Test Run";
+$lang['testrun.manual.close']="Manually Close Test Session";
+$lang['testrun.manual.close.detail']="Are you sure you want to do this? Only close sessions that you're sure aren't still running in the background. This does not kill processes - just marks the test session as complete.";
+$lang['testrun.del.yes']="Да - удалить";
+$lang['testrun.del.cancel']="Нет - отмена";
+$lang['testrun.session.closed']="Test Session Closed";
+$lang['testrun.fetch.error']="Error Fetching Testrun Data";
+
+$lang['confirm.action']="Подтвердить";
+
+
+$lang['alert.actions']="Alert Actions";
+$lang['id']="ID";
+$lang['aa.name']="Action Name";
+$lang['aa.type']="Action Type";
+$lang['aa.create']="Create New Alert Action";
+$lang['aa.limit']="Action Limit";
+$lang['aa.counter']="Action Counter";
+$lang['aa.efrom']="От";
+$lang['aa.esubj']="Тема";
+$lang['aa.mtype']="Тип";
+$lang['aa.eto']="Email To or URL";
+$lang['aa.update']="Сохранить";
+$lang['aa.test']="Тестировать";
+$lang['aa.cancel']="Отменить";
+$lang['aa.delete']="Удалить";
+$lang['aa.testflush']="Alert Action Tested & Flushed";
+
+
+$lang['system.status']="Статус";
+$lang['status.size']="Table Sizes";
+$lang['status.tname']="Table Name";
+$lang['status.tsize']="Size (Rows)";
+$lang['status.tsize.kb']="Size (Kb)";
+$lang['status.tother']="Other Information";
+$lang['status.free']="Free";
+$lang['status.optimise']="Optimise";
+
+$lang['notes']="Notes";
+
+$lang['status.running']="Open/Running Test Sessions";
+$lang['status.run.warn']="Warning: Over 15 Minutes Old";
+$lang['status.run.error']="Error: Over 1 Hour Old";
+
+$lang['status.env.http']="Environment: PHP Web (Apache Module/PHP-CGI)";
+$lang['status.env.cli']="Environment: PHP CLI (Command-Line Binary)";
+
+$lang['status.disclaim']="Please note this merely displays FreeNATS software status - not the status of the underlying Virtual Machine (if applicable).
You should monitor disk space and performance for the VM via the relevant system (such as the rPath interface).
";
+
+$lang['warnings']="Warnings";
+$lang['decreases']="Decreases";
+$lang['create']="Создать";
+
+$lang['version.info']="Version Information";
+$lang['version']="Version";
+$lang['release']="Release";
+$lang['compound']="Compound";
+
+$lang['reg.modules']="Registered Test Modules";
+$lang['provides']="Provides";
+$lang['revision']="Revision";
+$lang['additional']="Additional";
+$lang['reg.events']="Registered Event Handlers";
+$lang['event']="Event";
+$lang['handlers']="Handler(s)";
+$lang['reg.languages']="Registered Languages";
+
+$lang['back.to.admin']="Back to Main System Settings Menu";
+
+$lang['save.user.fail']="Save User Failed or Nothing Changed";
+$lang['save.user.ok']="User Saved";
+$lang['create.user.fail']="Failed to Create User";
+$lang['create.user.ok']="Пользователь создан";
+$lang['delete.user']="Удалить пользователя";
+$lang['user.deleted']="Пользователь удален";
+$lang['save.var.ok']="Updated or Deleted Variable";
+$lang['save.var.fail']="Failed to Update Variable";
+$lang['new.var.ok']="Created Variable";
+$lang['new.var.fail']="Failed to Create Variable";
+$lang['optimised.ok']="Optimised Table";
+
+$lang['changes.ok']="Изменения сохранены";
+$lang['changes.fail']="Failed to Save Changes or Nothing Changed";
+
+// System Event Log
+$lang['filter']="Фильтр";
+$lang['show']="Показать";
+$lang['filter.log']="Filter Log Entries and Display";
+$lang['reset']="Сбросить";
+$lang['next']="Следующий";
+$lang['prev']="Предыдущий";
+
+
+// Live Monitor
+$lang['live.monitor']="Live Monitor";
+$lang['mon.options']="настройки...";
+$lang['group.name']="Имя группы";
+$lang['description']="Описание";
+$lang['status']="Статус";
+$lang['node.name']="Имя узла";
+$lang['mon.std']="по умолчанию";
+$lang['mon.grp']="группы";
+$lang['mon.nodes']="узлы";
+$lang['mon.alerting']="тревоги";
+$lang['mon.hide']="...скрыть...";
+$lang['mon.goto.node']="перейти";
+$lang['mon.goto.node.page']="перейти на страницу узла";
+$lang['mon.popup.error']="Invalid or Illegal Node";
+
+// Node Page
+$lang['viewing.node']="Просмотр узла";
+$lang['no.node']="Узла не существует";
+$lang['enabled']="Включен";
+$lang['alert']="Тревога";
+$lang['yes']="Да";
+$lang['no']="Нет";
+$lang['alert.history']="История тревог";
+$lang['summary']="Действия";
+$lang['links']="Ссылки";
+$lang['opened']="Открыто";
+$lang['edit.node.options']="Настройки узла";
+$lang['nodeside.tests']="Тесты на стороне узла";
+
+$lang['local.tests']="Локальные тесты";
+$lang['history']="История";
+
+
+// Edit Node Options
+$lang['node.editor']="Редактировать";
+$lang['editing']="Редактирование";
+$lang['node.settings']="настройки узла";
+$lang['show.hide.options']="Показать / Скрыть настройки";
+$lang['node.tests']="Тесты";
+$lang['last.tested']="Последний раз тестировалось";
+$lang['add.test']="Добавить тест";
+$lang['no.such.node']="Узел не существует";
+$lang['create.test']="Создать тест";
+$lang['update.alert.actions']="ОБновить действия по тревоге";
+$lang['add']="Добавить";
+
+$lang['add.nodeside']="Добавить слежение со стороны узла";
+
+$lang['web.time']="Web Time";
+$lang['web.size']="Web Size";
+$lang['host']="Simple DNS Host";
+$lang['remote.ping']="Remote Ping";
+$lang['test.loop']="Test Loop";
+$lang['test.random']="Test Random";
+
+$lang['node.id']="Node ID";
+$lang['node.icon']="Node Icon";
+$lang['default']="Default";
+$lang['show.hide.icons']="Show/Hide Icons";
+$lang['master.node']="Master Node";
+$lang['no.master']="No Master Node";
+$lang['master.skip']="Skip if Master";
+$lang['fails.ping']="Fails Ping";
+$lang['fails.any.test']="Fails Any Test";
+$lang['node.enabled']="Node Enabled";
+$lang['test.schedule']="Test Schedule";
+$lang['test.interval']="Test Interval";
+$lang['test.due']="Test Due";
+$lang['check.asap']="Check ASAP";
+$lang['alerts.active']="Alerts Active";
+$lang['ping.test']="Ping Test";
+$lang['require.ping']="Require Ping";
+$lang['nodeside.testing']="Nodeside Testing";
+$lang['node.key']="Node Key";
+$lang['pull.enabled']="Pull Enabled";
+$lang['pull.url']="Pull URL";
+$lang['pull.interval']="Pull Interval";
+$lang['push.enabled']="Push Enabled";
+$lang['push.ip']="Push IP";
+$lang['last.date']="Last Data";
+$lang['next.pull.due']="Next Pull Due";
+$lang['catalogue']="Catalogue";
+$lang['nodeside.monitors']="Nodeside Monitors";
+$lang['refresh.now']="Обновить";
+$lang['nodeside.pull.now']="Refresh (Pull) Now";
+$lang['utility.links']="Utility Links";
+$lang['title']="Title";
+$lang['url']="URL";
+$lang['debug.raw']="Debug Raw Output";
+$lang['last.data']="Last Data";
+$lang['save.settings']="Сохранить";
+$lang['cancel']="Отменить";
+
+$lang['minutes']="Минуты";
+$lang['now']="Сейчас";
+$lang['edit.options']="Редактировать";
+
+$lang['save.ok']="Изменения сохранены";
+$lang['save.failed']="Изменения не сохранены";
+
+// Test Editing
+$lang['local.test.editor']="Local Test Editor";
+$lang['editing.test']="Редактировать";
+$lang['test.settings']="Настройки";
+$lang['test.type']="Тип";
+$lang['test.options']="Настройки";
+
+$lang['full.url']="Full URL including prefix e.g. http://www.somehost.com/";
+$lang['host.ip']="Имя или IP";
+$lang['host.desc']="Имя или IP для пинга (DNS resolution not timed)";
+$lang['value']="Значение";
+$lang['value.desc']="Value for Test Loop or Max Value for Test Random";
+$lang['host']="Имя";
+$lang['host.desc']="Hostname to resolve or IP address to do reverse lookup of";
+
+$lang['no.test.options']="No Options for Test";
+
+$lang['custom.name']="Custom Name";
+$lang['test.enabled']="Test Enabled";
+$lang['recorded']="Recorded";
+$lang['simple.eval']="Simple Evaluation";
+$lang['test.interval']="Test Interval";
+$lang['test.due']="Test Due";
+$lang['last.tested']="Last Tested";
+
+$lang['custom.attempts']="Custom Attempts";
+$lang['custom.timeout']="Custom Timeout";
+
+$lang['test.save']="Save Test Settings";
+$lang['abandon.changes']="Abandon Changes";
+
+$lang['seconds']="Seconds";
+
+$lang['passed']="Passed";
+$lang['untested']="Untested";
+$lang['warning']="Warning";
+$lang['failed']="Failed";
+$lang['failure']="Failure";
+
+$lang['test.evals']="Custom Test Evaluators";
+$lang['test.evals.simple']="Custom evaluators will not be parsed as Simple Evaluation is checked (above)";
+$lang['add.eval']="Add New";
+$lang['eval.equal']="Equal To";
+$lang['eval.lt']="Less Than";
+$lang['eval.gt']="Greater Than";
+
+$lang['edit.nodeside.test']="Nodeside Test Editor";
+$lang['ns.type']="Test Type / UID";
+$lang['nodeside.test']="Nodeside Test";
+$lang['test.alerts']="Test Alerts";
+$lang['last.checked']="Last Checked";
+$lang['last.result']="Last Result";
+$lang['last.value']="Last Value";
+$lang['save.changes']="Save Changes";
+
+$lang['result']="Result";
+
+$lang['edit.view']="Edit View";
+$lang['editing.view']="Editing View";
+$lang['no.such.view']="No Such View";
+$lang['preview']="Preview";
+$lang['linking']="Linking";
+$lang['unknown.action']="Unknown Action";
+$lang['expand.view.options']="Expand View Options";
+
+$lang['node.ping']="Node Ping";
+
+// Group Editor
+$lang['group.editor']="Редактор групп";
+$lang['no.group']="Группа не найдена";
+$lang['group.id']="ID группы";
+$lang['group.name']="Имя группы";
+$lang['group.icon']="Иконка группы";
+$lang['group.save']="Сохранить";
+$lang['group.members']="Члены группы";
+$lang['group.update']="Сохранить";
+$lang['group.updated']="Сохранено";
+$lang['group']="Группа";
+$lang['editing']="Редактировать";
+
+$lang['show.icons']="Показать все иконки";
+
+$lang['dns.host']="DNS Host Lookup";
+
+// Security Warnings
+$lang['sec.firstrun']="Security Warning: firstrun.php Script is Exposed";
+$lang['sec.firstrun.text']="The firstrun.php script in your web directory has not been renamed. This could be used to damage FreeNATS. Please rename to firstrun-.php.";
+$lang['sec.firstrun.ignore']="To stop this warning from being shown without renaming the script (not recommended) set site.firstrun.ignore to 1";
+
+// RSS
+$lang['rss.feed']="RSS Feed Management";
+$lang['rss.feed.name']="Feed Name";
+$lang['rss.feed.key']="Feed Key";
+$lang['rss.type']="Type of Feed";
+$lang['all.enabled.nodes']="All Enabled Nodes";
+$lang['one.node']="Single Node";
+$lang['rss.range']="Range/Scope of Feed";
+$lang['last.x.days']="Last X Days";
+$lang['last.x.alerts']="Last X Alerts";
+$lang['current.alerts']="Current Alerts";
+$lang['last.alerts.node']="Last Alert for Each Node";
+$lang['rss.feeds']="FreeNATS RSS Feeds";
+$lang['feed.url']="RSS Feed URL";
+$lang['feed.create']="Create New Feed";
+$lang['no.feeds']="No RSS Feeds Configured";
+$lang['open']="Open";
+$lang['closed']="Closed";
+
+// Help - Text support NATS_Help format strings i.e. {link} and {link|text} links
+$lang['nohelp'] = "Sorry no help is available";
+$lang['help.FREENATS'] = "FreeNATS is a network monitoring package";
+$lang['help.NODE'] = "A node is a system or device which you are monitoring. Note that nodes can have tests pointing to different physical devices and vice-versa";
+$lang['help.NODE:CREATE'] = "Create a new {node} with this {node:id|NodeID}";
+$lang['help.NODE:ID'] = "The NodeID is a unique text name for a {node}. Maximum length 60 chars and only normal characters allowed.";
+$lang['help.NODE:ENABLED'] = "The node is enabled for tests to be performed (and displayed in all applicable views)";
+$lang['help.NODE:ALERTACTIVE'] = "Alerts will be generated for this node and alert actions performed if selected";
+$lang['help.NODE:PINGTEST'] = "Do a ping (ICMP) test first before other tests - will always record results if enabled";
+$lang['help.NODE:REQUIREPING'] = "Require the ping to pass for other tests to even be tried - will always fail if {Node:PingTest|ping test} is disabled";
+$lang['help.NODE:MASTER'] = "Master Node to be Tested First";
+$lang['help.MASTERNODE:PING'] = "Tests required to pass on the {Node:Master|master node} for this node to be tested";
+$lang['help.NODE:TESTINTERVAL'] = "Interval (minutes) between tests on this node being carried out";
+$lang['help.NODESIDE'] = "Enable support for node-side scripts to gather data from this node";
+$lang['help.NODE:CHECKASAP'] = "Schedule node for immediate text in next test cycle";
+$lang['help.UTILLINKS'] = "Links to services on remote note for system administration";
+$lang['help.NODESIDE:KEY'] = "Key used to authenticate nodeside testing";
+$lang['help.NODESIDE:PULLENABLED'] = "Enable nodeside collection via http 'pull' from the node";
+$lang['help.NODESIDE:URL'] = "URL to 'pull' nodeside data from on the node";
+$lang['help.NODESIDE:INTERVAL'] = "Interval between 'pulling' (polling) data from the node";
+$lang['help.NODESIDE:PUSHENABLED'] = "Allow node to 'push' (post) data";
+$lang['help.NODESIDE:PUSHIP'] = "Limit node 'push' to this specific IP address for security";
+$lang['help.GROUP'] = "A group is a collection of one or more {node|nodes}. Note that nodes can be members of more than one group.";
+$lang['help.GROUP:CREATE'] = "Create a new {group} with this name";
+$lang['help.TEST:NAME'] = "A custom name can be assigned to the test for use in displays and alerts. If blank an automated name will be generated.";
+$lang['help.TEST:ATTEMPTS'] = "Number of times to attempt a test (will always try once). Defaults to 1 if zero or unset.";
+$lang['help.TEST:TIMEOUT'] = "Timeout value for the test - alters the defaults or system-wide variable settings for the relevant test (seconds)";
+$lang['help.TEST:SIMPLEEVALUATION'] = "Use simple pass/fail evaluation (i.e. if a web test returns any data it passes else it fails)";
+$lang['help.TEST:RECORDED'] = "Record the results of this test for historic reports";
+$lang['help.TEST:ENABLED'] = "Perform the test or not (will update nothing if disabled)";
+$lang['help.TEST:INTERVAL'] = "Interval (minutes) between this test being performed. Will only ever be tested as quickly as the {Node:TestInterval|node interval} is set to";
+$lang['help.TEST:TESTALERTS'] = "Test will generate an alert on failure";
+$lang['help.HISTORY:SHOULD'] = "A rough calculation based on configured polling times (i.e. test interval or node interval) from the start to finish (or now if sooner)";
+$lang['help.VIEW'] = "A view is a custom set of nodes/groups/tests which can be used in a variety of ways";
+$lang['help.VIEW:CREATE'] = "Creates a {view} of the specified name";
+$lang['help.VIEW:PUBLIC'] = "The view can be seen by people not logged into FreeNATS";
+$lang['help.VIEW:COLONS'] = "If text status is selected for a view item a colon will be displayed before it";
+$lang['help.VIEW:DASHES'] = "Display a dash before a test last run time where applicable";
+$lang['help.VIEW:TIMEAGO'] = "Use XX:XX ago or normal datetime for test details";
+$lang['help.VIEW:COLUMNS'] = "Display list-type elements in this number of columns (0 for off)";
+$lang['help.VIEW:REFRESH'] = "Send a http-equv to refresh the page after this many seconds (0 for off)";
+$lang['help.VIEW:USECOLOUR'] = "Use colour for status display as in normal FreeNATS display";
+$lang['help.VIEW:SHOWDETAIL'] = "Show details of the test/object(s) such as node tests";
+$lang['help.VIEW:TEXTSTATUS'] = "Textual status such as passed, failed etc";
+$lang['help.REPORT'] = "Reports show the %age of service availability in a specified period";
+$lang['help.BACKUP:TRUNCATE'] = "Clears tables first when restored back (recommended) otherwise duplicates may fail";
+$lang['help.SCHEDULE'] = "A schedule controls what times a node is tested and are managed through the admin page";
+$lang['help.SCHEDULE:DEFAULTACTION'] = "What will happen if no exceptions are matched (the opposite will happen if one is matched)";
+$lang['help.ALERTACTION'] = "An alert action is performed when a node fails a test, they are configured through the admin page";
+$lang['help.AACTION:WARNINGS'] = "The action is triggered for warning level events as well as failures (including downgrading from failure to warning if {AAction:Decreases|decreases} is set)";
+$lang['help.AACTION:DECREASES'] = "The action is triggered when the level goes down to closed (or {AAction:Warnings|warnings} if set)";
+$lang['help.AACTION:LIMIT'] = "Max times this action can run in any one day (0 = unlimited) to avoid flooding";
+$lang['help.AACTION:COUNTER'] = "Number of times this action has run in the day shown - you can manually reset this here";
+$lang['help.VARIABLE'] = "System variables are used to control the system environment. To delete a variable just save it with a blank name.";
+$lang['help.VAR:LOG.LEVEL'] = "The system log level - 10 is everything, 0 is fatal only. 5-6-ish is probably a good balance.";
+$lang['help.VAR:API.PUBLIC'] = "The API interface is available to public users if 1 (also see {Var:api.key|api.key})";
+$lang['help.VAR:API.KEY'] = "Require this key from public users as apikey when accessing the API ({Var:api.public|api.public} must be set)";
+$lang['help.VAR:ALERT.BODY.FOOTER'] = "Footer to go at the end of system generated alerts";
+$lang['help.VAR:ALERT.BODY.HEADER'] = "Header to go at the start of system generated alerts";
+$lang['help.VAR:ALERT.SUBJECT.LONG'] = "Subject for email alerts of long format";
+$lang['help.VAR:ALERT.SUBJECT.SHORT'] = "Subject for email alerts of short format";
+$lang['help.VAR:FREENATS.FIRSTRUN'] = "System variable to indicate first use of FreeNATS";
+$lang['help.VAR:SITE.ENABLE.TESTS'] = "Enable testing";
+$lang['help.VAR:SITE.ENABLE.WEB'] = "Enable web interface";
+$lang['help.VAR:SITE.ENABLE.TESTER'] = "Enable Tester to Run";
+$lang['help.VAR:SITE.GRAPH.PUBLIC'] = "Graphs are available to public users for views etc if 1 (also see {Var:site.graph.key|site.graph.key})";
+$lang['help.VAR:SITE.GRAPH.KEY'] = "Require this key from public users as graphkey ({Var:site.graph.public|site.graph.public} must be set)";
+$lang['help.VAR:SITE.ENABLE.INTERACTIVE'] = "Must be set (1) to allow interactive web sessions (like this one)";
+$lang['help.VAR:SITE.POPUPMESSAGE'] = "If set (1) will show a popup message when saving changes etc";
+$lang['help.VAR:SITE.DTFORMAT'] = "Site-wide custom date time format (in PHP format) i.e. Y-m-d H:i:s";
+$lang['help.VAR:SITE.TEXT.FAILED'] = "Text to show for a failed status (defaults to Failed if unset)";
+$lang['help.VAR:SITE.TEXT.PASSED'] = "Text to show for a passed status (defaults to Passed if unset)";
+$lang['help.VAR:SITE.TEXT.UNTESTED'] = "Text to show for untested items (defaults to Untested if unset)";
+$lang['help.VAR:SITE.TEXT.WARNING'] = "Text to show for a warning status (defaults to Warning if unset)";
+$lang['help.VAR:SITE.TEXT.CLOSED'] = "Text to indicate alert closed (defaults to Alert Closed if unset)";
+$lang['help.VAR:SITE.INCLUDE.EVENTS'] = "Include *.php in the server/site/events directory if 1";
+$lang['help.VAR:SITE.INCLUDE.TESTS'] = "Include *.php in the server/site/tests directory if 1";
+$lang['help.VAR:SITE.ENABLE.ADMINSQL'] = "Enables the admin SQL console if 1";
+$lang['help.VAR:SITE.LINKS.NEWWINDOW'] = "Opens {UtilLinks|utility links} in new window if 1";
+$lang['help.VAR:SITE.MONITOR.POPUPS'] = "Opens a popup status window in live monitor unless set to 0";
+$lang['help.VAR:SITE.FIRSTRUN.IGNORE'] = "Ignores the existance of the firstrun.php script (dangerous)";
+$lang['help.VAR:SITE.AUTH'] = "If set to http will use HTTP-AUTH otherwises uses standard login form";
+$lang['help.VAR:MAIL.FROMNAME'] = "Textual from name to be used in SMTP mail (defaults to FreeNATS if unset)";
+$lang['help.VAR:MAIL.SMTPSERVER'] = "SMTP server to relay mail through (can be ; seperated list) uses internal mail() if unset or blank";
+$lang['help.VAR:MAIL.SMTPUSERNAME'] = "Username for SMTP AUTH (AUTH only used if username is set or provided)";
+$lang['help.VAR:MAIL.SMTPPASSWORD'] = "Password for SMTP AUTH";
+$lang['help.VAR:MAIL.SMTPHOSTNAME'] = "Hostname for HELO in SMTP transactions (may be required for strict mail servers)";
+$lang['help.VAR:TEST.ICMP.TIMEOUT'] = "Timeout in seconds to wait for an ICMP response before declaring a failure in seconds (default 10)";
+$lang['help.VAR:TEST.ICMP.TRYTWICE'] = "Depreciated - replaced with {Var:test.icmp.attempts|test.icmp.attempts}";
+$lang['help.VAR:TEST.ICMP.ATTEMPTS'] = "Number of times the main "require ping" test will attempt before failing (default 2)";
+$lang['help.VAR:TEST.ICMP.RETURNMS'] = "If set (1) returns ping results in MilliSeconds (ms) (default 0)";
+$lang['help.VAR:TEST.HTTP.TIMEOUT'] = "Default timeout for HTTP/s streams used in web tests (uses system default if unset or <1)";
+$lang['help.VAR:TEST.IMAP.TIMEOUT'] = "Default timeout for IMAP tests in seconds (uses environment default if unset or 0)";
+$lang['help.VAR:TEST.SMTP.TIMEOUT'] = "Default timeout for SMTP tests in seconds (uses 20 seconds if 0 or unset)";
+$lang['help.VAR:TEST.MYSQL.TIMEOUT'] = "Default timeout for MySQL tests in seconds (uses environmental default if unset or 0)";
+$lang['help.VAR:TEST.SPAWNDELAY'] = "Delay in seconds between node test threads being spawned by test-threaded.sh (no delay if 0 or unset), can be a decimal";
+$lang['help.VAR:TEST.INTERVAL'] = "Delay in seconds between tests on a node (no delay if 0 or unset), can be a decimal";
+$lang['help.VAR:TEST.TCP.TIMEOUT'] = "Default timeout for TCP tests (system default if 0 or unset) (seconds)";
+$lang['help.VAR:TEST.UDP.TIMEOUT'] = "Default timeout for UDP tests (system default if 0 or unset) (seconds)";
+$lang['help.VAR:RETAIN.ALERT'] = "Days to retain alert records for (default 356 if 0 or unset). Retain forever with value -1.";
+$lang['help.VAR:RETAIN.RECORD'] = "Days to retain test result records for use in history and graphs (default 356 if 0 or unsert). Retain forever with value -1.";
+$lang['help.VAR:RETAIN.TESTRUN'] = "Days to retain test run records for (default 30 if 0 or unset). Retain forever with value -1.";
+$lang['help.VAR:RETAIN.SYSLOG'] = "Days to retain log entries for (default 30 if 0 or unset). Retain forever with value -1.";
+$lang['help.VAR:FREENATS.TRACKER'] = "Participate in the automated feedback process - 1 for yes low level, 2 for detailed, 0 for disabled (default 0)";
+$lang['help.VAR:FREENATS.TRACKER.USID'] = "Unique Site ID for FreeNATS tracker to anonymise data capture (only if {Var:freenats.tracker|freenats.tracker} set to 1";
+
+
+?>
diff --git a/src/server/base/nats.cfg.inc.php b/src/server/base/nats.cfg.inc.php
new file mode 100755
index 0000000..b32fe90
--- /dev/null
+++ b/src/server/base/nats.cfg.inc.php
@@ -0,0 +1,70 @@
+Query($q);
+ while ($row=$nats_db->Fetch_Array($r))
+ {
+ $this->data[$row['fnc_var']]=$row['fnc_val'];
+ //echo $row['fnc_var']."=".$row['fnc_val']."\n ";
+ }
+ $nats_db->Free($r);
+ }
+
+ function Get($var,$def="")
+ {
+ if (isset($this->data[$var])) return $this->data[$var];
+ return $def;
+ }
+
+ function DumpToScreen()
+ {
+ $keys=array_keys($this->data);
+ foreach($keys as $key)
+ {
+ echo $key."=".$this->data[$key]." \n";
+ }
+ }
+ function Set($var,$val,$perm=true)
+ {
+ $this->data[$var]=$val;
+ if ($perm)
+ {
+ global $NATS;
+ $q="UPDATE fnconfig SET fnc_val=\"".ss($val)."\" WHERE fnc_var=\"".ss($var)."\"";
+ $NATS->DB->Query($q);
+ if ($NATS->DB->Affected_Rows()<=0) // not already existing
+ {
+ $q="INSERT INTO fnconfig(fnc_var,fnc_val) VALUES(\"".ss($var)."\",\"".ss($val)."\")";
+ mysql_query($q);
+ }
+ }
+ }
+ }
\ No newline at end of file
diff --git a/src/server/base/nats.db.inc.php b/src/server/base/nats.db.inc.php
new file mode 100755
index 0000000..faff03c
--- /dev/null
+++ b/src/server/base/nats.db.inc.php
@@ -0,0 +1,126 @@
+sql=mysql_connect($fnCfg['db.server'],$fnCfg['db.username'],$fnCfg['db.password'])
+ or die("Cannot connect to MySQL server");
+ mysql_select_db($fnCfg['db.database'])
+ or die("Cannot select MySQL database");
+ $this->connected=true;
+ return $this->sql;
+ }
+
+ function Disconnect()
+ {
+ mysql_close($this->sql);
+ $this->sql=0;
+ $this->connected=false;
+ }
+
+ function Query($query,$debugerror=true)
+ {
+ global $NATS;
+ if (!$this->connected) return -1;
+ $result=mysql_query($query,$this->sql);
+ if ($debugerror)
+ {
+ // persist the last error state
+ $this->LastError=mysql_errno($this->sql);
+ if ($this->LastError>0)
+ {
+ $this->ErrorString=mysql_error($this->sql)." (".mysql_errno($this->sql).")";
+ }
+ else $this->ErrorString="";
+ }
+
+ if (mysql_errno($this->sql)>0)
+ {
+ $err=mysql_error($this->sql)." (".mysql_errno($this->sql).")";
+ if (isset($NATS)&&$debugerror)
+ {
+ $NATS->Event("Query Failed: ".$query,2,"DB","Query");
+ $NATS->Event("Query Error: ".$err,2,"DB","Query");
+ }
+ }
+ return $result;
+ }
+
+ function Free(&$result)
+ {
+ mysql_free_result($result);
+ }
+
+ function Fetch_Array(&$result)
+ {
+ return mysql_fetch_array($result);
+ }
+
+ function Affected_Rows()
+ {
+ return mysql_affected_rows($this->sql);
+ }
+
+ function Insert_Id()
+ {
+ return mysql_insert_id($this->sql);
+ }
+
+ function Num_Rows(&$result)
+ {
+ return mysql_num_rows($result);
+ }
+
+ function Error()
+ {
+ //if (mysql_errno($this->sql)==0) return false;
+ //return true;
+ if ($this->LastError==0) return false;
+ return true;
+ }
+
+ function Error_Number()
+ {
+ //return mysql_errno($this->sql);
+ return $this->LastError;
+ }
+
+ function Error_String()
+ {
+ return $this->ErrorString;
+ //return mysql_error($this->sql)." (".$this->Error_Number().")";
+ }
+ }
\ No newline at end of file
diff --git a/src/server/base/nats.lang.inc.php b/src/server/base/nats.lang.inc.php
new file mode 100755
index 0000000..d91ae30
--- /dev/null
+++ b/src/server/base/nats.lang.inc.php
@@ -0,0 +1,86 @@
+languages) )
+ {
+ $pathlen=strlen($BaseDir."lang/");
+ $this->languages=array();
+ foreach(glob($BaseDir."lang/*.lang.php") as $langfile)
+ {
+ $langfile=substr($langfile,$pathlen);
+ $parts=explode(".",$langfile);
+ if (count($parts)==4) // valid language format Language.code.lang.php
+ {
+ $this->languages[$parts[1]]=$parts[0];
+ }
+ }
+ }
+return $this->languages;
+}
+
+function Load($language="")
+{
+global $BaseDir,$NATS;
+$this->GetLanguages();
+if ($language == "") $language=$this->baselanguage;
+if ($language != $this->baselanguage) $this->Load($this->baselanguage);
+if (!is_array($this->items)) $this->items=array();
+
+if ( isset($this->languages[$language]) )
+ {
+ $file=$BaseDir."lang/".$this->languages[$language].".".$language.".lang.php";
+ if (file_exists($file))
+ {
+ $lang=array();
+ include_once($file);
+ $this->items = array_merge($this->items, $lang);
+ }
+ else $NATS->Event("Language file ".$file." not found",5,"Language","Load");
+ }
+else $NATS->Event("Illegal Language ".$language,5,"Language","Load");
+}
+
+function Item($item)
+{
+global $NATS;
+//return "{".$item."}";
+if (isset($this->items[$item])) return $this->items[$item];
+else
+ {
+ $NATS->PageError("missing lang.element {ULE}",$item);
+ return "ULE{".$item."}";
+ }
+}
+
+}
+
+?>
\ No newline at end of file
diff --git a/src/server/base/nats.php b/src/server/base/nats.php
new file mode 100755
index 0000000..03e2b31
--- /dev/null
+++ b/src/server/base/nats.php
@@ -0,0 +1,69 @@
+Start();
+
+// Session Management
+require($BaseDir."session.inc.php");
+$NATS_Session=new TNATS_Session();
+
+
+
+
+
+// Screen and Stuff
+require($BaseDir."screen.inc.php");
+require($BaseDir."testtext.inc.php");
+require($BaseDir."view.inc.php");
+?>
\ No newline at end of file
diff --git a/src/server/base/nats.tests.inc.php b/src/server/base/nats.tests.inc.php
new file mode 100755
index 0000000..483a8e1
--- /dev/null
+++ b/src/server/base/nats.tests.inc.php
@@ -0,0 +1,105 @@
+type=$type;
+ $this->class=$class;
+ if ($name=="") $this->name=$type;
+ else $this->name=$name;
+ $this->revision=$revision;
+ $this->additional=$additional;
+ if ($parameters===false) $this->parameters=array();
+ else $this->parameters=$parameters;
+ }
+
+function Create()
+ {
+ if ($this->instance===false) // doesn't exist
+ {
+ $this->instance=new $this->class();
+ }
+ return $this->instance;
+ }
+}
+
+class TNATS_Tests
+{
+var $count=0;
+var $Tests=array();
+var $QuickList=array(); // quick list to save doing it dynamically each time
+var $UnitList=array(); // Unit list for easy reference
+
+function Register($type,$class,$parameters=false,$name="",$revision=0,$additional="")
+ {
+ if ($name=="") $name=$type;
+ $this->Tests[$type]=new TNATS_Test($type,$class,$parameters,$name,$revision,$additional);
+ $this->QuickList[$type]=$name;
+ $this->count++;
+ }
+
+function Get($type)
+ {
+ if (isset($this->Tests[$type])) return $this->Tests[$type];
+ return -1;
+ }
+
+function QuickList()
+ {
+ return $this->QuickList;
+ }
+
+function Exists($type)
+ {
+ if (isset($this->Tests[$type])) return true;
+ return false;
+ }
+
+function SetUnits($type,$long,$short="")
+ {
+ if (!isset($this->UnitList[$type]))
+ $this->UnitList[$type]=array();
+
+ $this->UnitList[$type]['long']=$long;
+ $this->UnitList[$type]['short']=$short;
+ }
+
+function Units($type,$long=true)
+ {
+ if (!isset($this->UnitList[$type])) return "";
+ if ($long) return $this->UnitList[$type]['long'];
+ else return $this->UnitList[$type]['short'];
+ }
+
+
+}
+?>
\ No newline at end of file
diff --git a/src/server/base/node.xml.inc.php b/src/server/base/node.xml.inc.php
new file mode 100755
index 0000000..8b10363
--- /dev/null
+++ b/src/server/base/node.xml.inc.php
@@ -0,0 +1,167 @@
+debug_log)
+ $NATS->Event("Start Element: ".$name,10,"NodeXML","StartE");
+if ($name=="FREENATS-DATA")
+ {
+ $this->in_freenats=true;
+ if ($this->debug_log)
+ $NATS->Event("in_freenats set to true",10,"NodeXML","StartE");
+ }
+if (!$this->in_freenats) return 0;
+
+if ($this->debug_log)
+ $NATS->Event("startE passed in_freenats true",10,"NodeXML","StartE");
+
+if ($name=="TEST")
+ {
+ $this->in_test=true;
+ $this->Tests++;
+ $this->cur_testname=$attrs['NAME'];
+ if ($this->debug_log)
+ $NATS->Event("Test Element: ".$this->cur_testname,10,"NodeXML","TestE");
+ }
+else if ($name=="HEADER") $in_header=true;
+$this->last_element=$name;
+$this->depth++;
+$this->Elements++;
+}
+
+function endElement($parser, $name)
+{
+global $NATS;
+$this->depth--;
+if ($name=="TEST") $in_test=false;
+else if ($name=="HEADER") $in_header=false;
+else if ($name=="FREENATS-DATA")
+ {
+ $in_freenats=false;
+ if ($this->debug_log)
+ $NATS->Event("endE in_freenats set to false",10,"NodeXML","EndE");
+ }
+if ($this->debug_log)
+ $NATS->Event("End Element: ".$name,10,"NodeXML","EndE");
+}
+
+function charData($parser,$data)
+{
+global $NATS;
+if ($this->debug_log) $NATS->Event("Char Data Called",10,"NodeXML","CharData");
+if (!$this->in_freenats)
+ {
+ if ($this->debug_log)
+ $NATS->Event("Char Data in_freenats FALSE",10,"NodeXML","CharData");
+ return 0;
+ }
+if ($this->debug_log)
+ {
+ $NATS->Event("Char Data in FreeNATS",10,"NodeXML","CharData");
+ $NATS->Event("Untrimmed Data: ".$data,10,"NodeXML","CharData");
+ }
+
+$data=trim($data);
+if ($data!="")
+ {
+ if ($this->debug_log)
+ $NATS->Event("Data: ".$data,10,"NodeXML","CharData");
+
+ if ($this->in_test)
+ {
+ $this->Catalogue[$this->cur_testname][$this->last_element]=$data;
+ }
+ else if ($this->in_header)
+ $this->Header[$this->last_element]=$data;
+ }
+}
+
+function Error()
+{
+return $this->LastError;
+}
+
+function Parse($xml)
+{
+if (get_magic_quotes_gpc()) $xml=stripslashes($xml);
+$this->Init=true;
+$parser=xml_parser_create();
+xml_set_element_handler($parser,Array( $this, "startElement" ),
+ Array( $this, "endElement" ) );
+xml_set_character_data_handler($parser,Array( $this, "charData" ));
+
+$return=true;
+
+if (!xml_parse($parser,$xml,true))
+ {
+ $this->LastError="XML Error ".xml_error_string(xml_get_error_code($parser));
+ $this->LastError.=" at line ".xml_get_current_line_number($parser);
+ if ($debug_log) $NATS->Event($this->LastError,5,"NodeXML","Parse");
+ $return=false;
+ }
+
+xml_parser_free($parser);
+
+if ($return) return $this->Catalogue;
+else return 0;
+}
+
+function ParseFile($xmlfile)
+{
+$fp=fopen($xmlfile,"r")
+ or die("Could not open XML file ".$xmlfile);
+$data="";
+while (!feof($fp))
+ $data.=fgets($fp,4096);
+fclose($fp);
+return $this->Parse($data);
+}
+
+
+}
+?>
\ No newline at end of file
diff --git a/src/server/base/phpmailer/LICENSE b/src/server/base/phpmailer/LICENSE
new file mode 100644
index 0000000..03851a3
--- /dev/null
+++ b/src/server/base/phpmailer/LICENSE
@@ -0,0 +1,504 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+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 and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, 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 library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete 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 distribute a copy of this License along with the
+Library.
+
+ 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 Library or any portion
+of it, thus forming a work based on the Library, 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) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+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 Library, 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 Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you 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.
+
+ If distribution of 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 satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be 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.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library 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.
+
+ 9. 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 Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+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 with
+this License.
+
+ 11. 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 Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library 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 Library.
+
+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.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library 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.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser 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 Library
+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 Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+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
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "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
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. 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 LIBRARY 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
+LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), 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 Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. 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.
+
+
+ Copyright (C)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ , 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/src/server/base/phpmailer/README b/src/server/base/phpmailer/README
new file mode 100644
index 0000000..2d79f38
--- /dev/null
+++ b/src/server/base/phpmailer/README
@@ -0,0 +1,218 @@
+/*******************************************************************
+* The http://phpmailer.codeworxtech.com/ website now carries a few *
+* advertisements through the Google Adsense network. Please visit *
+* the advertiser sites and help us offset some of our costs. *
+* Thanks .... *
+********************************************************************/
+
+PHPMailer
+Full Featured Email Transfer Class for PHP
+==========================================
+
+Version 5.0.0 (April 02, 2009)
+
+With the release of this version, we are initiating a new version numbering
+system to differentiate from the PHP4 version of PHPMailer.
+
+Most notable in this release is fully object oriented code.
+
+We now have available the PHPDocumentor (phpdocs) documentation. This is
+separate from the regular download to keep file sizes down. Please see the
+download area of http://phpmailer.codeworxtech.com.
+
+We also have created a new test script (see /test_script) that you can use
+right out of the box. Copy the /test_script folder directly to your server (in
+the same structure ... with class.phpmailer.php and class.smtp.php in the
+folder above it. Then launch the test script with:
+http://www.yourdomain.com/phpmailer/test_script/index.php
+from this one script, you can test your server settings for mail(), sendmail (or
+qmail), and SMTP. This will email you a sample email (using contents.html for
+the email body) and two attachments. One of the attachments is used as an inline
+image to demonstrate how PHPMailer will automatically detect if attachments are
+the same source as inline graphics and only include one version. Once you click
+the Submit button, the results will be displayed including any SMTP debug
+information and send status. We will also display a version of the script that
+you can cut and paste to include in your projects. Enjoy!
+
+Version 2.3 (November 08, 2008)
+
+We have removed the /phpdoc from the downloads. All documentation is now on
+the http://phpmailer.codeworxtech.com website.
+
+The phpunit.php has been updated to support PHP5.
+
+For all other changes and notes, please see the changelog.
+
+Donations are accepted at PayPal with our id "paypal@worxteam.com".
+
+Version 2.2 (July 15 2008)
+
+- see the changelog.
+
+Version 2.1 (June 04 2008)
+
+With this release, we are announcing that the development of PHPMailer for PHP5
+will be our focus from this date on. We have implemented all the enhancements
+and fixes from the latest release of PHPMailer for PHP4.
+
+Far more important, though, is that this release of PHPMailer (v2.1) is
+fully tested with E_STRICT error checking enabled.
+
+** NOTE: WE HAVE A NEW LANGUAGE VARIABLE FOR DIGITALLY SIGNED S/MIME EMAILS.
+ IF YOU CAN HELP WITH LANGUAGES OTHER THAN ENGLISH AND SPANISH, IT WOULD BE
+ APPRECIATED.
+
+We have now added S/MIME functionality (ability to digitally sign emails).
+BIG THANKS TO "sergiocambra" for posting this patch back in November 2007.
+The "Signed Emails" functionality adds the Sign method to pass the private key
+filename and the password to read it, and then email will be sent with
+content-type multipart/signed and with the digital signature attached.
+
+A quick note on E_STRICT:
+
+- In about half the test environments the development version was subjected
+ to, an error was thrown for the date() functions (used at line 1565 and 1569).
+ This is NOT a PHPMailer error, it is the result of an incorrectly configured
+ PHP5 installation. The fix is to modify your 'php.ini' file and include the
+ date.timezone = America/New York
+ directive, (for your own server timezone)
+- If you do get this error, and are unable to access your php.ini file, there is
+ a workaround. In your PHP script, add
+ date_default_timezone_set('America/Toronto');
+
+ * do NOT try to use
+ $myVar = date_default_timezone_get();
+ as a test, it will throw an error.
+
+We have also included more example files to show the use of "sendmail", "mail()",
+"smtp", and "gmail".
+
+We are also looking for more programmers to join the volunteer development team.
+If you have an interest in this, please let us know.
+
+Enjoy!
+
+
+Version 2.1.0beta1 & beta2
+
+please note, this is BETA software
+** DO NOT USE THIS IN PRODUCTION OR LIVE PROJECTS
+INTENDED STRICTLY FOR TESTING
+
+** NOTE:
+
+As of November 2007, PHPMailer has a new project team headed by industry
+veteran Andy Prevost (codeworxtech). The first release in more than two
+years will focus on fixes, adding ease-of-use enhancements, provide
+basic compatibility with PHP4 and PHP5 using PHP5 backwards compatibility
+features. A new release is planned before year-end 2007 that will provide
+full compatiblity with PHP4 and PHP5, as well as more bug fixes.
+
+We are looking for project developers to assist in restoring PHPMailer to
+its leadership position. Our goals are to simplify use of PHPMailer, provide
+good documentation and examples, and retain backward compatibility to level
+1.7.3 standards.
+
+If you are interested in helping out, visit http://sourceforge.net/projects/phpmailer
+and indicate your interest.
+
+**
+
+http://phpmailer.sourceforge.net/
+
+This software is licenced under the LGPL. Please read LICENSE for information on the
+software availability and distribution.
+
+Class Features:
+- Send emails with multiple TOs, CCs, BCCs and REPLY-TOs
+- Redundant SMTP servers
+- Multipart/alternative emails for mail clients that do not read HTML email
+- Support for 8bit, base64, binary, and quoted-printable encoding
+- Uses the same methods as the very popular AspEmail active server (COM) component
+- SMTP authentication
+- Native language support
+- Word wrap, and more!
+
+Why you might need it:
+
+Many PHP developers utilize email in their code. The only PHP function
+that supports this is the mail() function. However, it does not expose
+any of the popular features that many email clients use nowadays like
+HTML-based emails and attachments. There are two proprietary
+development tools out there that have all the functionality built into
+easy to use classes: AspEmail(tm) and AspMail. Both of these
+programs are COM components only available on Windows. They are also a
+little pricey for smaller projects.
+
+Since I do Linux development I�ve missed these tools for my PHP coding.
+So I built a version myself that implements the same methods (object
+calls) that the Windows-based components do. It is open source and the
+LGPL license allows you to place the class in your proprietary PHP
+projects.
+
+
+Installation:
+
+Copy class.phpmailer.php into your php.ini include_path. If you are
+using the SMTP mailer then place class.smtp.php in your path as well.
+In the language directory you will find several files like
+phpmailer.lang-en.php. If you look right before the .php extension
+that there are two letters. These represent the language type of the
+translation file. For instance "en" is the English file and "br" is
+the Portuguese file. Chose the file that best fits with your language
+and place it in the PHP include path. If your language is English
+then you have nothing more to do. If it is a different language then
+you must point PHPMailer to the correct translation. To do this, call
+the PHPMailer SetLanguage method like so:
+
+// To load the Portuguese version
+$mail->SetLanguage("br", "/optional/path/to/language/directory/");
+
+That's it. You should now be ready to use PHPMailer!
+
+
+A Simple Example:
+
+IsSMTP(); // set mailer to use SMTP
+$mail->Host = "smtp1.example.com;smtp2.example.com"; // specify main and backup server
+$mail->SMTPAuth = true; // turn on SMTP authentication
+$mail->Username = "jswan"; // SMTP username
+$mail->Password = "secret"; // SMTP password
+
+$mail->From = "from@example.com";
+$mail->FromName = "Mailer";
+$mail->AddAddress("josh@example.net", "Josh Adams");
+$mail->AddAddress("ellen@example.com"); // name is optional
+$mail->AddReplyTo("info@example.com", "Information");
+
+$mail->WordWrap = 50; // set word wrap to 50 characters
+$mail->AddAttachment("/var/tmp/file.tar.gz"); // add attachments
+$mail->AddAttachment("/tmp/image.jpg", "new.jpg"); // optional name
+$mail->IsHTML(true); // set email format to HTML
+
+$mail->Subject = "Here is the subject";
+$mail->Body = "This is the HTML message body in bold!";
+$mail->AltBody = "This is the body in plain text for non-HTML mail clients";
+
+if(!$mail->Send())
+{
+ echo "Message could not be sent.
";
+ echo "Mailer Error: " . $mail->ErrorInfo;
+ exit;
+}
+
+echo "Message has been sent";
+?>
+
+CHANGELOG
+
+See ChangeLog.txt
+
+Download: http://sourceforge.net/project/showfiles.php?group_id=26031
+
+Andy Prevost
diff --git a/src/server/base/phpmailer/class.phpmailer.php b/src/server/base/phpmailer/class.phpmailer.php
new file mode 100644
index 0000000..aeb4bc3
--- /dev/null
+++ b/src/server/base/phpmailer/class.phpmailer.php
@@ -0,0 +1,2068 @@
+exceptions = ($exceptions == true);
+ }
+
+ /**
+ * Sets message type to HTML.
+ * @param bool $ishtml
+ * @return void
+ */
+ public function IsHTML($ishtml = true) {
+ if ($ishtml) {
+ $this->ContentType = 'text/html';
+ } else {
+ $this->ContentType = 'text/plain';
+ }
+ }
+
+ /**
+ * Sets Mailer to send message using SMTP.
+ * @return void
+ */
+ public function IsSMTP() {
+ $this->Mailer = 'smtp';
+ }
+
+ /**
+ * Sets Mailer to send message using PHP mail() function.
+ * @return void
+ */
+ public function IsMail() {
+ $this->Mailer = 'mail';
+ }
+
+ /**
+ * Sets Mailer to send message using the $Sendmail program.
+ * @return void
+ */
+ public function IsSendmail() {
+ if (!stristr(ini_get('sendmail_path'), 'sendmail')) {
+ $this->Sendmail = '/var/qmail/bin/sendmail';
+ }
+ $this->Mailer = 'sendmail';
+ }
+
+ /**
+ * Sets Mailer to send message using the qmail MTA.
+ * @return void
+ */
+ public function IsQmail() {
+ if (stristr(ini_get('sendmail_path'), 'qmail')) {
+ $this->Sendmail = '/var/qmail/bin/sendmail';
+ }
+ $this->Mailer = 'sendmail';
+ }
+
+ /////////////////////////////////////////////////
+ // METHODS, RECIPIENTS
+ /////////////////////////////////////////////////
+
+ /**
+ * Adds a "To" address.
+ * @param string $address
+ * @param string $name
+ * @return boolean true on success, false if address already used
+ */
+ public function AddAddress($address, $name = '') {
+ return $this->AddAnAddress('to', $address, $name);
+ }
+
+ /**
+ * Adds a "Cc" address.
+ * Note: this function works with the SMTP mailer on win32, not with the "mail" mailer.
+ * @param string $address
+ * @param string $name
+ * @return boolean true on success, false if address already used
+ */
+ public function AddCC($address, $name = '') {
+ return $this->AddAnAddress('cc', $address, $name);
+ }
+
+ /**
+ * Adds a "Bcc" address.
+ * Note: this function works with the SMTP mailer on win32, not with the "mail" mailer.
+ * @param string $address
+ * @param string $name
+ * @return boolean true on success, false if address already used
+ */
+ public function AddBCC($address, $name = '') {
+ return $this->AddAnAddress('bcc', $address, $name);
+ }
+
+ /**
+ * Adds a "Reply-to" address.
+ * @param string $address
+ * @param string $name
+ * @return boolean
+ */
+ public function AddReplyTo($address, $name = '') {
+ return $this->AddAnAddress('ReplyTo', $address, $name);
+ }
+
+ /**
+ * Adds an address to one of the recipient arrays
+ * Addresses that have been added already return false, but do not throw exceptions
+ * @param string $kind One of 'to', 'cc', 'bcc', 'ReplyTo'
+ * @param string $address The email address to send to
+ * @param string $name
+ * @return boolean true on success, false if address already used or invalid in some way
+ * @access private
+ */
+ private function AddAnAddress($kind, $address, $name = '') {
+ if (!preg_match('/^(to|cc|bcc|ReplyTo)$/', $kind)) {
+ echo 'Invalid recipient array: ' . kind;
+ return false;
+ }
+ $address = trim($address);
+ $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
+ if (!self::ValidateAddress($address)) {
+ $this->SetError($this->Lang('invalid_address').': '. $address);
+ if ($this->exceptions) {
+ throw new phpmailerException($this->Lang('invalid_address').': '.$address);
+ }
+ echo $this->Lang('invalid_address').': '.$address;
+ return false;
+ }
+ if ($kind != 'ReplyTo') {
+ if (!isset($this->all_recipients[strtolower($address)])) {
+ array_push($this->$kind, array($address, $name));
+ $this->all_recipients[strtolower($address)] = true;
+ return true;
+ }
+ } else {
+ if (!array_key_exists(strtolower($address), $this->ReplyTo)) {
+ $this->ReplyTo[strtolower($address)] = array($address, $name);
+ return true;
+ }
+ }
+ return false;
+ }
+
+/**
+ * Set the From and FromName properties
+ * @param string $address
+ * @param string $name
+ * @return boolean
+ */
+ public function SetFrom($address, $name = '') {
+ $address = trim($address);
+ $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
+ if (!self::ValidateAddress($address)) {
+ $this->SetError($this->Lang('invalid_address').': '. $address);
+ if ($this->exceptions) {
+ throw new phpmailerException($this->Lang('invalid_address').': '.$address);
+ }
+ echo $this->Lang('invalid_address').': '.$address;
+ return false;
+ }
+ $this->From = $address;
+ $this->FromName = $name;
+ return true;
+ }
+
+ /**
+ * Check that a string looks roughly like an email address should
+ * Static so it can be used without instantiation
+ * Tries to use PHP built-in validator in the filter extension (from PHP 5.2), falls back to a reasonably competent regex validator
+ * Conforms approximately to RFC2822
+ * @link http://www.hexillion.com/samples/#Regex Original pattern found here
+ * @param string $address The email address to check
+ * @return boolean
+ * @static
+ * @access public
+ */
+ public static function ValidateAddress($address) {
+ if (function_exists('filter_var')) { //Introduced in PHP 5.2
+ if(filter_var($address, FILTER_VALIDATE_EMAIL) === FALSE) {
+ return false;
+ } else {
+ return true;
+ }
+ } else {
+ return preg_match('/^(?:[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+\.)*[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+@(?:(?:(?:[a-zA-Z0-9_](?:[a-zA-Z0-9_\-](?!\.)){0,61}[a-zA-Z0-9_-]?\.)+[a-zA-Z0-9_](?:[a-zA-Z0-9_\-](?!$)){0,61}[a-zA-Z0-9_]?)|(?:\[(?:(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\]))$/', $address);
+ }
+ }
+
+ /////////////////////////////////////////////////
+ // METHODS, MAIL SENDING
+ /////////////////////////////////////////////////
+
+ /**
+ * Creates message and assigns Mailer. If the message is
+ * not sent successfully then it returns false. Use the ErrorInfo
+ * variable to view description of the error.
+ * @return bool
+ */
+ public function Send() {
+ try {
+ if ((count($this->to) + count($this->cc) + count($this->bcc)) < 1) {
+ throw new phpmailerException($this->Lang('provide_address'), self::STOP_CRITICAL);
+ }
+
+ // Set whether the message is multipart/alternative
+ if(!empty($this->AltBody)) {
+ $this->ContentType = 'multipart/alternative';
+ }
+
+ $this->error_count = 0; // reset errors
+ $this->SetMessageType();
+ $header = $this->CreateHeader();
+ $body = $this->CreateBody();
+
+ if (empty($this->Body)) {
+ throw new phpmailerException($this->Lang('empty_message'), self::STOP_CRITICAL);
+ }
+
+ // Choose the mailer and send through it
+ switch($this->Mailer) {
+ case 'sendmail':
+ return $this->SendmailSend($header, $body);
+ case 'smtp':
+ return $this->SmtpSend($header, $body);
+ case 'mail':
+ default:
+ return $this->MailSend($header, $body);
+ }
+
+ } catch (phpmailerException $e) {
+ $this->SetError($e->getMessage());
+ if ($this->exceptions) {
+ throw $e;
+ }
+ echo $e->getMessage()."\n";
+ return false;
+ }
+ }
+
+ /**
+ * Sends mail using the $Sendmail program.
+ * @param string $header The message headers
+ * @param string $body The message body
+ * @access protected
+ * @return bool
+ */
+ protected function SendmailSend($header, $body) {
+ if ($this->Sender != '') {
+ $sendmail = sprintf("%s -oi -f %s -t", escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender));
+ } else {
+ $sendmail = sprintf("%s -oi -t", escapeshellcmd($this->Sendmail));
+ }
+ if(!@$mail = popen($sendmail, 'w')) {
+ throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
+ }
+ fputs($mail, $header);
+ fputs($mail, $body);
+ $result = pclose($mail);
+ if($result != 0) {
+ throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
+ }
+ return true;
+ }
+
+ /**
+ * Sends mail using the PHP mail() function.
+ * @param string $header The message headers
+ * @param string $body The message body
+ * @access protected
+ * @return bool
+ */
+ protected function MailSend($header, $body) {
+ $toArr = array();
+ foreach($this->to as $t) {
+ $toArr[] = $this->AddrFormat($t);
+ }
+ $to = implode(', ', $toArr);
+
+ $params = sprintf("-oi -f %s", $this->Sender);
+ if ($this->Sender != '' && strlen(ini_get('safe_mode'))< 1) {
+ $old_from = ini_get('sendmail_from');
+ ini_set('sendmail_from', $this->Sender);
+ if ($this->SingleTo === true && count($toArr) > 1) {
+ foreach ($toArr as $key => $val) {
+ $rt = @mail($val, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params);
+ }
+ } else {
+ $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params);
+ }
+ } else {
+ if ($this->SingleTo === true && count($toArr) > 1) {
+ foreach ($toArr as $key => $val) {
+ $rt = @mail($val, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params);
+ }
+ } else {
+ $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header);
+ }
+ }
+ if (isset($old_from)) {
+ ini_set('sendmail_from', $old_from);
+ }
+ if(!$rt) {
+ throw new phpmailerException($this->Lang('instantiate'), self::STOP_CRITICAL);
+ }
+ return true;
+ }
+
+ /**
+ * Sends mail via SMTP using PhpSMTP
+ * Returns false if there is a bad MAIL FROM, RCPT, or DATA input.
+ * @param string $header The message headers
+ * @param string $body The message body
+ * @uses SMTP
+ * @access protected
+ * @return bool
+ */
+ protected function SmtpSend($header, $body) {
+ require_once $this->PluginDir . 'class.smtp.php';
+ $bad_rcpt = array();
+
+ if(!$this->SmtpConnect()) {
+ throw new phpmailerException($this->Lang('smtp_connect_failed'), self::STOP_CRITICAL);
+ }
+ $smtp_from = ($this->Sender == '') ? $this->From : $this->Sender;
+ if(!$this->smtp->Mail($smtp_from)) {
+ throw new phpmailerException($this->Lang('from_failed') . $smtp_from, self::STOP_CRITICAL);
+ }
+
+ // Attempt to send attach all recipients
+ foreach($this->to as $to) {
+ if (!$this->smtp->Recipient($to[0])) {
+ $bad_rcpt[] = $to[0];
+ }
+ }
+ foreach($this->cc as $cc) {
+ if (!$this->smtp->Recipient($cc[0])) {
+ $bad_rcpt[] = $cc[0];
+ }
+ }
+ foreach($this->bcc as $bcc) {
+ if (!$this->smtp->Recipient($bcc[0])) {
+ $bad_rcpt[] = $bcc[0];
+ }
+ }
+ if (count($bad_rcpt) > 0 ) { //Create error message for any bad addresses
+ $badaddresses = implode(', ', $bad_rcpt);
+ throw new phpmailerException($this->Lang('recipients_failed') . $badaddresses);
+ }
+ if(!$this->smtp->Data($header . $body)) {
+ throw new phpmailerException($this->Lang('data_not_accepted'), self::STOP_CRITICAL);
+ }
+ if($this->SMTPKeepAlive == true) {
+ $this->smtp->Reset();
+ }
+ return true;
+ }
+
+ /**
+ * Initiates a connection to an SMTP server.
+ * Returns false if the operation failed.
+ * @uses SMTP
+ * @access public
+ * @return bool
+ */
+ public function SmtpConnect() {
+ if(is_null($this->smtp)) {
+ $this->smtp = new SMTP();
+ }
+
+ $this->smtp->do_debug = $this->SMTPDebug;
+ $hosts = explode(';', $this->Host);
+ $index = 0;
+ $connection = $this->smtp->Connected();
+
+ // Retry while there is no connection
+ try {
+ while($index < count($hosts) && !$connection) {
+ $hostinfo = array();
+ if (preg_match('/^(.+):([0-9]+)$/', $hosts[$index], $hostinfo)) {
+ $host = $hostinfo[1];
+ $port = $hostinfo[2];
+ } else {
+ $host = $hosts[$index];
+ $port = $this->Port;
+ }
+
+ $tls = ($this->SMTPSecure == 'tls');
+ $ssl = ($this->SMTPSecure == 'ssl');
+
+ if ($this->smtp->Connect(($ssl ? 'ssl://':'').$host, $port, $this->Timeout)) {
+
+ $hello = ($this->Helo != '' ? $this->Helo : $this->ServerHostname());
+ $this->smtp->Hello($hello);
+
+ if ($tls) {
+ if (!$this->smtp->StartTLS()) {
+ throw new phpmailerException($this->Lang('tls'));
+ }
+
+ //We must resend HELO after tls negotiation
+ $this->smtp->Hello($hello);
+ }
+
+ $connection = true;
+ if ($this->SMTPAuth) {
+ if (!$this->smtp->Authenticate($this->Username, $this->Password)) {
+ throw new phpmailerException($this->Lang('authenticate'));
+ }
+ }
+ }
+ $index++;
+ if (!$connection) {
+ throw new phpmailerException($this->Lang('connect_host'));
+ }
+ }
+ } catch (phpmailerException $e) {
+ $this->smtp->Reset();
+ throw $e;
+ }
+ return true;
+ }
+
+ /**
+ * Closes the active SMTP session if one exists.
+ * @return void
+ */
+ public function SmtpClose() {
+ if(!is_null($this->smtp)) {
+ if($this->smtp->Connected()) {
+ $this->smtp->Quit();
+ $this->smtp->Close();
+ }
+ }
+ }
+
+ /**
+ * Sets the language for all class error messages.
+ * Returns false if it cannot load the language file. The default language is English.
+ * @param string $langcode ISO 639-1 2-character language code (e.g. Portuguese: "br")
+ * @param string $lang_path Path to the language file directory
+ * @access public
+ */
+ function SetLanguage($langcode = 'en', $lang_path = 'language/') {
+ //Define full set of translatable strings
+ $PHPMAILER_LANG = array(
+ 'provide_address' => 'You must provide at least one recipient email address.',
+ 'mailer_not_supported' => ' mailer is not supported.',
+ 'execute' => 'Could not execute: ',
+ 'instantiate' => 'Could not instantiate mail function.',
+ 'authenticate' => 'SMTP Error: Could not authenticate.',
+ 'from_failed' => 'The following From address failed: ',
+ 'recipients_failed' => 'SMTP Error: The following recipients failed: ',
+ 'data_not_accepted' => 'SMTP Error: Data not accepted.',
+ 'connect_host' => 'SMTP Error: Could not connect to SMTP host.',
+ 'file_access' => 'Could not access file: ',
+ 'file_open' => 'File Error: Could not open file: ',
+ 'encoding' => 'Unknown encoding: ',
+ 'signing' => 'Signing Error: ',
+ 'smtp_error' => 'SMTP server error: ',
+ 'empty_message' => 'Message body empty',
+ 'invalid_address' => 'Invalid address',
+ 'variable_set' => 'Cannot set or reset variable: '
+ );
+ //Overwrite language-specific strings. This way we'll never have missing translations - no more "language string failed to load"!
+ $l = true;
+ if ($langcode != 'en') { //There is no English translation file
+ $l = @include $lang_path.'phpmailer.lang-'.$langcode.'.php';
+ }
+ $this->language = $PHPMAILER_LANG;
+ return ($l == true); //Returns false if language not found
+ }
+
+ /**
+ * Return the current array of language strings
+ * @return array
+ */
+ public function GetTranslations() {
+ return $this->language;
+ }
+
+ /////////////////////////////////////////////////
+ // METHODS, MESSAGE CREATION
+ /////////////////////////////////////////////////
+
+ /**
+ * Creates recipient headers.
+ * @access public
+ * @return string
+ */
+ public function AddrAppend($type, $addr) {
+ $addr_str = $type . ': ';
+ $addresses = array();
+ foreach ($addr as $a) {
+ $addresses[] = $this->AddrFormat($a);
+ }
+ $addr_str .= implode(', ', $addresses);
+ $addr_str .= $this->LE;
+
+ return $addr_str;
+ }
+
+ /**
+ * Formats an address correctly.
+ * @access public
+ * @return string
+ */
+ public function AddrFormat($addr) {
+ if (empty($addr[1])) {
+ return $this->SecureHeader($addr[0]);
+ } else {
+ return $this->EncodeHeader($this->SecureHeader($addr[1]), 'phrase') . " <" . $this->SecureHeader($addr[0]) . ">";
+ }
+ }
+
+ /**
+ * Wraps message for use with mailers that do not
+ * automatically perform wrapping and for quoted-printable.
+ * Original written by philippe.
+ * @param string $message The message to wrap
+ * @param integer $length The line length to wrap to
+ * @param boolean $qp_mode Whether to run in Quoted-Printable mode
+ * @access public
+ * @return string
+ */
+ public function WrapText($message, $length, $qp_mode = false) {
+ $soft_break = ($qp_mode) ? sprintf(" =%s", $this->LE) : $this->LE;
+ // If utf-8 encoding is used, we will need to make sure we don't
+ // split multibyte characters when we wrap
+ $is_utf8 = (strtolower($this->CharSet) == "utf-8");
+
+ $message = $this->FixEOL($message);
+ if (substr($message, -1) == $this->LE) {
+ $message = substr($message, 0, -1);
+ }
+
+ $line = explode($this->LE, $message);
+ $message = '';
+ for ($i=0 ;$i < count($line); $i++) {
+ $line_part = explode(' ', $line[$i]);
+ $buf = '';
+ for ($e = 0; $e $length)) {
+ $space_left = $length - strlen($buf) - 1;
+ if ($e != 0) {
+ if ($space_left > 20) {
+ $len = $space_left;
+ if ($is_utf8) {
+ $len = $this->UTF8CharBoundary($word, $len);
+ } elseif (substr($word, $len - 1, 1) == "=") {
+ $len--;
+ } elseif (substr($word, $len - 2, 1) == "=") {
+ $len -= 2;
+ }
+ $part = substr($word, 0, $len);
+ $word = substr($word, $len);
+ $buf .= ' ' . $part;
+ $message .= $buf . sprintf("=%s", $this->LE);
+ } else {
+ $message .= $buf . $soft_break;
+ }
+ $buf = '';
+ }
+ while (strlen($word) > 0) {
+ $len = $length;
+ if ($is_utf8) {
+ $len = $this->UTF8CharBoundary($word, $len);
+ } elseif (substr($word, $len - 1, 1) == "=") {
+ $len--;
+ } elseif (substr($word, $len - 2, 1) == "=") {
+ $len -= 2;
+ }
+ $part = substr($word, 0, $len);
+ $word = substr($word, $len);
+
+ if (strlen($word) > 0) {
+ $message .= $part . sprintf("=%s", $this->LE);
+ } else {
+ $buf = $part;
+ }
+ }
+ } else {
+ $buf_o = $buf;
+ $buf .= ($e == 0) ? $word : (' ' . $word);
+
+ if (strlen($buf) > $length and $buf_o != '') {
+ $message .= $buf_o . $soft_break;
+ $buf = $word;
+ }
+ }
+ }
+ $message .= $buf . $this->LE;
+ }
+
+ return $message;
+ }
+
+ /**
+ * Finds last character boundary prior to maxLength in a utf-8
+ * quoted (printable) encoded string.
+ * Original written by Colin Brown.
+ * @access public
+ * @param string $encodedText utf-8 QP text
+ * @param int $maxLength find last character boundary prior to this length
+ * @return int
+ */
+ public function UTF8CharBoundary($encodedText, $maxLength) {
+ $foundSplitPos = false;
+ $lookBack = 3;
+ while (!$foundSplitPos) {
+ $lastChunk = substr($encodedText, $maxLength - $lookBack, $lookBack);
+ $encodedCharPos = strpos($lastChunk, "=");
+ if ($encodedCharPos !== false) {
+ // Found start of encoded character byte within $lookBack block.
+ // Check the encoded byte value (the 2 chars after the '=')
+ $hex = substr($encodedText, $maxLength - $lookBack + $encodedCharPos + 1, 2);
+ $dec = hexdec($hex);
+ if ($dec < 128) { // Single byte character.
+ // If the encoded char was found at pos 0, it will fit
+ // otherwise reduce maxLength to start of the encoded char
+ $maxLength = ($encodedCharPos == 0) ? $maxLength :
+ $maxLength - ($lookBack - $encodedCharPos);
+ $foundSplitPos = true;
+ } elseif ($dec >= 192) { // First byte of a multi byte character
+ // Reduce maxLength to split at start of character
+ $maxLength = $maxLength - ($lookBack - $encodedCharPos);
+ $foundSplitPos = true;
+ } elseif ($dec < 192) { // Middle byte of a multi byte character, look further back
+ $lookBack += 3;
+ }
+ } else {
+ // No encoded character found
+ $foundSplitPos = true;
+ }
+ }
+ return $maxLength;
+ }
+
+
+ /**
+ * Set the body wrapping.
+ * @access public
+ * @return void
+ */
+ public function SetWordWrap() {
+ if($this->WordWrap < 1) {
+ return;
+ }
+
+ switch($this->message_type) {
+ case 'alt':
+ case 'alt_attachments':
+ $this->AltBody = $this->WrapText($this->AltBody, $this->WordWrap);
+ break;
+ default:
+ $this->Body = $this->WrapText($this->Body, $this->WordWrap);
+ break;
+ }
+ }
+
+ /**
+ * Assembles message header.
+ * @access public
+ * @return string The assembled header
+ */
+ public function CreateHeader() {
+ $result = '';
+
+ // Set the boundaries
+ $uniq_id = md5(uniqid(time()));
+ $this->boundary[1] = 'b1_' . $uniq_id;
+ $this->boundary[2] = 'b2_' . $uniq_id;
+
+ $result .= $this->HeaderLine('Date', self::RFCDate());
+ if($this->Sender == '') {
+ $result .= $this->HeaderLine('Return-Path', trim($this->From));
+ } else {
+ $result .= $this->HeaderLine('Return-Path', trim($this->Sender));
+ }
+
+ // To be created automatically by mail()
+ if($this->Mailer != 'mail') {
+ if(count($this->to) > 0) {
+ $result .= $this->AddrAppend('To', $this->to);
+ } elseif (count($this->cc) == 0) {
+ $result .= $this->HeaderLine('To', 'undisclosed-recipients:;');
+ }
+ }
+
+ $from = array();
+ $from[0][0] = trim($this->From);
+ $from[0][1] = $this->FromName;
+ $result .= $this->AddrAppend('From', $from);
+
+ // sendmail and mail() extract Cc from the header before sending
+ if((($this->Mailer == 'sendmail') || ($this->Mailer == 'mail')) && (count($this->cc) > 0)) {
+ $result .= $this->AddrAppend('Cc', $this->cc);
+ }
+
+ // sendmail and mail() extract Bcc from the header before sending
+ if((($this->Mailer == 'sendmail') || ($this->Mailer == 'mail')) && (count($this->bcc) > 0)) {
+ $result .= $this->AddrAppend('Bcc', $this->bcc);
+ }
+
+ if(count($this->ReplyTo) > 0) {
+ $result .= $this->AddrAppend('Reply-to', $this->ReplyTo);
+ }
+
+ // mail() sets the subject itself
+ if($this->Mailer != 'mail') {
+ $result .= $this->HeaderLine('Subject', $this->EncodeHeader($this->SecureHeader($this->Subject)));
+ }
+
+ if($this->MessageID != '') {
+ $result .= $this->HeaderLine('Message-ID',$this->MessageID);
+ } else {
+ $result .= sprintf("Message-ID: <%s@%s>%s", $uniq_id, $this->ServerHostname(), $this->LE);
+ }
+ $result .= $this->HeaderLine('X-Priority', $this->Priority);
+ $result .= $this->HeaderLine('X-Mailer', 'PHPMailer ' . self::VERSION . ' (phpmailer.codeworxtech.com)');
+
+ if($this->ConfirmReadingTo != '') {
+ $result .= $this->HeaderLine('Disposition-Notification-To', '<' . trim($this->ConfirmReadingTo) . '>');
+ }
+
+ // Add custom headers
+ for($index = 0; $index < count($this->CustomHeader); $index++) {
+ $result .= $this->HeaderLine(trim($this->CustomHeader[$index][0]), $this->EncodeHeader(trim($this->CustomHeader[$index][1])));
+ }
+ if (!$this->sign_key_file) {
+ $result .= $this->HeaderLine('MIME-Version', '1.0');
+ $result .= $this->GetMailMIME();
+ }
+
+ return $result;
+ }
+
+ /**
+ * Returns the message MIME.
+ * @access public
+ * @return string
+ */
+ public function GetMailMIME() {
+ $result = '';
+ switch($this->message_type) {
+ case 'plain':
+ $result .= $this->HeaderLine('Content-Transfer-Encoding', $this->Encoding);
+ $result .= sprintf("Content-Type: %s; charset=\"%s\"", $this->ContentType, $this->CharSet);
+ break;
+ case 'attachments':
+ case 'alt_attachments':
+ if($this->InlineImageExists()){
+ $result .= sprintf("Content-Type: %s;%s\ttype=\"text/html\";%s\tboundary=\"%s\"%s", 'multipart/related', $this->LE, $this->LE, $this->boundary[1], $this->LE);
+ } else {
+ $result .= $this->HeaderLine('Content-Type', 'multipart/mixed;');
+ $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"');
+ }
+ break;
+ case 'alt':
+ $result .= $this->HeaderLine('Content-Type', 'multipart/alternative;');
+ $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"');
+ break;
+ }
+
+ if($this->Mailer != 'mail') {
+ $result .= $this->LE.$this->LE;
+ }
+
+ return $result;
+ }
+
+ /**
+ * Assembles the message body. Returns an empty string on failure.
+ * @access public
+ * @return string The assembled message body
+ */
+ public function CreateBody() {
+ $body = '';
+
+ if ($this->sign_key_file) {
+ $body .= $this->GetMailMIME();
+ }
+
+ $this->SetWordWrap();
+
+ switch($this->message_type) {
+ case 'alt':
+ $body .= $this->GetBoundary($this->boundary[1], '', 'text/plain', '');
+ $body .= $this->EncodeString($this->AltBody, $this->Encoding);
+ $body .= $this->LE.$this->LE;
+ $body .= $this->GetBoundary($this->boundary[1], '', 'text/html', '');
+ $body .= $this->EncodeString($this->Body, $this->Encoding);
+ $body .= $this->LE.$this->LE;
+ $body .= $this->EndBoundary($this->boundary[1]);
+ break;
+ case 'plain':
+ $body .= $this->EncodeString($this->Body, $this->Encoding);
+ break;
+ case 'attachments':
+ $body .= $this->GetBoundary($this->boundary[1], '', '', '');
+ $body .= $this->EncodeString($this->Body, $this->Encoding);
+ $body .= $this->LE;
+ $body .= $this->AttachAll();
+ break;
+ case 'alt_attachments':
+ $body .= sprintf("--%s%s", $this->boundary[1], $this->LE);
+ $body .= sprintf("Content-Type: %s;%s" . "\tboundary=\"%s\"%s", 'multipart/alternative', $this->LE, $this->boundary[2], $this->LE.$this->LE);
+ $body .= $this->GetBoundary($this->boundary[2], '', 'text/plain', '') . $this->LE; // Create text body
+ $body .= $this->EncodeString($this->AltBody, $this->Encoding);
+ $body .= $this->LE.$this->LE;
+ $body .= $this->GetBoundary($this->boundary[2], '', 'text/html', '') . $this->LE; // Create the HTML body
+ $body .= $this->EncodeString($this->Body, $this->Encoding);
+ $body .= $this->LE.$this->LE;
+ $body .= $this->EndBoundary($this->boundary[2]);
+ $body .= $this->AttachAll();
+ break;
+ }
+
+ if ($this->IsError()) {
+ $body = '';
+ } elseif ($this->sign_key_file) {
+ try {
+ $file = tempnam('', 'mail');
+ file_put_contents($file, $body); //TODO check this worked
+ $signed = tempnam("", "signed");
+ if (@openssl_pkcs7_sign($file, $signed, "file://".$this->sign_cert_file, array("file://".$this->sign_key_file, $this->sign_key_pass), NULL)) {
+ @unlink($file);
+ @unlink($signed);
+ $body = file_get_contents($signed);
+ } else {
+ @unlink($file);
+ @unlink($signed);
+ throw new phpmailerException($this->Lang("signing").openssl_error_string());
+ }
+ } catch (phpmailerException $e) {
+ $body = '';
+ if ($this->exceptions) {
+ throw $e;
+ }
+ }
+ }
+
+ return $body;
+ }
+
+ /**
+ * Returns the start of a message boundary.
+ * @access private
+ */
+ private function GetBoundary($boundary, $charSet, $contentType, $encoding) {
+ $result = '';
+ if($charSet == '') {
+ $charSet = $this->CharSet;
+ }
+ if($contentType == '') {
+ $contentType = $this->ContentType;
+ }
+ if($encoding == '') {
+ $encoding = $this->Encoding;
+ }
+ $result .= $this->TextLine('--' . $boundary);
+ $result .= sprintf("Content-Type: %s; charset = \"%s\"", $contentType, $charSet);
+ $result .= $this->LE;
+ $result .= $this->HeaderLine('Content-Transfer-Encoding', $encoding);
+ $result .= $this->LE;
+
+ return $result;
+ }
+
+ /**
+ * Returns the end of a message boundary.
+ * @access private
+ */
+ private function EndBoundary($boundary) {
+ return $this->LE . '--' . $boundary . '--' . $this->LE;
+ }
+
+ /**
+ * Sets the message type.
+ * @access private
+ * @return void
+ */
+ private function SetMessageType() {
+ if(count($this->attachment) < 1 && strlen($this->AltBody) < 1) {
+ $this->message_type = 'plain';
+ } else {
+ if(count($this->attachment) > 0) {
+ $this->message_type = 'attachments';
+ }
+ if(strlen($this->AltBody) > 0 && count($this->attachment) < 1) {
+ $this->message_type = 'alt';
+ }
+ if(strlen($this->AltBody) > 0 && count($this->attachment) > 0) {
+ $this->message_type = 'alt_attachments';
+ }
+ }
+ }
+
+ /**
+ * Returns a formatted header line.
+ * @access public
+ * @return string
+ */
+ public function HeaderLine($name, $value) {
+ return $name . ': ' . $value . $this->LE;
+ }
+
+ /**
+ * Returns a formatted mail line.
+ * @access public
+ * @return string
+ */
+ public function TextLine($value) {
+ return $value . $this->LE;
+ }
+
+ /////////////////////////////////////////////////
+ // CLASS METHODS, ATTACHMENTS
+ /////////////////////////////////////////////////
+
+ /**
+ * Adds an attachment from a path on the filesystem.
+ * Returns false if the file could not be found
+ * or accessed.
+ * @param string $path Path to the attachment.
+ * @param string $name Overrides the attachment name.
+ * @param string $encoding File encoding (see $Encoding).
+ * @param string $type File extension (MIME) type.
+ * @return bool
+ */
+ public function AddAttachment($path, $name = '', $encoding = 'base64', $type = 'application/octet-stream') {
+ try {
+ if ( !@is_file($path) ) {
+ throw new phpmailerException($this->Lang('file_access') . $path, self::STOP_CONTINUE);
+ }
+ $filename = basename($path);
+ if ( $name == '' ) {
+ $name = $filename;
+ }
+
+ $this->attachment[] = array(
+ 0 => $path,
+ 1 => $filename,
+ 2 => $name,
+ 3 => $encoding,
+ 4 => $type,
+ 5 => false, // isStringAttachment
+ 6 => 'attachment',
+ 7 => 0
+ );
+
+ } catch (phpmailerException $e) {
+ $this->SetError($e->getMessage());
+ if ($this->exceptions) {
+ throw $e;
+ }
+ echo $e->getMessage()."\n";
+ if ( $e->getCode() == self::STOP_CRITICAL ) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Return the current array of attachments
+ * @return array
+ */
+ public function GetAttachments() {
+ return $this->attachment;
+ }
+
+ /**
+ * Attaches all fs, string, and binary attachments to the message.
+ * Returns an empty string on failure.
+ * @access private
+ * @return string
+ */
+ private function AttachAll() {
+ // Return text of body
+ $mime = array();
+ $cidUniq = array();
+ $incl = array();
+
+ // Add all attachments
+ foreach ($this->attachment as $attachment) {
+ // Check for string attachment
+ $bString = $attachment[5];
+ if ($bString) {
+ $string = $attachment[0];
+ } else {
+ $path = $attachment[0];
+ }
+
+ if (in_array($attachment[0], $incl)) { continue; }
+ $filename = $attachment[1];
+ $name = $attachment[2];
+ $encoding = $attachment[3];
+ $type = $attachment[4];
+ $disposition = $attachment[6];
+ $cid = $attachment[7];
+ $incl[] = $attachment[0];
+ if ( isset($cidUniq[$cid]) ) { continue; }
+ $cidUniq[$cid] = true;
+
+ $mime[] = sprintf("--%s%s", $this->boundary[1], $this->LE);
+ $mime[] = sprintf("Content-Type: %s; name=\"%s\"%s", $type, $this->EncodeHeader($this->SecureHeader($name)), $this->LE);
+ $mime[] = sprintf("Content-Transfer-Encoding: %s%s", $encoding, $this->LE);
+
+ if($disposition == 'inline') {
+ $mime[] = sprintf("Content-ID: <%s>%s", $cid, $this->LE);
+ }
+
+ $mime[] = sprintf("Content-Disposition: %s; filename=\"%s\"%s", $disposition, $this->EncodeHeader($this->SecureHeader($name)), $this->LE.$this->LE);
+
+ // Encode as string attachment
+ if($bString) {
+ $mime[] = $this->EncodeString($string, $encoding);
+ if($this->IsError()) {
+ return '';
+ }
+ $mime[] = $this->LE.$this->LE;
+ } else {
+ $mime[] = $this->EncodeFile($path, $encoding);
+ if($this->IsError()) {
+ return '';
+ }
+ $mime[] = $this->LE.$this->LE;
+ }
+ }
+
+ $mime[] = sprintf("--%s--%s", $this->boundary[1], $this->LE);
+
+ return join('', $mime);
+ }
+
+ /**
+ * Encodes attachment in requested format.
+ * Returns an empty string on failure.
+ * @param string $path The full path to the file
+ * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable'
+ * @see EncodeFile()
+ * @access private
+ * @return string
+ */
+ private function EncodeFile($path, $encoding = 'base64') {
+ try {
+ if (!is_readable($path)) {
+ throw new phpmailerException($this->Lang('file_open') . $path, self::STOP_CONTINUE);
+ }
+ if (function_exists('get_magic_quotes')) {
+ function get_magic_quotes() {
+ return false;
+ }
+ }
+ if (PHP_VERSION < 6) {
+ $magic_quotes = get_magic_quotes_runtime();
+ set_magic_quotes_runtime(0);
+ }
+ $file_buffer = file_get_contents($path);
+ $file_buffer = $this->EncodeString($file_buffer, $encoding);
+ if (PHP_VERSION < 6) { set_magic_quotes_runtime($magic_quotes); }
+ return $file_buffer;
+ } catch (Exception $e) {
+ $this->SetError($e->getMessage());
+ return '';
+ }
+ }
+
+ /**
+ * Encodes string to requested format.
+ * Returns an empty string on failure.
+ * @param string $str The text to encode
+ * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable'
+ * @access public
+ * @return string
+ */
+ public function EncodeString ($str, $encoding = 'base64') {
+ $encoded = '';
+ switch(strtolower($encoding)) {
+ case 'base64':
+ $encoded = chunk_split(base64_encode($str), 76, $this->LE);
+ break;
+ case '7bit':
+ case '8bit':
+ $encoded = $this->FixEOL($str);
+ //Make sure it ends with a line break
+ if (substr($encoded, -(strlen($this->LE))) != $this->LE)
+ $encoded .= $this->LE;
+ break;
+ case 'binary':
+ $encoded = $str;
+ break;
+ case 'quoted-printable':
+ $encoded = $this->EncodeQP($str);
+ break;
+ default:
+ $this->SetError($this->Lang('encoding') . $encoding);
+ break;
+ }
+ return $encoded;
+ }
+
+ /**
+ * Encode a header string to best (shortest) of Q, B, quoted or none.
+ * @access public
+ * @return string
+ */
+ public function EncodeHeader($str, $position = 'text') {
+ $x = 0;
+
+ switch (strtolower($position)) {
+ case 'phrase':
+ if (!preg_match('/[\200-\377]/', $str)) {
+ // Can't use addslashes as we don't know what value has magic_quotes_sybase
+ $encoded = addcslashes($str, "\0..\37\177\\\"");
+ if (($str == $encoded) && !preg_match('/[^A-Za-z0-9!#$%&\'*+\/=?^_`{|}~ -]/', $str)) {
+ return ($encoded);
+ } else {
+ return ("\"$encoded\"");
+ }
+ }
+ $x = preg_match_all('/[^\040\041\043-\133\135-\176]/', $str, $matches);
+ break;
+ case 'comment':
+ $x = preg_match_all('/[()"]/', $str, $matches);
+ // Fall-through
+ case 'text':
+ default:
+ $x += preg_match_all('/[\000-\010\013\014\016-\037\177-\377]/', $str, $matches);
+ break;
+ }
+
+ if ($x == 0) {
+ return ($str);
+ }
+
+ $maxlen = 75 - 7 - strlen($this->CharSet);
+ // Try to select the encoding which should produce the shortest output
+ if (strlen($str)/3 < $x) {
+ $encoding = 'B';
+ if (function_exists('mb_strlen') && $this->HasMultiBytes($str)) {
+ // Use a custom function which correctly encodes and wraps long
+ // multibyte strings without breaking lines within a character
+ $encoded = $this->Base64EncodeWrapMB($str);
+ } else {
+ $encoded = base64_encode($str);
+ $maxlen -= $maxlen % 4;
+ $encoded = trim(chunk_split($encoded, $maxlen, "\n"));
+ }
+ } else {
+ $encoding = 'Q';
+ $encoded = $this->EncodeQ($str, $position);
+ $encoded = $this->WrapText($encoded, $maxlen, true);
+ $encoded = str_replace('='.$this->LE, "\n", trim($encoded));
+ }
+
+ $encoded = preg_replace('/^(.*)$/m', " =?".$this->CharSet."?$encoding?\\1?=", $encoded);
+ $encoded = trim(str_replace("\n", $this->LE, $encoded));
+
+ return $encoded;
+ }
+
+ /**
+ * Checks if a string contains multibyte characters.
+ * @access public
+ * @param string $str multi-byte text to wrap encode
+ * @return bool
+ */
+ public function HasMultiBytes($str) {
+ if (function_exists('mb_strlen')) {
+ return (strlen($str) > mb_strlen($str, $this->CharSet));
+ } else { // Assume no multibytes (we can't handle without mbstring functions anyway)
+ return false;
+ }
+ }
+
+ /**
+ * Correctly encodes and wraps long multibyte strings for mail headers
+ * without breaking lines within a character.
+ * Adapted from a function by paravoid at http://uk.php.net/manual/en/function.mb-encode-mimeheader.php
+ * @access public
+ * @param string $str multi-byte text to wrap encode
+ * @return string
+ */
+ public function Base64EncodeWrapMB($str) {
+ $start = "=?".$this->CharSet."?B?";
+ $end = "?=";
+ $encoded = "";
+
+ $mb_length = mb_strlen($str, $this->CharSet);
+ // Each line must have length <= 75, including $start and $end
+ $length = 75 - strlen($start) - strlen($end);
+ // Average multi-byte ratio
+ $ratio = $mb_length / strlen($str);
+ // Base64 has a 4:3 ratio
+ $offset = $avgLength = floor($length * $ratio * .75);
+
+ for ($i = 0; $i < $mb_length; $i += $offset) {
+ $lookBack = 0;
+
+ do {
+ $offset = $avgLength - $lookBack;
+ $chunk = mb_substr($str, $i, $offset, $this->CharSet);
+ $chunk = base64_encode($chunk);
+ $lookBack++;
+ }
+ while (strlen($chunk) > $length);
+
+ $encoded .= $chunk . $this->LE;
+ }
+
+ // Chomp the last linefeed
+ $encoded = substr($encoded, 0, -strlen($this->LE));
+ return $encoded;
+ }
+
+ /**
+ * Encode string to quoted-printable.
+ * Only uses standard PHP, slow, but will always work
+ * @access public
+ * @param string $string the text to encode
+ * @param integer $line_max Number of chars allowed on a line before wrapping
+ * @return string
+ */
+ public function EncodeQPphp( $input = '', $line_max = 76, $space_conv = false) {
+ $hex = array('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F');
+ $lines = preg_split('/(?:\r\n|\r|\n)/', $input);
+ $eol = "\r\n";
+ $escape = '=';
+ $output = '';
+ while( list(, $line) = each($lines) ) {
+ $linlen = strlen($line);
+ $newline = '';
+ for($i = 0; $i < $linlen; $i++) {
+ $c = substr( $line, $i, 1 );
+ $dec = ord( $c );
+ if ( ( $i == 0 ) && ( $dec == 46 ) ) { // convert first point in the line into =2E
+ $c = '=2E';
+ }
+ if ( $dec == 32 ) {
+ if ( $i == ( $linlen - 1 ) ) { // convert space at eol only
+ $c = '=20';
+ } else if ( $space_conv ) {
+ $c = '=20';
+ }
+ } elseif ( ($dec == 61) || ($dec < 32 ) || ($dec > 126) ) { // always encode "\t", which is *not* required
+ $h2 = floor($dec/16);
+ $h1 = floor($dec%16);
+ $c = $escape.$hex[$h2].$hex[$h1];
+ }
+ if ( (strlen($newline) + strlen($c)) >= $line_max ) { // CRLF is not counted
+ $output .= $newline.$escape.$eol; // soft line break; " =\r\n" is okay
+ $newline = '';
+ // check if newline first character will be point or not
+ if ( $dec == 46 ) {
+ $c = '=2E';
+ }
+ }
+ $newline .= $c;
+ } // end of for
+ $output .= $newline.$eol;
+ } // end of while
+ return $output;
+ }
+
+ /**
+ * Encode string to RFC2045 (6.7) quoted-printable format
+ * Uses a PHP5 stream filter to do the encoding about 64x faster than the old version
+ * Also results in same content as you started with after decoding
+ * @see EncodeQPphp()
+ * @access public
+ * @param string $string the text to encode
+ * @param integer $line_max Number of chars allowed on a line before wrapping
+ * @param boolean $space_conv Dummy param for compatibility with existing EncodeQP function
+ * @return string
+ * @author Marcus Bointon
+ */
+ public function EncodeQP($string, $line_max = 76, $space_conv = false) {
+ if (function_exists('quoted_printable_encode')) { //Use native function if it's available (>= PHP5.3)
+ return quoted_printable_encode($string);
+ }
+ $filters = stream_get_filters();
+ if (!in_array('convert.*', $filters)) { //Got convert stream filter?
+ return $this->EncodeQPphp($string, $line_max, $space_conv); //Fall back to old implementation
+ }
+ $fp = fopen('php://temp/', 'r+');
+ $string = preg_replace('/\r\n?/', $this->LE, $string); //Normalise line breaks
+ $params = array('line-length' => $line_max, 'line-break-chars' => $this->LE);
+ $s = stream_filter_append($fp, 'convert.quoted-printable-encode', STREAM_FILTER_READ, $params);
+ fputs($fp, $string);
+ rewind($fp);
+ $out = stream_get_contents($fp);
+ stream_filter_remove($s);
+ $out = preg_replace('/^\./m', '=2E', $out); //Encode . if it is first char on a line, workaround for bug in Exchange
+ fclose($fp);
+ return $out;
+ }
+
+ /**
+ * Encode string to q encoding.
+ * @link http://tools.ietf.org/html/rfc2047
+ * @param string $str the text to encode
+ * @param string $position Where the text is going to be used, see the RFC for what that means
+ * @access public
+ * @return string
+ */
+ public function EncodeQ ($str, $position = 'text') {
+ // There should not be any EOL in the string
+ $encoded = preg_replace('/[\r\n]*/', '', $str);
+
+ switch (strtolower($position)) {
+ case 'phrase':
+ $encoded = preg_replace("/([^A-Za-z0-9!*+\/ -])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded);
+ break;
+ case 'comment':
+ $encoded = preg_replace("/([\(\)\"])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded);
+ case 'text':
+ default:
+ // Replace every high ascii, control =, ? and _ characters
+ //TODO using /e (equivalent to eval()) is probably not a good idea
+ $encoded = preg_replace('/([\000-\011\013\014\016-\037\075\077\137\177-\377])/e',
+ "'='.sprintf('%02X', ord('\\1'))", $encoded);
+ break;
+ }
+
+ // Replace every spaces to _ (more readable than =20)
+ $encoded = str_replace(' ', '_', $encoded);
+
+ return $encoded;
+ }
+
+ /**
+ * Adds a string or binary attachment (non-filesystem) to the list.
+ * This method can be used to attach ascii or binary data,
+ * such as a BLOB record from a database.
+ * @param string $string String attachment data.
+ * @param string $filename Name of the attachment.
+ * @param string $encoding File encoding (see $Encoding).
+ * @param string $type File extension (MIME) type.
+ * @return void
+ */
+ public function AddStringAttachment($string, $filename, $encoding = 'base64', $type = 'application/octet-stream') {
+ // Append to $attachment array
+ $this->attachment[] = array(
+ 0 => $string,
+ 1 => $filename,
+ 2 => $filename,
+ 3 => $encoding,
+ 4 => $type,
+ 5 => true, // isStringAttachment
+ 6 => 'attachment',
+ 7 => 0
+ );
+ }
+
+ /**
+ * Adds an embedded attachment. This can include images, sounds, and
+ * just about any other document. Make sure to set the $type to an
+ * image type. For JPEG images use "image/jpeg" and for GIF images
+ * use "image/gif".
+ * @param string $path Path to the attachment.
+ * @param string $cid Content ID of the attachment. Use this to identify
+ * the Id for accessing the image in an HTML form.
+ * @param string $name Overrides the attachment name.
+ * @param string $encoding File encoding (see $Encoding).
+ * @param string $type File extension (MIME) type.
+ * @return bool
+ */
+ public function AddEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = 'application/octet-stream') {
+
+ if ( !@is_file($path) ) {
+ $this->SetError($this->Lang('file_access') . $path);
+ return false;
+ }
+
+ $filename = basename($path);
+ if ( $name == '' ) {
+ $name = $filename;
+ }
+
+ // Append to $attachment array
+ $this->attachment[] = array(
+ 0 => $path,
+ 1 => $filename,
+ 2 => $name,
+ 3 => $encoding,
+ 4 => $type,
+ 5 => false, // isStringAttachment
+ 6 => 'inline',
+ 7 => $cid
+ );
+
+ return true;
+ }
+
+ /**
+ * Returns true if an inline attachment is present.
+ * @access public
+ * @return bool
+ */
+ public function InlineImageExists() {
+ foreach($this->attachment as $attachment) {
+ if ($attachment[6] == 'inline') {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /////////////////////////////////////////////////
+ // CLASS METHODS, MESSAGE RESET
+ /////////////////////////////////////////////////
+
+ /**
+ * Clears all recipients assigned in the TO array. Returns void.
+ * @return void
+ */
+ public function ClearAddresses() {
+ foreach($this->to as $to) {
+ unset($this->all_recipients[strtolower($to[0])]);
+ }
+ $this->to = array();
+ }
+
+ /**
+ * Clears all recipients assigned in the CC array. Returns void.
+ * @return void
+ */
+ public function ClearCCs() {
+ foreach($this->cc as $cc) {
+ unset($this->all_recipients[strtolower($cc[0])]);
+ }
+ $this->cc = array();
+ }
+
+ /**
+ * Clears all recipients assigned in the BCC array. Returns void.
+ * @return void
+ */
+ public function ClearBCCs() {
+ foreach($this->bcc as $bcc) {
+ unset($this->all_recipients[strtolower($bcc[0])]);
+ }
+ $this->bcc = array();
+ }
+
+ /**
+ * Clears all recipients assigned in the ReplyTo array. Returns void.
+ * @return void
+ */
+ public function ClearReplyTos() {
+ $this->ReplyTo = array();
+ }
+
+ /**
+ * Clears all recipients assigned in the TO, CC and BCC
+ * array. Returns void.
+ * @return void
+ */
+ public function ClearAllRecipients() {
+ $this->to = array();
+ $this->cc = array();
+ $this->bcc = array();
+ $this->all_recipients = array();
+ }
+
+ /**
+ * Clears all previously set filesystem, string, and binary
+ * attachments. Returns void.
+ * @return void
+ */
+ public function ClearAttachments() {
+ $this->attachment = array();
+ }
+
+ /**
+ * Clears all custom headers. Returns void.
+ * @return void
+ */
+ public function ClearCustomHeaders() {
+ $this->CustomHeader = array();
+ }
+
+ /////////////////////////////////////////////////
+ // CLASS METHODS, MISCELLANEOUS
+ /////////////////////////////////////////////////
+
+ /**
+ * Adds the error message to the error container.
+ * @access protected
+ * @return void
+ */
+ protected function SetError($msg) {
+ $this->error_count++;
+ if ($this->Mailer == 'smtp' and !is_null($this->smtp)) {
+ $lasterror = $this->smtp->getError();
+ if (!empty($lasterror) and array_key_exists('smtp_msg', $lasterror)) {
+ $msg .= '
";
+}
+
+function ng_tiny($groupid,$groupname="",$text=true)
+{
+global $NATS;
+// to do - get groupname if not sent but F--- it for now
+$al=$NATS->GroupAlertLevel($groupid);
+echo "
";
+ $out.=" ";
+ $out.=" ";
+ $out.="";
+ $out.=" String(s) to search for - all defined must be found for the test to pass ";
+ $out.="Blank strings are ignored.";
+ $out.="
";
+ $out.="
No Strings :
";
+ $out.="
";
+ $out.=" ";
+ $out.=" ";
+ $out.="";
+ $out.=" String(s) to NOT find - fails if any are present Leave blank to not use this portion of the test";
+ $out.="
";
+
+ $out.="
Username :
";
+ $out.="
";
+ $out.="";
+ $out.=" Specify to use HTTP-AUTH on the URL";
+ $out.="
";
+
+ $out.="
Password :
";
+ $out.="
";
+ $out.=""; // dont display it
+ $out.=""; // don't update testparam3 (if blank)
+ $out.=" Enter a new password to set or... ";
+ $out.=" "; // clears testparam3 if set
+ $out.="clear it";
+ $out.="
";
+ echo $out; // output the buffer
+ }
+}
+
+// Now we have defined the class we must register it with FreeNATS
+
+$params=array(); // blank parameters array as we have implemented DisplayForm above
+
+$NATS->Tests->Register(
+ "advpagecheck", // the internal simple test name (must not conflict with anything else)
+ "Advanced_Pagecheck_Test", // the class name (above)
+ $params, // parameters (blank for now)
+ "Web Content Test", // the display name of the test in the interface
+ 3, // the revision number of the test
+ "Advanced Page Checker"); // extended description for the test module used in overview
+
+?>
diff --git a/src/server/base/site/tests/dynamic_dns_test.php b/src/server/base/site/tests/dynamic_dns_test.php
new file mode 100755
index 0000000..865007a
--- /dev/null
+++ b/src/server/base/site/tests/dynamic_dns_test.php
@@ -0,0 +1,160 @@
+0) return 0; // FreeNATS passed (0) flag if > 0
+ return 2; // FreeNATS failed (2) flag ( <= 0 )
+ }
+
+ function ProtectOutput(&$test)
+ {
+ $test['testparam3']=""; // blank password for output
+ return true;
+ }
+
+ function DisplayForm(&$test)
+ {
+ $out="";
+ $out.="
";
+ $out.="
Hostname:
";
+ $out.="
";
+ $out.="";
+ $out.=" Dynamic DNS Hostname to Check (i.e. myhost.dyndns.org)";
+ $out.="
";
+ $out.="
IP:
";
+ $out.="
";
+ $out.=" Use xml.purplepixie.org IP Address Service ";
+ $out.=" URL: ";
+ $out.="This setting tells FreeNATS where to get your external IP from. You can either use ";
+ $out.="the PurplePixie XML App gateway or put in your own URL. The URL must return a plain IP.";
+ $out.="
";
+ $out.="
";
+ echo $out; // output the buffer
+ }
+}
+
+// Now we have defined the class we must register it with FreeNATS
+
+$params=array(); // blank parameters array as we have implemented DisplayForm above
+
+$NATS->Tests->Register(
+ "dynamicdns", // the internal simple test name (must not conflict with anything else)
+ "Dynamic_DNS_Test", // the class name (above)
+ $params, // parameters (blank for now)
+ "Dynamic DNS Test", // the display name of the test in the interface
+ 1, // the revision number of the test
+ "Check Dyanamic DNS Host Against External IP"); // extended description for the test module used in overview
+
+?>
diff --git a/src/server/base/site/tests/ext.pagecheck.php b/src/server/base/site/tests/ext.pagecheck.php
new file mode 100755
index 0000000..dd85d4b
--- /dev/null
+++ b/src/server/base/site/tests/ext.pagecheck.php
@@ -0,0 +1,223 @@
+Cfg->Get("test.http.timeout",-1);
+ if ($nto>0) $timeout=$nto; // use NATS timeout
+ }
+ }
+ if ($timeout>0) // use the set timeout
+ $oldtimeout=ini_set("default_socket_timeout",$timeout);
+
+ $timer->Start();
+
+ if (function_exists("curl_getinfo")) // use CURL if present
+ {
+ $ch=curl_init();
+ curl_setopt($ch,CURLOPT_URL,$url);
+ curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
+ curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,0);
+ curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,0);
+ curl_setopt($ch,CURLOPT_HEADER,1);
+ if ($timeout>0) curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,$timeout);
+ if ($timeout>0) curl_setopt($ch,CURLOPT_TIMEOUT,$timeout);
+ if (!$output=curl_exec($ch))
+ {
+ $ctr=-1; // failed
+ }
+ else $ctr=round(curl_getinfo($ch,CURLINFO_SIZE_DOWNLOAD)/1024,2);
+ curl_close($ch);
+
+ if ($ctr==0) $ctr="0.0001";
+
+ }
+ else
+ { // no CURL - use fopen()
+ $fp=@fopen($url,"r");
+ if ($fp<=0)
+ {
+ if ($timeout>0) ini_set("default_socket_timeout",$oldtimeout);
+ return -1;
+ }
+ $ctr=0;
+ while ($output.=@fgets($fp,1024)) $ctr+=sizeof($body);
+ @fclose($fp);
+ }
+
+ if ($ctr<0) return $ctr; // negative number (-1) failed to open
+
+ $elapsed=$timer->Stop();
+
+ if ($timeout>0) ini_set("default_socket_timeout",$oldtimeout);
+
+ // now to check the actual text
+ if (is_array($text))
+ {
+ foreach($text as $findthis)
+ {
+ if ($findthis!="")
+ if (strpos($output,$findthis)===false) return -2; // text to be found not found
+ }
+ }
+ if (is_array($notext))
+ {
+ foreach($notext as $donotfindthis)
+ {
+ if ($donotfindthis!="")
+ if (strpos($output,$donotfindthis)!==false) return -3; // text not to find found
+ }
+ }
+
+ return $elapsed;
+ }
+
+
+/* // The old version
+function extended_check_page_text($url,$text,$notext="",$user="",$pass="")
+{
+ $timer=new TFNTimer(); // initialise the timer
+ url_lookup($url); // pre-resolve the DNS into cache
+
+ if ($user!="") // use HTTP-AUTH
+ {
+ $pos=strpos($url,"://");
+ if ($pos===false) return -1; // not a valid URL
+ $protocol=substr($url,0,$pos+3); // protocol section
+ $uri=substr($url,$pos+3); // uri section
+ $url=$protocol.$user.":".$pass."@".$uri; // make http://user:pass@uri
+ }
+ $timer->Start(); // start the timer
+ $fp=fopen($url,"r"); // open the URL
+ if ($fp<=0) return false; // fail if can't open
+ // or we could start it here to not include opening times...
+ $body="";
+ while (!feof($fp))
+ $body.=fgets($fp,1024); // read into the body in 1k chunks
+ $elapsed=$timer->Stop(); // get the elapsed time at this point
+ fclose($fp); // finished with pointer
+ if (strpos($body,$text)===false) return -1; // not found
+ if ($notext!="") // the text we do NOT want to appear is $notext - check if set
+ {
+ if (strpos($body,$notext)!==false) return -2; // was found in the page
+ }
+ return $elapsed; // return a positive elapsed time on success
+}
+*/
+
+global $NATS;
+
+class Ext_Pagecheck_Test extends FreeNATS_Local_Test
+{
+
+ function DoTest($testname,$param,$hostname,$timeout,$params)
+ {
+ /* parameters: -- sadly very messy but to do otherwise would break plug+play
+ 0: url
+ 1: text
+ 4: notext
+ 2: user
+ 3: pass
+
+ 5: text
+ 6: text
+ 7: notext
+ 8: notext
+ 9: NULL
+ */
+ $text=array( $params[1], $params[5], $params[6] );
+ $notext=array( $params[4], $params[7], $params[8] );
+
+ $result=extended_check_page_text_2($params[0],$text,$notext,$params[2],$params[3],$timeout);
+ return $result;
+ }
+
+ function Evaluate($result)
+ {
+ if ($result>0) return 0; // FreeNATS passed (0) flag if > 0
+ return 2; // FreeNATS failed (2) flag ( <= 0 )
+ }
+
+ function ProtectOutput(&$test)
+ {
+ $test['testparam3']=""; // blank password for output
+ return true;
+ }
+
+ function DisplayForm(&$test) // nice user form (optional)
+ {
+ $out=""; // output buffer
+ $out.="
";
+ $out.=" ";
+ $out.=" ";
+ $out.="";
+ $out.=" String(s) to search for - all defined must be found for the test to pass ";
+ $out.="Blank strings are ignored.";
+ $out.="
";
+ $out.="
No Strings :
";
+ $out.="
";
+ $out.=" ";
+ $out.=" ";
+ $out.="";
+ $out.=" String(s) to NOT find - fails if any are present Leave blank to not use this portion of the test";
+ $out.="
";
+
+ $out.="
Username :
";
+ $out.="
";
+ $out.="";
+ $out.=" Specify to use HTTP-AUTH on the URL";
+ $out.="
";
+
+ // so far so much the same... but...
+ $out.="
Password :
";
+ $out.="
";
+ $out.=""; // dont display it
+ $out.=""; // don't update testparam3 (if blank)
+ $out.=" Enter a new password to set or... ";
+ $out.=" "; // clears testparam3 if set
+ $out.="clear it";
+ $out.="
";
+ echo $out; // output the buffer
+ }
+}
+
+// Now we have defined the class we must register it with FreeNATS
+
+$params=array(); // blank parameters array as we have implemented DisplayForm above
+
+$NATS->Tests->Register(
+ "extpagecheck", // the internal simple test name (must not conflict with anything else)
+ "Ext_Pagecheck_Test", // the class name (above)
+ $params, // parameters (blank for now)
+ "Page Content Checker", // the display name of the test in the interface
+ 1, // the revision number of the test
+ "Extended Page Checker"); // extended description for the test module used in overview
+
+?>
diff --git a/src/server/base/site/tests/page_load_sim.php b/src/server/base/site/tests/page_load_sim.php
new file mode 100755
index 0000000..68c6e61
--- /dev/null
+++ b/src/server/base/site/tests/page_load_sim.php
@@ -0,0 +1,156 @@
+Start();
+
+ if (!$is_ip_address) // only do the DNS lookup if the URL isn't an IP address already
+ {
+ $answer=$dns_query->Query($hostname,$type);
+ //echo "DNS";
+
+ if ( ($answer===false) || ($dns_query->error) ) // query error
+ {
+ $udp=false; // switch to TCP
+ $dns_query->udp=$udp;
+
+ // wait!
+ while ($timer->Stop() < $dns_delay) usleep(100);
+
+ $answer=$dns_query->Query($hostname,$type);
+ //echo "DNS2";
+ }
+
+ if ($answer->count<=0) return -1; // no records returned
+ if ($answer===false) return -1; // object is false
+ if ($dns_query->error) return -1; // DNS object error
+
+ $dns_time_taken=$timer->Stop();
+
+ // if we get this far the DNS has worked
+
+ $ip_address=url_lookup($url); // pre-cache DNS
+ }
+ else $dns_time_taken=0;
+
+ $ch=curl_init();
+ curl_setopt($ch,CURLOPT_URL,$url);
+ curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
+ curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,0);
+ curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,0);
+ curl_setopt($ch,CURLOPT_HEADER,1);
+ curl_setopt($ch,CURLOPT_FOLLOWLOCATION,1);
+ curl_setopt($ch,CURLOPT_MAXREDIRS,32);
+ if ($timeout>0) curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,$timeout);
+ if ($timeout>0) curl_setopt($ch,CURLOPT_TIMEOUT,$timeout);
+
+ // restart timer
+ $timer->Start();
+
+ if (!$output=curl_exec($ch))
+ {
+ $ctr=-1; // failed
+ }
+ else $ctr=round(curl_getinfo($ch,CURLINFO_SIZE_DOWNLOAD)/1024,2);
+
+ $fetch_time_taken=$timer->Stop();
+
+ curl_close($ch);
+
+ if ($ctr<=0) return -2; // URL request failed
+
+ return $dns_time_taken + $fetch_time_taken; // return elapsed time taken
+
+ }
+ function Evaluate($result)
+ {
+ if ($result<0) return 2; // failed
+ return 0; // passed
+ }
+ function DisplayForm(&$row)
+ {
+ echo "
";
+ echo "
";
+ echo "FQDN URL :";
+ echo "
";
+ echo "";
+ echo "
";
+ echo "
Include http[s]://
";
+ echo "
";
+ echo "Nameserver :";
+ echo "
";
+ echo "";
+ echo "
";
+ echo "
DNS Server to perform lookup on
";
+ echo "
";
+ echo "DNS Delay :";
+ echo "
";
+ echo "";
+ echo "
";
+ echo "
If UDP DNS fails wait until elapsed time is x seconds before doing TCP lookup
";
+ echo "
";
+ }
+
+
+ }
+
+$params=array();
+$NATS->Tests->Register("loadsim","Page_Load_Sim_Test",$params,"Page Load Simulator",4,"Page Load Simulator");
+$NATS->Tests->SetUnits("loadsim","Seconds","s");
+}
+
+?>
diff --git a/src/server/base/site/tests/page_load_sim.zip b/src/server/base/site/tests/page_load_sim.zip
new file mode 100644
index 0000000000000000000000000000000000000000..53a42025ff979487e9419601df55729f15b1e025
GIT binary patch
literal 1747
zcmV;^1}yndO9KQH000080Blb|J1_&PIxPkO06h-?01*Hc0B~VvWnXM>VPs!(X>BfW
zXmC|j2>=6YZ^TM#Z^TMfcmx3S0rUZ_S8Z?FND%%E68~XpMOWNHc}eedN-${@Kt)PP
z3gk|AZHhMb0(&*KZ+9J%Yx>`BX4eMOv}t=+$pU+4=k1x%FO1aSh$^TA;
z;M&d_DvgO3s2?xZ)rpKTHE2RLaD4&Lmr@1A1-30SsREMsP7crSBGg
z_eK+#aCyxot+cb1i{3f(c*t&1#1nYM^)e0)%B9mdexD{*#xhnqVk-{Uf|>nsWLT9I
zRvOODYG_&JOoR#&mMRW9#z(Ud0@46C$l}LQKz{KEw7iAs$$7bSE_ofjjl*lcRfZan
z!sR@cD{=$k1bJ8#z?^G;SuUM~vEt=&U&>g*H49UYzL)APV_R-N8p8uzZ5t6|#FZ<(
zUEYUbgsdVcI`pJbE-%9P3hmw-9Zx5R7!)yws!)pSs#$W~O8G;j?1xM##C^eMr!fm=
z6S102NddpnoctU}&S^iAeHI#8rCdVJ(maiPEeOe&R;zoOTgPjA3B|Ftmm^Wz(_+Qr
zRA&^0x=Thz$xx&h@ij~bqbYq<-9secgE1ZmiMEJHXn{T|gDD^ahidVgtRk7&_!l^GOZHM3X0r1Y+%vN|;X$soeR-HE
zwQB7K&uhAHcL&u+Ld~KSJrsU{?7HAWVR!Qo(D8uJSsH4HVv2-hHvdri#;pv}4oS~H
zykDBeZ)0+hcv`01h|3Vf{LorN3!*2n)ZWhqg&f40LDmEVaehr71u$xcr4UQhP@A(*
zao6aOX#{JbmuTu$x`22-w*kIQxaS-@IdCh6xz82G!UTYva1cA^uu_N>Mk^EKc@{8}
z4@Ie*Y5-*d+HCXNte}9>2l_GLG`!X=1lnIxbu#6r7`}R!w$gsGi6Ezgv}Qs-qWAR@
z3rChd#@jfly3i?PpbM!AIZvvsX4Bos_&z9#ShP)`OCPhuG|6j))w_P2MmB}>W7#tP
zVcJV9v=R%DB~Yy^vTl*wWwccRgaSh@)PPTr-ese*lCkEv=VyX|nrZf)N8T=I+bV@B
z)*Kd`8lBNBO~)glOQv8Q%lF29lTuh`SP)>dP#z}orsm+gJw|vK>OS+AS^qG0_)E{H
z&2)^j)HL6CoZ|#5ufMFFV0Sn>pU&{FW`#YpYuuk+j7QV)@n|yWk87=mcTXm#v)}sT
z;oyOn5I`K`Op`zZS>yI=N?ds_>Nm92|e@g=U4v(c!3GMx@z_0KM*o0{}}Lhf^K
zB8uUmG5{vvpD7N7!~KX#Sb|l|sNpxEpX(iRKD)xf4pT!14{>!wgsB9kXKHNxV44~YR%XNi
zCH~>weiK&gCgjmVFTGa#S35d-Zyo0uIq~N4X8+^MXUmgn3U|+^htBosdwpqqUzl-UkIh~hT(*G*HL2S)SUZQ
zA1A-1SRxP+keG%{$I_|oe}4VGx(U}8*sxVm-Nbs1Z_03dr2Fzww^IHWP)h*<7XuUk
z000O8Y)?TuFaxSOEd~GpJr4i?5daMU000000RR91?STLQ003}dXJub(Z((F#b7^fZ
paAoFS7su
literal 0
HcmV?d00001
diff --git a/src/server/base/site/tests/proxy_page_load.php b/src/server/base/site/tests/proxy_page_load.php
new file mode 100755
index 0000000..ebe7046
--- /dev/null
+++ b/src/server/base/site/tests/proxy_page_load.php
@@ -0,0 +1,212 @@
+Cfg->Get("test.http.timeout",-1);
+ if ($nto>0) $timeout=$nto; // use NATS timeout
+ }
+ }
+ if ($timeout>0) // use the set timeout
+ $oldtimeout=ini_set("default_socket_timeout",$timeout);
+
+ $timer->Start();
+
+ // Requires CURL Now
+
+ $ch=curl_init();
+ curl_setopt($ch,CURLOPT_URL,$url);
+ curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
+ curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,0);
+ curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,0);
+ curl_setopt($ch,CURLOPT_HEADER,1);
+ if ($timeout>0) curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,$timeout);
+ if ($timeout>0) curl_setopt($ch,CURLOPT_TIMEOUT,$timeout);
+ if (!$output=curl_exec($ch))
+ {
+ $ctr=-1; // failed
+ }
+ else $ctr=round(curl_getinfo($ch,CURLINFO_SIZE_DOWNLOAD)/1024,2);
+ curl_close($ch);
+
+ if ($ctr==0) $ctr="0.0001";
+
+
+
+ if ($ctr<0) return $ctr; // negative number (-1) failed to open
+
+ $elapsed=$timer->Stop();
+
+ if ($timeout>0) ini_set("default_socket_timeout",$oldtimeout);
+
+ // now to check the actual text
+ if (is_array($text))
+ {
+ foreach($text as $findthis)
+ {
+ if ($findthis!="")
+ if (strpos($output,$findthis)===false) return -2; // text to be found not found
+ }
+ }
+ if (is_array($notext))
+ {
+ foreach($notext as $donotfindthis)
+ {
+ if ($donotfindthis!="")
+ if (strpos($output,$donotfindthis)!==false) return -3; // text not to find found
+ }
+ }
+
+ return $elapsed;
+ }
+
+ function Evaluate($result)
+ {
+ if ($result>0) return 0; // FreeNATS passed (0) flag if > 0
+ return 2; // FreeNATS failed (2) flag ( <= 0 )
+ }
+
+ function ProtectOutput(&$test)
+ {
+ $test['testparam4']=""; // blank proxy password for output
+ return true;
+ }
+
+ function DisplayForm(&$test)
+ {
+ $out="";
+ $out.="
";
+ $out.=" ";
+ $out.=" ";
+ $out.="";
+ $out.=" String(s) to search for - all defined must be found for the test to pass ";
+ $out.="Blank strings are ignored.";
+ $out.="
";
+ $out.="
No Strings :
";
+ $out.="
";
+ $out.=" ";
+ $out.=" ";
+ $out.="";
+ $out.=" String(s) to NOT find - fails if any are present Leave blank to not use this portion of the test";
+ $out.="
";
+
+ $out.="
Username :
";
+ $out.="
";
+ $out.="";
+ $out.=" Specify to use HTTP-AUTH on the URL";
+ $out.="
";
+
+ $out.="
Password :
";
+ $out.="
";
+ $out.=""; // dont display it
+ $out.=""; // don't update testparam3 (if blank)
+ $out.=" Enter a new password to set or... ";
+ $out.=" "; // clears testparam3 if set
+ $out.="clear it";
+ $out.="
";
+ echo $out; // output the buffer
+ }
+}
+
+// Now we have defined the class we must register it with FreeNATS
+
+$params=array(); // blank parameters array as we have implemented DisplayForm above
+
+if (function_exists("curl_getinfo")) // register if CURL exists
+{
+$NATS->Tests->Register(
+ "proxypage", // the internal simple test name (must not conflict with anything else)
+ "Proxy_Page_Test", // the class name (above)
+ $params, // parameters (blank for now)
+ "Web Proxy Test", // the display name of the test in the interface
+ 3, // the revision number of the test
+ "Proxy Page Test"); // extended description for the test module used in overview
+$NATS->Tests->SetUnits("proxypage","Seconds","s");
+}
+else
+{ // display appropriate error
+$NATS->Event("Proxy Test Not Loaded as CURL Not Supported",3,"Proxy Test","Extras");
+}
+?>
diff --git a/src/server/base/site/tests/tcpdebug.php b/src/server/base/site/tests/tcpdebug.php
new file mode 100755
index 0000000..13096f1
--- /dev/null
+++ b/src/server/base/site/tests/tcpdebug.php
@@ -0,0 +1,57 @@
+ ".$ip."\n";
+ if ($ip=="0") return -2; // lookup failed
+ echo "Lookup Successful\n";
+ $errno=0;
+ $errstr="";
+ $timer->Start();
+ echo "Doing fsockopen()\n";
+ $fp=@fsockopen($ip,$param,$errno,$errstr,$timeout);
+ $elapsed=$timer->Stop();
+ echo "FP is : ";
+ echo $fp;
+ echo "\n";
+ if ($fp===false) return -1; // open failed
+ echo "Closing\n";
+ @fclose($fp);
+ return $elapsed;
+ }
+
+ function Evaluate($result)
+ {
+ if ($result<0) return 2; // failure
+ return 0; // else success
+ }
+
+ function DisplayForm(&$row)
+ {
+ echo "
";
+ echo "
";
+ echo "TCP Port :";
+ echo "
";
+ echo "";
+ echo "
";
+ echo "
";
+ }
+
+ }
+
+$params=array();
+$NATS->Tests->Register("tcpdebug","FreeNATS_TCP_Debug",$params,"TCP Debug Connect",1,"FreeNATS TCP Debug");
+$NATS->Tests->SetUnits("tcpdebug","Seconds","s");
+}
+
+
+?>
\ No newline at end of file
diff --git a/src/server/base/sql/default.sql b/src/server/base/sql/default.sql
new file mode 100755
index 0000000..3dcefd6
--- /dev/null
+++ b/src/server/base/sql/default.sql
@@ -0,0 +1,48 @@
+-- default.sql
+-- FreeNATS Default Settings
+INSERT INTO fnuser(username,password,realname,userlevel) VALUES("admin",MD5("admin"),"Administrator",10);
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("site.name","FreeNATS");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("site.admin","");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("site.email","");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("site.enable.tester","1");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("site.enable.web","1");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("site.enable.adminsql","0");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("site.enable.interactive","1");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("site.popupmessage","0");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("site.graph.public","0");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("site.text.closed","Alert Closed");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("site.text.untested","Untested");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("site.text.passed","Passed");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("site.text.warning","Warning");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("site.text.failed","Failed");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("site.dtformat","H:i:s d/m/Y");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("site.include.tests","0");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("site.include.events","0");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("site.links.newwindow","1");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("log.level","5");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("freenats.firstrun","1");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("freenats.tracker","1");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("test.http.timeout","0");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("test.icmp.attempts","2");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("test.icmp.timeout","0");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("test.icmp.returnms","0");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("test.smtp.timeout","0");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("test.imap.timeout","0");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("test.mysql.timeout","0");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("test.tcp.timeout","0");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("test.udp.timeout","0");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("test.spawndelay","1");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("test.interval","0");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("retain.alert","0");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("retain.testrun","0");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("retain.record","0");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("retain.syslog","0");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("mail.fromname","");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("mail.smtphostname","");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("mail.smtpserver","");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("mail.smtppassword","");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("alert.body.footer","");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("alert.body.header","FreeNATS Alert,");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("alert.subject.long","** FreeNATS Alert **");
+INSERT INTO fnconfig(fnc_var,fnc_val) VALUES("alert.subject.short","FreeNATS Alert");
+
diff --git a/src/server/base/sql/example.sql b/src/server/base/sql/example.sql
new file mode 100755
index 0000000..b5c95bf
--- /dev/null
+++ b/src/server/base/sql/example.sql
@@ -0,0 +1,3 @@
+-- example.sql
+-- FreeNATS Example Settings
+INSERT INTO fnnode(nodeid,nodename,nodedesc,hostname,nodeenabled,pingtest,weight) VALUES("freenats","FreeNATS","FreeNATS Server","127.0.0.1",1,1,10);
\ No newline at end of file
diff --git a/src/server/base/sql/schema.drop.sql b/src/server/base/sql/schema.drop.sql
new file mode 100755
index 0000000..213265c
--- /dev/null
+++ b/src/server/base/sql/schema.drop.sql
@@ -0,0 +1,247 @@
+-- With DROP TABLES - will clean database
+-- MySQL dump 10.9
+--
+-- Host: localhost Database: freenats
+-- ------------------------------------------------------
+-- Server version 4.1.14
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES utf8 */;
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
+
+--
+-- Table structure for table `fnalert`
+--
+
+DROP TABLE IF EXISTS `fnalert`;
+CREATE TABLE `fnalert` (
+ `alertid` bigint(20) unsigned NOT NULL auto_increment,
+ `nodeid` varchar(64) NOT NULL default '',
+ `alertlevel` int(11) NOT NULL default '0',
+ `openedx` bigint(20) unsigned NOT NULL default '0',
+ `closedx` bigint(20) unsigned NOT NULL default '0',
+ PRIMARY KEY (`alertid`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+--
+-- Table structure for table `fnalertaction`
+--
+
+DROP TABLE IF EXISTS `fnalertaction`;
+CREATE TABLE `fnalertaction` (
+ `aaid` bigint(20) unsigned NOT NULL auto_increment,
+ `atype` varchar(32) NOT NULL default '',
+ `efrom` varchar(250) NOT NULL default '',
+ `etolist` text NOT NULL,
+ `esubject` int(11) NOT NULL default '0',
+ `etype` int(11) NOT NULL default '0',
+ `awarnings` tinyint(1) NOT NULL default '0',
+ `adecrease` tinyint(1) NOT NULL default '0',
+ `mdata` text NOT NULL,
+ `aname` varchar(120) NOT NULL default '',
+ `ctrdate` varchar(8) NOT NULL default '',
+ `ctrlimit` int(10) unsigned NOT NULL default '0',
+ `ctrtoday` int(10) unsigned NOT NULL default '0',
+ PRIMARY KEY (`aaid`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+--
+-- Table structure for table `fnalertlog`
+--
+
+DROP TABLE IF EXISTS `fnalertlog`;
+CREATE TABLE `fnalertlog` (
+ `alid` bigint(20) unsigned NOT NULL auto_increment,
+ `alertid` bigint(20) unsigned NOT NULL default '0',
+ `postedx` bigint(20) unsigned NOT NULL default '0',
+ `logentry` varchar(250) NOT NULL default '',
+ PRIMARY KEY (`alid`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+--
+-- Table structure for table `fnconfig`
+--
+
+DROP TABLE IF EXISTS `fnconfig`;
+CREATE TABLE `fnconfig` (
+ `fnc_var` varchar(64) NOT NULL default '',
+ `fnc_val` varchar(64) NOT NULL default '',
+ PRIMARY KEY (`fnc_var`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+--
+-- Table structure for table `fneval`
+--
+
+DROP TABLE IF EXISTS `fneval`;
+CREATE TABLE `fneval` (
+ `evalid` bigint(20) unsigned NOT NULL auto_increment,
+ `testid` varchar(128) NOT NULL default '',
+ `weight` int(11) NOT NULL default '0',
+ `eoperator` varchar(32) NOT NULL default '',
+ `evalue` varchar(128) NOT NULL default '',
+ `eoutcome` int(11) NOT NULL default '0',
+ PRIMARY KEY (`evalid`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+--
+-- Table structure for table `fngroup`
+--
+
+DROP TABLE IF EXISTS `fngroup`;
+CREATE TABLE `fngroup` (
+ `groupid` bigint(20) unsigned NOT NULL auto_increment,
+ `groupname` varchar(128) NOT NULL default '',
+ `groupdesc` varchar(250) NOT NULL default '',
+ `groupicon` varchar(64) NOT NULL default '',
+ `weight` int(10) unsigned NOT NULL default '0',
+ PRIMARY KEY (`groupid`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+--
+-- Table structure for table `fngrouplink`
+--
+
+DROP TABLE IF EXISTS `fngrouplink`;
+CREATE TABLE `fngrouplink` (
+ `glid` bigint(20) unsigned NOT NULL auto_increment,
+ `groupid` bigint(20) unsigned NOT NULL default '0',
+ `nodeid` varchar(64) NOT NULL default '',
+ PRIMARY KEY (`glid`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+--
+-- Table structure for table `fnlocaltest`
+--
+
+DROP TABLE IF EXISTS `fnlocaltest`;
+CREATE TABLE `fnlocaltest` (
+ `localtestid` bigint(20) unsigned NOT NULL auto_increment,
+ `nodeid` varchar(64) NOT NULL default '',
+ `alertlevel` int(11) NOT NULL default '-1',
+ `lastrunx` bigint(20) unsigned NOT NULL default '0',
+ `testtype` varchar(128) NOT NULL default '',
+ `testparam` varchar(250) default NULL,
+ `testrecord` tinyint(1) NOT NULL default '0',
+ `simpleeval` tinyint(1) NOT NULL default '1',
+ PRIMARY KEY (`localtestid`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+--
+-- Table structure for table `fnlog`
+--
+
+DROP TABLE IF EXISTS `fnlog`;
+CREATE TABLE `fnlog` (
+ `logid` bigint(20) unsigned NOT NULL auto_increment,
+ `postedx` bigint(20) unsigned NOT NULL default '0',
+ `modid` varchar(32) NOT NULL default '',
+ `catid` varchar(32) NOT NULL default '',
+ `username` varchar(64) NOT NULL default '',
+ `loglevel` int(11) NOT NULL default '1',
+ `logevent` varchar(250) NOT NULL default '',
+ PRIMARY KEY (`logid`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+--
+-- Table structure for table `fnnalink`
+--
+
+DROP TABLE IF EXISTS `fnnalink`;
+CREATE TABLE `fnnalink` (
+ `nalid` bigint(20) unsigned NOT NULL auto_increment,
+ `nodeid` varchar(64) NOT NULL default '',
+ `aaid` bigint(20) unsigned NOT NULL default '0',
+ PRIMARY KEY (`nalid`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+--
+-- Table structure for table `fnnode`
+--
+
+DROP TABLE IF EXISTS `fnnode`;
+CREATE TABLE `fnnode` (
+ `nodeid` varchar(64) NOT NULL default '',
+ `nodename` varchar(128) NOT NULL default '',
+ `nodedesc` varchar(254) NOT NULL default '',
+ `hostname` varchar(254) NOT NULL default '',
+ `nodeenabled` tinyint(1) NOT NULL default '0',
+ `pingtest` tinyint(1) NOT NULL default '0',
+ `pingfatal` tinyint(1) NOT NULL default '0',
+ `alertlevel` int(11) NOT NULL default '-1',
+ `nodeicon` varchar(64) NOT NULL default '',
+ `weight` int(10) unsigned NOT NULL default '0',
+ `nodealert` tinyint(1) NOT NULL default '1',
+ PRIMARY KEY (`nodeid`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+--
+-- Table structure for table `fnrecord`
+--
+
+DROP TABLE IF EXISTS `fnrecord`;
+CREATE TABLE `fnrecord` (
+ `recordid` bigint(20) unsigned NOT NULL auto_increment,
+ `testid` varchar(128) NOT NULL default '',
+ `alertlevel` int(11) NOT NULL default '0',
+ `testvalue` float NOT NULL default '0',
+ `recordx` bigint(20) unsigned NOT NULL default '0',
+ `nodeid` varchar(64) NOT NULL default '',
+ PRIMARY KEY (`recordid`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+--
+-- Table structure for table `fnsession`
+--
+
+DROP TABLE IF EXISTS `fnsession`;
+CREATE TABLE `fnsession` (
+ `sessionid` bigint(20) unsigned NOT NULL auto_increment,
+ `sessionkey` varchar(128) NOT NULL default '',
+ `ipaddress` varchar(128) NOT NULL default '',
+ `username` varchar(64) NOT NULL default '',
+ `startx` bigint(20) unsigned NOT NULL default '0',
+ `updatex` bigint(20) unsigned NOT NULL default '0',
+ `userlevel` int(11) NOT NULL default '0',
+ PRIMARY KEY (`sessionid`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+--
+-- Table structure for table `fntestrun`
+--
+
+DROP TABLE IF EXISTS `fntestrun`;
+CREATE TABLE `fntestrun` (
+ `trid` bigint(20) unsigned NOT NULL auto_increment,
+ `startx` bigint(20) unsigned NOT NULL default '0',
+ `finishx` bigint(20) unsigned NOT NULL default '0',
+ `routput` text NOT NULL,
+ `fnode` varchar(64) NOT NULL default '',
+ PRIMARY KEY (`trid`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+--
+-- Table structure for table `fnuser`
+--
+
+DROP TABLE IF EXISTS `fnuser`;
+CREATE TABLE `fnuser` (
+ `username` varchar(64) NOT NULL default '',
+ `password` varchar(64) NOT NULL default '',
+ `realname` varchar(128) NOT NULL default '',
+ `userlevel` int(11) NOT NULL default '1'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
+
diff --git a/src/server/base/sql/schema.sql b/src/server/base/sql/schema.sql
new file mode 100755
index 0000000..6d3b7ca
--- /dev/null
+++ b/src/server/base/sql/schema.sql
@@ -0,0 +1,224 @@
+-- No DROP TABLES - suitable for upgrade
+-- MySQL dump 10.9
+--
+-- Host: localhost Database: freenats
+-- ------------------------------------------------------
+-- Server version 4.1.14
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
+
+--
+-- Table structure for table `fnalert`
+--
+
+CREATE TABLE `fnalert` (
+ `alertid` bigint(20) unsigned NOT NULL auto_increment,
+ `nodeid` varchar(64) NOT NULL default '',
+ `alertlevel` int(11) NOT NULL default '0',
+ `openedx` bigint(20) unsigned NOT NULL default '0',
+ `closedx` bigint(20) unsigned NOT NULL default '0',
+ PRIMARY KEY (`alertid`)
+);
+
+--
+-- Table structure for table `fnalertaction`
+--
+
+CREATE TABLE `fnalertaction` (
+ `aaid` bigint(20) unsigned NOT NULL auto_increment,
+ `atype` varchar(32) NOT NULL default '',
+ `efrom` varchar(250) NOT NULL default '',
+ `etolist` text NOT NULL,
+ `esubject` int(11) NOT NULL default '0',
+ `etype` int(11) NOT NULL default '0',
+ `awarnings` tinyint(1) NOT NULL default '0',
+ `adecrease` tinyint(1) NOT NULL default '0',
+ `mdata` text NOT NULL,
+ `aname` varchar(120) NOT NULL default '',
+ `ctrdate` varchar(8) NOT NULL default '',
+ `ctrlimit` int(10) unsigned NOT NULL default '0',
+ `ctrtoday` int(10) unsigned NOT NULL default '0',
+ PRIMARY KEY (`aaid`)
+);
+
+--
+-- Table structure for table `fnalertlog`
+--
+
+CREATE TABLE `fnalertlog` (
+ `alid` bigint(20) unsigned NOT NULL auto_increment,
+ `alertid` bigint(20) unsigned NOT NULL default '0',
+ `postedx` bigint(20) unsigned NOT NULL default '0',
+ `logentry` varchar(250) NOT NULL default '',
+ PRIMARY KEY (`alid`)
+);
+
+--
+-- Table structure for table `fnconfig`
+--
+
+CREATE TABLE `fnconfig` (
+ `fnc_var` varchar(64) NOT NULL default '',
+ `fnc_val` varchar(64) NOT NULL default '',
+ PRIMARY KEY (`fnc_var`)
+);
+
+--
+-- Table structure for table `fneval`
+--
+
+CREATE TABLE `fneval` (
+ `evalid` bigint(20) unsigned NOT NULL auto_increment,
+ `testid` varchar(128) NOT NULL default '',
+ `weight` int(11) NOT NULL default '0',
+ `eoperator` varchar(32) NOT NULL default '',
+ `evalue` varchar(128) NOT NULL default '',
+ `eoutcome` int(11) NOT NULL default '0',
+ PRIMARY KEY (`evalid`)
+);
+
+--
+-- Table structure for table `fngroup`
+--
+
+CREATE TABLE `fngroup` (
+ `groupid` bigint(20) unsigned NOT NULL auto_increment,
+ `groupname` varchar(128) NOT NULL default '',
+ `groupdesc` varchar(250) NOT NULL default '',
+ `groupicon` varchar(64) NOT NULL default '',
+ `weight` int(10) unsigned NOT NULL default '0',
+ PRIMARY KEY (`groupid`)
+);
+
+--
+-- Table structure for table `fngrouplink`
+--
+
+CREATE TABLE `fngrouplink` (
+ `glid` bigint(20) unsigned NOT NULL auto_increment,
+ `groupid` bigint(20) unsigned NOT NULL default '0',
+ `nodeid` varchar(64) NOT NULL default '',
+ PRIMARY KEY (`glid`)
+);
+
+--
+-- Table structure for table `fnlocaltest`
+--
+
+CREATE TABLE `fnlocaltest` (
+ `localtestid` bigint(20) unsigned NOT NULL auto_increment,
+ `nodeid` varchar(64) NOT NULL default '',
+ `alertlevel` int(11) NOT NULL default '-1',
+ `lastrunx` bigint(20) unsigned NOT NULL default '0',
+ `testtype` varchar(128) NOT NULL default '',
+ `testparam` varchar(250) default NULL,
+ `testrecord` tinyint(1) NOT NULL default '0',
+ `simpleeval` tinyint(1) NOT NULL default '1',
+ PRIMARY KEY (`localtestid`)
+);
+
+--
+-- Table structure for table `fnlog`
+--
+
+CREATE TABLE `fnlog` (
+ `logid` bigint(20) unsigned NOT NULL auto_increment,
+ `postedx` bigint(20) unsigned NOT NULL default '0',
+ `modid` varchar(32) NOT NULL default '',
+ `catid` varchar(32) NOT NULL default '',
+ `username` varchar(64) NOT NULL default '',
+ `loglevel` int(11) NOT NULL default '1',
+ `logevent` varchar(250) NOT NULL default '',
+ PRIMARY KEY (`logid`)
+);
+
+--
+-- Table structure for table `fnnalink`
+--
+
+CREATE TABLE `fnnalink` (
+ `nalid` bigint(20) unsigned NOT NULL auto_increment,
+ `nodeid` varchar(64) NOT NULL default '',
+ `aaid` bigint(20) unsigned NOT NULL default '0',
+ PRIMARY KEY (`nalid`)
+);
+
+--
+-- Table structure for table `fnnode`
+--
+
+CREATE TABLE `fnnode` (
+ `nodeid` varchar(64) NOT NULL default '',
+ `nodename` varchar(128) NOT NULL default '',
+ `nodedesc` varchar(254) NOT NULL default '',
+ `hostname` varchar(254) NOT NULL default '',
+ `nodeenabled` tinyint(1) NOT NULL default '0',
+ `pingtest` tinyint(1) NOT NULL default '0',
+ `pingfatal` tinyint(1) NOT NULL default '0',
+ `alertlevel` int(11) NOT NULL default '-1',
+ `nodeicon` varchar(64) NOT NULL default '',
+ `weight` int(10) unsigned NOT NULL default '0',
+ `nodealert` tinyint(1) NOT NULL default '1',
+ PRIMARY KEY (`nodeid`)
+);
+
+--
+-- Table structure for table `fnrecord`
+--
+
+CREATE TABLE `fnrecord` (
+ `recordid` bigint(20) unsigned NOT NULL auto_increment,
+ `testid` varchar(128) NOT NULL default '',
+ `alertlevel` int(11) NOT NULL default '0',
+ `testvalue` float NOT NULL default '0',
+ `recordx` bigint(20) unsigned NOT NULL default '0',
+ `nodeid` varchar(64) NOT NULL default '',
+ PRIMARY KEY (`recordid`)
+);
+
+--
+-- Table structure for table `fnsession`
+--
+
+CREATE TABLE `fnsession` (
+ `sessionid` bigint(20) unsigned NOT NULL auto_increment,
+ `sessionkey` varchar(128) NOT NULL default '',
+ `ipaddress` varchar(128) NOT NULL default '',
+ `username` varchar(64) NOT NULL default '',
+ `startx` bigint(20) unsigned NOT NULL default '0',
+ `updatex` bigint(20) unsigned NOT NULL default '0',
+ `userlevel` int(11) NOT NULL default '0',
+ PRIMARY KEY (`sessionid`)
+);
+
+--
+-- Table structure for table `fntestrun`
+--
+
+CREATE TABLE `fntestrun` (
+ `trid` bigint(20) unsigned NOT NULL auto_increment,
+ `startx` bigint(20) unsigned NOT NULL default '0',
+ `finishx` bigint(20) unsigned NOT NULL default '0',
+ `routput` text NOT NULL,
+ `fnode` varchar(64) NOT NULL default '',
+ PRIMARY KEY (`trid`)
+);
+
+--
+-- Table structure for table `fnuser`
+--
+
+CREATE TABLE `fnuser` (
+ `username` varchar(64) NOT NULL default '',
+ `password` varchar(64) NOT NULL default '',
+ `realname` varchar(128) NOT NULL default '',
+ `userlevel` int(11) NOT NULL default '1'
+);
+
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
+
diff --git a/src/server/base/sql/schema.upgrade.sql b/src/server/base/sql/schema.upgrade.sql
new file mode 100755
index 0000000..c812783
--- /dev/null
+++ b/src/server/base/sql/schema.upgrade.sql
@@ -0,0 +1,241 @@
+-- Both will generate many many errors - run with --force, ignore errors
+-- dbupg.sh -- PurplePixie Systems
+--
+-- SHOW TABLES LIKE "fn%"
+-- Table: fnalert
+-- DESCRIBE fnalert
+ALTER TABLE `fnalert` CHANGE `alertid` `alertid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fnalert` ADD `alertid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fnalert` ADD PRIMARY KEY( `alertid` );
+ALTER TABLE `fnalert` CHANGE `nodeid` `nodeid` varchar(64) NOT NULL;
+ALTER TABLE `fnalert` ADD `nodeid` varchar(64) NOT NULL;
+ALTER TABLE `fnalert` CHANGE `alertlevel` `alertlevel` int(11) NOT NULL DEFAULT '0';
+ALTER TABLE `fnalert` ADD `alertlevel` int(11) NOT NULL DEFAULT '0';
+ALTER TABLE `fnalert` CHANGE `openedx` `openedx` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnalert` ADD `openedx` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnalert` CHANGE `closedx` `closedx` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnalert` ADD `closedx` bigint(20) unsigned NOT NULL DEFAULT '0';
+--
+-- Table: fnalertaction
+-- DESCRIBE fnalertaction
+ALTER TABLE `fnalertaction` CHANGE `aaid` `aaid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fnalertaction` ADD `aaid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fnalertaction` ADD PRIMARY KEY( `aaid` );
+ALTER TABLE `fnalertaction` CHANGE `atype` `atype` varchar(32) NOT NULL;
+ALTER TABLE `fnalertaction` ADD `atype` varchar(32) NOT NULL;
+ALTER TABLE `fnalertaction` CHANGE `efrom` `efrom` varchar(250) NOT NULL;
+ALTER TABLE `fnalertaction` ADD `efrom` varchar(250) NOT NULL;
+ALTER TABLE `fnalertaction` CHANGE `etolist` `etolist` text NOT NULL;
+ALTER TABLE `fnalertaction` ADD `etolist` text NOT NULL;
+ALTER TABLE `fnalertaction` CHANGE `esubject` `esubject` int(11) NOT NULL DEFAULT '0';
+ALTER TABLE `fnalertaction` ADD `esubject` int(11) NOT NULL DEFAULT '0';
+ALTER TABLE `fnalertaction` CHANGE `etype` `etype` int(11) NOT NULL DEFAULT '0';
+ALTER TABLE `fnalertaction` ADD `etype` int(11) NOT NULL DEFAULT '0';
+ALTER TABLE `fnalertaction` CHANGE `awarnings` `awarnings` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnalertaction` ADD `awarnings` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnalertaction` CHANGE `adecrease` `adecrease` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnalertaction` ADD `adecrease` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnalertaction` CHANGE `mdata` `mdata` text NOT NULL;
+ALTER TABLE `fnalertaction` ADD `mdata` text NOT NULL;
+ALTER TABLE `fnalertaction` CHANGE `aname` `aname` varchar(120) NOT NULL;
+ALTER TABLE `fnalertaction` ADD `aname` varchar(120) NOT NULL;
+ALTER TABLE `fnalertaction` CHANGE `ctrdate` `ctrdate` varchar(8) NOT NULL;
+ALTER TABLE `fnalertaction` ADD `ctrdate` varchar(8) NOT NULL;
+ALTER TABLE `fnalertaction` CHANGE `ctrlimit` `ctrlimit` int(10) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnalertaction` ADD `ctrlimit` int(10) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnalertaction` CHANGE `ctrtoday` `ctrtoday` int(10) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnalertaction` ADD `ctrtoday` int(10) unsigned NOT NULL DEFAULT '0';
+--
+-- Table: fnalertlog
+-- DESCRIBE fnalertlog
+ALTER TABLE `fnalertlog` CHANGE `alid` `alid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fnalertlog` ADD `alid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fnalertlog` ADD PRIMARY KEY( `alid` );
+ALTER TABLE `fnalertlog` CHANGE `alertid` `alertid` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnalertlog` ADD `alertid` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnalertlog` CHANGE `postedx` `postedx` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnalertlog` ADD `postedx` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnalertlog` CHANGE `logentry` `logentry` varchar(250) NOT NULL;
+ALTER TABLE `fnalertlog` ADD `logentry` varchar(250) NOT NULL;
+--
+-- Table: fnconfig
+-- DESCRIBE fnconfig
+ALTER TABLE `fnconfig` CHANGE `fnc_var` `fnc_var` varchar(64) NOT NULL;
+ALTER TABLE `fnconfig` ADD `fnc_var` varchar(64) NOT NULL;
+ALTER TABLE `fnconfig` ADD PRIMARY KEY( `fnc_var` );
+ALTER TABLE `fnconfig` CHANGE `fnc_val` `fnc_val` varchar(64) NOT NULL;
+ALTER TABLE `fnconfig` ADD `fnc_val` varchar(64) NOT NULL;
+--
+-- Table: fneval
+-- DESCRIBE fneval
+ALTER TABLE `fneval` CHANGE `evalid` `evalid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fneval` ADD `evalid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fneval` ADD PRIMARY KEY( `evalid` );
+ALTER TABLE `fneval` CHANGE `testid` `testid` varchar(128) NOT NULL;
+ALTER TABLE `fneval` ADD `testid` varchar(128) NOT NULL;
+ALTER TABLE `fneval` CHANGE `weight` `weight` int(11) NOT NULL DEFAULT '0';
+ALTER TABLE `fneval` ADD `weight` int(11) NOT NULL DEFAULT '0';
+ALTER TABLE `fneval` CHANGE `eoperator` `eoperator` varchar(32) NOT NULL;
+ALTER TABLE `fneval` ADD `eoperator` varchar(32) NOT NULL;
+ALTER TABLE `fneval` CHANGE `evalue` `evalue` varchar(128) NOT NULL;
+ALTER TABLE `fneval` ADD `evalue` varchar(128) NOT NULL;
+ALTER TABLE `fneval` CHANGE `eoutcome` `eoutcome` int(11) NOT NULL DEFAULT '0';
+ALTER TABLE `fneval` ADD `eoutcome` int(11) NOT NULL DEFAULT '0';
+--
+-- Table: fngroup
+-- DESCRIBE fngroup
+ALTER TABLE `fngroup` CHANGE `groupid` `groupid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fngroup` ADD `groupid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fngroup` ADD PRIMARY KEY( `groupid` );
+ALTER TABLE `fngroup` CHANGE `groupname` `groupname` varchar(128) NOT NULL;
+ALTER TABLE `fngroup` ADD `groupname` varchar(128) NOT NULL;
+ALTER TABLE `fngroup` CHANGE `groupdesc` `groupdesc` varchar(250) NOT NULL;
+ALTER TABLE `fngroup` ADD `groupdesc` varchar(250) NOT NULL;
+ALTER TABLE `fngroup` CHANGE `groupicon` `groupicon` varchar(64) NOT NULL;
+ALTER TABLE `fngroup` ADD `groupicon` varchar(64) NOT NULL;
+ALTER TABLE `fngroup` CHANGE `weight` `weight` int(10) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fngroup` ADD `weight` int(10) unsigned NOT NULL DEFAULT '0';
+--
+-- Table: fngrouplink
+-- DESCRIBE fngrouplink
+ALTER TABLE `fngrouplink` CHANGE `glid` `glid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fngrouplink` ADD `glid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fngrouplink` ADD PRIMARY KEY( `glid` );
+ALTER TABLE `fngrouplink` CHANGE `groupid` `groupid` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fngrouplink` ADD `groupid` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fngrouplink` CHANGE `nodeid` `nodeid` varchar(64) NOT NULL;
+ALTER TABLE `fngrouplink` ADD `nodeid` varchar(64) NOT NULL;
+--
+-- Table: fnlocaltest
+-- DESCRIBE fnlocaltest
+ALTER TABLE `fnlocaltest` CHANGE `localtestid` `localtestid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fnlocaltest` ADD `localtestid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fnlocaltest` ADD PRIMARY KEY( `localtestid` );
+ALTER TABLE `fnlocaltest` CHANGE `nodeid` `nodeid` varchar(64) NOT NULL;
+ALTER TABLE `fnlocaltest` ADD `nodeid` varchar(64) NOT NULL;
+ALTER TABLE `fnlocaltest` CHANGE `alertlevel` `alertlevel` int(11) NOT NULL DEFAULT '-1';
+ALTER TABLE `fnlocaltest` ADD `alertlevel` int(11) NOT NULL DEFAULT '-1';
+ALTER TABLE `fnlocaltest` CHANGE `lastrunx` `lastrunx` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnlocaltest` ADD `lastrunx` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnlocaltest` CHANGE `testtype` `testtype` varchar(128) NOT NULL;
+ALTER TABLE `fnlocaltest` ADD `testtype` varchar(128) NOT NULL;
+ALTER TABLE `fnlocaltest` CHANGE `testparam` `testparam` varchar(250);
+ALTER TABLE `fnlocaltest` ADD `testparam` varchar(250);
+ALTER TABLE `fnlocaltest` CHANGE `testrecord` `testrecord` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnlocaltest` ADD `testrecord` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnlocaltest` CHANGE `simpleeval` `simpleeval` tinyint(1) NOT NULL DEFAULT '1';
+ALTER TABLE `fnlocaltest` ADD `simpleeval` tinyint(1) NOT NULL DEFAULT '1';
+--
+-- Table: fnlog
+-- DESCRIBE fnlog
+ALTER TABLE `fnlog` CHANGE `logid` `logid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fnlog` ADD `logid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fnlog` ADD PRIMARY KEY( `logid` );
+ALTER TABLE `fnlog` CHANGE `postedx` `postedx` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnlog` ADD `postedx` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnlog` CHANGE `modid` `modid` varchar(32) NOT NULL;
+ALTER TABLE `fnlog` ADD `modid` varchar(32) NOT NULL;
+ALTER TABLE `fnlog` CHANGE `catid` `catid` varchar(32) NOT NULL;
+ALTER TABLE `fnlog` ADD `catid` varchar(32) NOT NULL;
+ALTER TABLE `fnlog` CHANGE `username` `username` varchar(64) NOT NULL;
+ALTER TABLE `fnlog` ADD `username` varchar(64) NOT NULL;
+ALTER TABLE `fnlog` CHANGE `loglevel` `loglevel` int(11) NOT NULL DEFAULT '1';
+ALTER TABLE `fnlog` ADD `loglevel` int(11) NOT NULL DEFAULT '1';
+ALTER TABLE `fnlog` CHANGE `logevent` `logevent` varchar(250) NOT NULL;
+ALTER TABLE `fnlog` ADD `logevent` varchar(250) NOT NULL;
+--
+-- Table: fnnalink
+-- DESCRIBE fnnalink
+ALTER TABLE `fnnalink` CHANGE `nalid` `nalid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fnnalink` ADD `nalid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fnnalink` ADD PRIMARY KEY( `nalid` );
+ALTER TABLE `fnnalink` CHANGE `nodeid` `nodeid` varchar(64) NOT NULL;
+ALTER TABLE `fnnalink` ADD `nodeid` varchar(64) NOT NULL;
+ALTER TABLE `fnnalink` CHANGE `aaid` `aaid` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnnalink` ADD `aaid` bigint(20) unsigned NOT NULL DEFAULT '0';
+--
+-- Table: fnnode
+-- DESCRIBE fnnode
+ALTER TABLE `fnnode` CHANGE `nodeid` `nodeid` varchar(64) NOT NULL;
+ALTER TABLE `fnnode` ADD `nodeid` varchar(64) NOT NULL;
+ALTER TABLE `fnnode` ADD PRIMARY KEY( `nodeid` );
+ALTER TABLE `fnnode` CHANGE `nodename` `nodename` varchar(128) NOT NULL;
+ALTER TABLE `fnnode` ADD `nodename` varchar(128) NOT NULL;
+ALTER TABLE `fnnode` CHANGE `nodedesc` `nodedesc` varchar(254) NOT NULL;
+ALTER TABLE `fnnode` ADD `nodedesc` varchar(254) NOT NULL;
+ALTER TABLE `fnnode` CHANGE `hostname` `hostname` varchar(254) NOT NULL;
+ALTER TABLE `fnnode` ADD `hostname` varchar(254) NOT NULL;
+ALTER TABLE `fnnode` CHANGE `nodeenabled` `nodeenabled` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnnode` ADD `nodeenabled` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnnode` CHANGE `pingtest` `pingtest` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnnode` ADD `pingtest` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnnode` CHANGE `pingfatal` `pingfatal` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnnode` ADD `pingfatal` tinyint(1) NOT NULL DEFAULT '0';
+ALTER TABLE `fnnode` CHANGE `alertlevel` `alertlevel` int(11) NOT NULL DEFAULT '-1';
+ALTER TABLE `fnnode` ADD `alertlevel` int(11) NOT NULL DEFAULT '-1';
+ALTER TABLE `fnnode` CHANGE `nodeicon` `nodeicon` varchar(64) NOT NULL;
+ALTER TABLE `fnnode` ADD `nodeicon` varchar(64) NOT NULL;
+ALTER TABLE `fnnode` CHANGE `weight` `weight` int(10) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnnode` ADD `weight` int(10) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnnode` CHANGE `nodealert` `nodealert` tinyint(1) NOT NULL DEFAULT '1';
+ALTER TABLE `fnnode` ADD `nodealert` tinyint(1) NOT NULL DEFAULT '1';
+--
+-- Table: fnrecord
+-- DESCRIBE fnrecord
+ALTER TABLE `fnrecord` CHANGE `recordid` `recordid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fnrecord` ADD `recordid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fnrecord` ADD PRIMARY KEY( `recordid` );
+ALTER TABLE `fnrecord` CHANGE `testid` `testid` varchar(128) NOT NULL;
+ALTER TABLE `fnrecord` ADD `testid` varchar(128) NOT NULL;
+ALTER TABLE `fnrecord` CHANGE `alertlevel` `alertlevel` int(11) NOT NULL DEFAULT '0';
+ALTER TABLE `fnrecord` ADD `alertlevel` int(11) NOT NULL DEFAULT '0';
+ALTER TABLE `fnrecord` CHANGE `testvalue` `testvalue` float NOT NULL DEFAULT '0';
+ALTER TABLE `fnrecord` ADD `testvalue` float NOT NULL DEFAULT '0';
+ALTER TABLE `fnrecord` CHANGE `recordx` `recordx` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnrecord` ADD `recordx` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnrecord` CHANGE `nodeid` `nodeid` varchar(64) NOT NULL;
+ALTER TABLE `fnrecord` ADD `nodeid` varchar(64) NOT NULL;
+--
+-- Table: fnsession
+-- DESCRIBE fnsession
+ALTER TABLE `fnsession` CHANGE `sessionid` `sessionid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fnsession` ADD `sessionid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fnsession` ADD PRIMARY KEY( `sessionid` );
+ALTER TABLE `fnsession` CHANGE `sessionkey` `sessionkey` varchar(128) NOT NULL;
+ALTER TABLE `fnsession` ADD `sessionkey` varchar(128) NOT NULL;
+ALTER TABLE `fnsession` CHANGE `ipaddress` `ipaddress` varchar(128) NOT NULL;
+ALTER TABLE `fnsession` ADD `ipaddress` varchar(128) NOT NULL;
+ALTER TABLE `fnsession` CHANGE `username` `username` varchar(64) NOT NULL;
+ALTER TABLE `fnsession` ADD `username` varchar(64) NOT NULL;
+ALTER TABLE `fnsession` CHANGE `startx` `startx` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnsession` ADD `startx` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnsession` CHANGE `updatex` `updatex` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnsession` ADD `updatex` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fnsession` CHANGE `userlevel` `userlevel` int(11) NOT NULL DEFAULT '0';
+ALTER TABLE `fnsession` ADD `userlevel` int(11) NOT NULL DEFAULT '0';
+--
+-- Table: fntestrun
+-- DESCRIBE fntestrun
+ALTER TABLE `fntestrun` CHANGE `trid` `trid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fntestrun` ADD `trid` bigint(20) unsigned NOT NULL auto_increment;
+ALTER TABLE `fntestrun` ADD PRIMARY KEY( `trid` );
+ALTER TABLE `fntestrun` CHANGE `startx` `startx` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fntestrun` ADD `startx` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fntestrun` CHANGE `finishx` `finishx` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fntestrun` ADD `finishx` bigint(20) unsigned NOT NULL DEFAULT '0';
+ALTER TABLE `fntestrun` CHANGE `routput` `routput` text NOT NULL;
+ALTER TABLE `fntestrun` ADD `routput` text NOT NULL;
+ALTER TABLE `fntestrun` CHANGE `fnode` `fnode` varchar(64) NOT NULL;
+ALTER TABLE `fntestrun` ADD `fnode` varchar(64) NOT NULL;
+--
+-- Table: fnuser
+-- DESCRIBE fnuser
+ALTER TABLE `fnuser` CHANGE `username` `username` varchar(64) NOT NULL;
+ALTER TABLE `fnuser` ADD `username` varchar(64) NOT NULL;
+ALTER TABLE `fnuser` CHANGE `password` `password` varchar(64) NOT NULL;
+ALTER TABLE `fnuser` ADD `password` varchar(64) NOT NULL;
+ALTER TABLE `fnuser` CHANGE `realname` `realname` varchar(128) NOT NULL;
+ALTER TABLE `fnuser` ADD `realname` varchar(128) NOT NULL;
+ALTER TABLE `fnuser` CHANGE `userlevel` `userlevel` int(11) NOT NULL DEFAULT '1';
+ALTER TABLE `fnuser` ADD `userlevel` int(11) NOT NULL DEFAULT '1';
+--
diff --git a/src/server/base/tests.inc.php b/src/server/base/tests.inc.php
new file mode 100755
index 0000000..089935c
--- /dev/null
+++ b/src/server/base/tests.inc.php
@@ -0,0 +1,374 @@
+Cfg->Get("test.interval",0);
+if ($sleep<=0) return false;
+$sleep=$sleep*1000000; // convert to usec
+usleep($sleep);
+return true;
+}
+
+function url_lookup($url)
+{
+// Sod regular expressions here as we'd have to do it twice or with cleverness I lack
+// Is it a URL?
+$colon=strpos($url,":");
+if ($colon != 0) // exists so it a URL
+ {
+ $out=preg_match("@^(?:http[s]*://)?([^/|\?|:]+)@i",$url,$matches);
+ $hostname=$matches[1];
+ }
+else $hostname=$url; // try direct
+
+return ip_lookup($hostname);
+}
+
+
+function bin_str_dump($s,$count=0)
+{
+//$s = base_convert($s,10,2);
+$data = unpack('C*',$s);
+foreach($data as $item)
+ {
+ echo ord($item)." ";
+ }
+echo "\n";
+}
+
+
+
+function PingTest($host,$ctimeout=-1)
+ {
+ global $NATS;
+
+ $returnsecs=true;
+ if (isset($NATS))
+ {
+ if ($NATS->Cfg->Get("test.icmp.returnms",0)==1) $returnsecs=false;
+ }
+
+ // Timeout Values
+ if (isset($NATS)) $timeout=$NATS->Cfg->Get("test.icmp.timeout",10);
+ else $timeout=10;
+ if ($ctimeout>0) $timeout=$ctimeout; // use custom timeout if passed
+ if ($timeout<=0) $timeout=10; // catch-all for defaults bug
+
+ $ping = new PPPing();
+ $ping->hostname = $host;
+ $ping->timeout = $timeout;
+
+ $result=$ping->Ping();
+
+ if ($result<0) // error condition
+ {
+ return $result;
+ }
+ else if ($result==0) // zero time
+ {
+ $result="0.0001";
+ }
+
+ if ($returnsecs)
+ {
+ $result = round($result/1000,3); // convert to seconds
+ if ($result==0) $result=0.0001;
+ }
+
+ return $result;
+ }
+
+function WebTest($url,$timeout=-1)
+ {
+ global $NATS;
+ if ($timeout<=0) // use NATS or env
+ {
+ if (isset($NATS))
+ {
+ $nto=$NATS->Cfg->Get("test.http.timeout",-1);
+ if ($nto>0) $timeout=$nto; // use NATS timeout
+ }
+ }
+ if ($timeout>0) // use the set timeout
+ $oldtimeout=ini_set("default_socket_timeout",$timeout);
+
+ if (function_exists("curl_getinfo")) // use CURL if present
+ {
+ $ch=curl_init();
+ curl_setopt($ch,CURLOPT_URL,$url);
+ curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
+ curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,0);
+ curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,0);
+ curl_setopt($ch,CURLOPT_HEADER,1);
+ if ($timeout>0) curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,$timeout);
+ if ($timeout>0) curl_setopt($ch,CURLOPT_TIMEOUT,$timeout);
+ if (!$output=curl_exec($ch))
+ {
+ $ctr=-1; // failed
+ }
+ else $ctr=round(curl_getinfo($ch,CURLINFO_SIZE_DOWNLOAD)/1024,2);
+ curl_close($ch);
+
+ if ($ctr==0) $ctr="0.0001";
+
+ }
+ else
+ { // no CURL - use fopen()
+ $oldagent=ini_set("user_agent","MSIE 4\.0b2;"); // MSIE 4.0b2 is HTTP/1.0 only just like fopen http wrapper
+ $fp=@fopen($url,"r");
+ if ($fp<=0)
+ {
+ if ($timeout>0) ini_set("default_socket_timeout",$oldtimeout);
+ ini_set("user_agent",$oldagent);
+ return -1;
+ }
+ $ctr=0;
+ while ($body=@fgets($fp,1024)) $ctr+=sizeof($body);
+ @fclose($fp);
+ ini_set("user_agent",$oldagent);
+ }
+
+
+
+ if ($timeout>0) ini_set("default_socket_timeout",$oldtimeout);
+ return $ctr;
+ }
+
+function DoTest($test,$param,$hostname="",$timeout=-1,$params=0,$nodeid="")
+{
+global $NATS;
+if (!is_array($params))
+ {
+ $params=array();
+ for ($a=0; $a<10; $a++) $params[$a]="";
+ }
+
+switch ($test)
+ {
+ case "web": case "wsize":
+ // Don't bother with pre-resolution as size only
+ return WebTest($param,$timeout);
+ break;
+ /* -- modularised
+ case "tcp": // nb TCP does not support timeouts currently
+ $ip=ip_lookup($hostname);
+ if ($ip=="0") return 0;
+ $fp=@fsockopen($ip,$param);
+ if ($fp<=0) return 0;
+ @fclose($fp);
+ return 1;
+ break;
+ */
+ case "wtime":
+ $timer=new TFNTimer();
+ // Do a pre-lookup
+ $ip=url_lookup($param);
+ if ($ip=="0") return -1; // dns lookup failed
+ $timer->Start();
+ $r=WebTest($param,$timeout);
+ $elapsedTime=$timer->Stop();
+ $elapsedTime=round($elapsedTime,4);
+ if ($r<0) return -1; // open failed
+ if ($r==0) return -2; // no chars shown as returned
+ if ($elapsedTime<=0) return 0.0001;
+ return $elapsedTime;
+ break;
+
+ case "host":
+ $timer=new TFNTimer();
+ if (preg_match("/[a-zA-Z]/",$param)>0) $is_ip=false;
+ else $is_ip=true;
+
+ $timer->Start();
+ if ($is_ip) $result=gethostbyaddr($param);
+ else $result=gethostbyname($param);
+ $elapsedTime=$timer->Stop();
+
+ if ($result==$param) // lookup failed
+ return -1;
+
+ if ($result=="") // lookup failed
+ return -1;
+
+ $elapsedTime=round($elapsedTime,4);
+ if ($elapsedTime<=0) return 0.0001;
+ return $elapsedTime;
+ break;
+
+ case "testloop":
+ return $param;
+ break;
+
+ case "testrand":
+ mt_srand(microtime()*1000000);
+ if ( ($param=="") || ($param==0) ) $param=100;
+ return mt_rand(0,$param);
+ break;
+
+ case "ping":
+ return PingTest($param,$timeout);
+ break;
+
+ default:
+ if (isset($NATS)) // try and see if a test is registered
+ {
+ if (isset($NATS->Tests->QuickList[$test])) // exists
+ {
+ $NATS->Tests->Tests[$test]->Create();
+ return $NATS->Tests->Tests[$test]->instance->DoTest($test,$param,$hostname,$timeout,$params);
+ }
+ }
+
+ }
+return -1; // did not run any test so untested
+}
+
+function SimpleEval($test,$result)
+{
+global $NATS;
+switch($test)
+ {
+ case "ping": // handles both types of simple evaluation (inbuilt ICMP and remote ping)
+ if ($result<=0) return 2;
+ return 0;
+ case "web": case "wsize":
+ if ($result<=0) return 2;
+ return 0;
+ /*
+ case "tcp":
+ if ($result==1) return 0;
+ return 2;
+ */
+ case "wtime":
+ if ($result<0) return 2;
+ return 0;
+ /*
+ case "mysql":
+ if ($result<=0) return 2;
+ return 0;
+
+ case "mysqlrows":
+ if ($result<=0) return 2; // no rows returned or error
+ return 0;
+ */
+ case "host": case "dns":
+ if ($result<=0) return 2; // no records returned or error
+
+ case "testloop":
+ return 0;
+ case "testrand":
+ return 0;
+
+ default:
+ if (isset($NATS))
+ {
+ if (isset($NATS->Tests->QuickList[$test]))
+ {
+ $NATS->Tests->Tests[$test]->Create();
+ return $NATS->Tests->Tests[$test]->instance->Evaluate($result);
+ }
+ }
+ }
+return -1; // untested if we don't know WTF the result was
+}
+
+function aText($al)
+{
+return oText($al); // uses function in tests.inc.php with site config support
+/* -- depreciated
+switch($al)
+ {
+ case -1: return "Untested";
+ case 0: return "Passed";
+ case 1: return "Warning";
+ case 2: return "Failed";
+ default: return "Unknown";
+ }
+*/
+}
+?>
\ No newline at end of file
diff --git a/src/server/base/tests/dns.inc.php b/src/server/base/tests/dns.inc.php
new file mode 100755
index 0000000..824dbc2
--- /dev/null
+++ b/src/server/base/tests/dns.inc.php
@@ -0,0 +1,562 @@
+types_by_id[$id]=$name;
+ $this->types_by_name[$name]=$id;
+ }
+
+ function DNSTypes()
+ {
+ $this->types_by_id=array();
+ $this->types_by_name=array();
+
+ $this->AddType(1,"A");
+ $this->AddType(2,"NS");
+ $this->AddType(5,"CNAME");
+ $this->AddType(6,"SOA");
+ $this->AddType(12,"PTR");
+ $this->AddType(15,"MX");
+ $this->AddType(16,"TXT");
+ $this->AddType(255,"ANY");
+ }
+
+ function GetByName($name)
+ {
+ if (isset($this->types_by_name[$name])) return $this->types_by_name[$name];
+ return 0;
+ }
+
+ function GetById($id)
+ {
+ if (isset($this->types_by_id[$id])) return $this->types_by_id[$id];
+ return "";
+ }
+}
+
+class DNSResult
+{
+ var $type;
+ var $typeid;
+ var $class;
+ var $ttl;
+ var $data;
+ var $domain;
+ var $string;
+ var $extas=array();
+}
+
+class DNSAnswer
+{
+ var $count=0;
+ var $results=array();
+
+ function AddResult($type,$typeid,$class,$ttl,$data,$domain="",$string="",$extras=array())
+ {
+ $this->results[$this->count]=new DNSResult();
+ $this->results[$this->count]->type=$type;
+ $this->results[$this->count]->typeid=$typeid;
+ $this->results[$this->count]->class=$class;
+ $this->results[$this->count]->ttl=$ttl;
+ $this->results[$this->count]->data=$data;
+ $this->results[$this->count]->domain=$domain;
+ $this->results[$this->count]->string=$string;
+ $this->results[$this->count]->extras=$extras;
+ $this->count++;
+ return ($this->count-1);
+ }
+}
+
+
+class DNSQuery
+{
+ var $server="";
+ var $port;
+ var $timeout;
+ var $udp;
+ var $debug;
+ var $binarydebug=false;
+
+ var $types;
+
+ var $rawbuffer="";
+ var $rawheader="";
+ var $rawresponse="";
+ var $header;
+ var $responsecounter=0;
+
+ var $lastnameservers;
+ var $lastadditional;
+
+ var $error=false;
+ var $lasterror="";
+
+ function ReadResponse($count=1,$offset="")
+ {
+ if ($offset=="") // no offset so use and increment the ongoing counter
+ {
+ $return=substr($this->rawbuffer,$this->responsecounter,$count);
+ $this->responsecounter+=$count;
+ }
+ else
+ {
+ $return=substr($this->rawbuffer,$offset,$count);
+ }
+ return $return;
+ }
+
+ function ReadDomainLabels($offset,&$counter=0)
+ {
+ $labels=array();
+ $startoffset=$offset;
+ $return=false;
+ while (!$return)
+ {
+ $label_len=ord($this->ReadResponse(1,$offset++));
+ if ($label_len<=0) $return=true; // end of data
+ else if ($label_len<64) // uncompressed data
+ {
+ $labels[]=$this->ReadResponse($label_len,$offset);
+ $offset+=$label_len;
+ }
+ else // label_len>=64 -- pointer
+ {
+ $nextitem=$this->ReadResponse(1,$offset++);
+ $pointer_offset = ( ($label_len & 0x3f) << 8 ) + ord($nextitem);
+ // Branch Back Upon Ourselves...
+ $this->Debug("Label Offset: ".$pointer_offset);
+ $pointer_labels=$this->ReadDomainLabels($pointer_offset);
+ foreach($pointer_labels as $ptr_label)
+ $labels[]=$ptr_label;
+ $return=true;
+ }
+ }
+ $counter=$offset-$startoffset;
+ return $labels;
+ }
+
+ function ReadDomainLabel()
+ {
+ $count=0;
+ $labels=$this->ReadDomainLabels($this->responsecounter,$count);
+ $domain=implode(".",$labels);
+ $this->responsecounter+=$count;
+ $this->Debug("Label ".$domain." len ".$count);
+ return $domain;
+ }
+
+ function Debug($text)
+ {
+ if ($this->debug) echo $text."\n";
+ }
+
+ function DebugBinary($data)
+ {
+ if ($this->binarydebug)
+ {
+ for ($a=0; $a30)&&($dec<150)) echo $data[$a];
+ echo "\n";
+ }
+ }
+ }
+
+ function SetError($text)
+ {
+ $this->error=true;
+ $this->lasterror=$text;
+ $this->Debug("Error: ".$text);
+ }
+
+ function ClearError()
+ {
+ $this->error=false;
+ $this->lasterror="";
+ }
+
+ function DNSQuery($server,$port=53,$timeout=60,$udp=true,$debug=false)
+ {
+ $this->server=$server;
+ $this->port=$port;
+ $this->timeout=$timeout;
+ $this->udp=$udp;
+ $this->debug=$debug;
+
+ $this->types=new DNSTypes();
+ $this->Debug("DNSQuery Class Initialised");
+ }
+
+
+ function ReadRecord()
+ {
+ // First the pesky domain names - maybe not so pesky though I suppose
+
+ $domain=$this->ReadDomainLabel();
+
+
+
+ $ans_header_bin=$this->ReadResponse(10); // 10 byte header
+ $ans_header=unpack("ntype/nclass/Nttl/nlength",$ans_header_bin);
+ $this->Debug("Record Type ".$ans_header['type']." Class ".$ans_header['class']." TTL ".$ans_header['ttl']." Length ".$ans_header['length']);
+
+ $typeid=$this->types->GetById($ans_header['type']);
+ $extras=array();
+ $data="";
+ $string="";
+
+ switch($typeid)
+ {
+ case "A":
+ $ip=implode(".",unpack("Ca/Cb/Cc/Cd",$this->ReadResponse(4)));
+ $data=$ip;
+ $string=$domain." has address ".$ip;
+ break;
+
+ case "NS":
+ $nameserver=$this->ReadDomainLabel();
+ $data=$nameserver;
+ $string=$domain." nameserver ".$nameserver;
+ break;
+
+ case "PTR":
+ $data=$this->ReadDomainLabel();
+ $string=$domain." points to ".$data;
+ break;
+
+ case "CNAME":
+ $data=$this->ReadDomainLabel();
+ $string=$domain." alias of ".$data;
+ break;
+
+ case "MX":
+ $prefs=$this->ReadResponse(2);
+ $prefs=unpack("nlevel",$prefs);
+ $extras['level']=$prefs['level'];
+ $data=$this->ReadDomainLabel();
+ $string=$domain." mailserver ".$data." (pri=".$extras['level'].")";
+ break;
+
+ case "SOA":
+ // Label First
+ $data=$this->ReadDomainLabel();
+ $responsible=$this->ReadDomainLabel();
+
+ $buffer=$this->ReadResponse(20);
+ $extras=unpack("nserial/nrefresh/Nretry/Nexpiry/Nminttl",$buffer);
+ $dot=strpos($responsible,".");
+ $responsible[$dot]="@";
+ $extras['responsible']=$responsible;
+ $string=$domain." SOA ".$data." Serial ".$extras['serial'];
+ break;
+
+ case "TXT":
+ $data=$this->ReadResponse($ans_header['length']);
+ $string=$domain." TEXT ".$data;
+ break;
+
+ default: // something we can't deal with
+ $stuff=$this->ReadResponse($ans_header['length']);
+ break;
+
+ }
+
+ //$dns_answer->AddResult($ans_header['type'],$typeid,$ans_header['class'],$ans_header['ttl'],$data,$domain,$string,$extras);
+ $return=array(
+ "header" => $ans_header,
+ "typeid" => $typeid,
+ "data" => $data,
+ "domain" => $domain,
+ "string" => $string,
+ "extras" => $extras );
+ return $return;
+ }
+
+
+
+
+
+
+ function Query($question,$type="A")
+ {
+ $this->ClearError();
+ $typeid=$this->types->GetByName($type);
+ if ($typeid===false)
+ {
+ $this->SetError("Invalid Query Type ".$type);
+ return false;
+ }
+
+ if ($this->udp) $host="udp://".$this->server;
+ else $host=$this->server;
+
+ if (!$socket=fsockopen($host,$this->port,$this->timeout))
+ {
+ $this->SetError("Failed to Open Socket");
+ return false;
+ }
+
+ // Split Into Labels
+ if (preg_match("/[a-z|A-Z]/",$question)==0) // IP Address
+ {
+ $labeltmp=explode(".",$question); // reverse ARPA format
+ for ($i=count($labeltmp)-1; $i>=0; $i--)
+ $labels[]=$labeltmp[$i];
+ $labels[]="IN-ADDR";
+ $labels[]="ARPA";
+ }
+ else // hostname
+ $labels=explode(".",$question);
+
+ $question_binary="";
+ for ($a=0; $aDebug("Question: ".$question." (type=".$type."/".$typeid.")");
+
+ $id=rand(1,255)|(rand(0,255)<<8); // generate the ID
+
+ // Set standard codes and flags
+ $flags=0x0100 & 0x0300; // recursion & queryspecmask
+ $opcode=0x0000; // opcode
+
+ // Build the header
+ $header="";
+ $header.=pack("n",$id);
+ $header.=pack("n",$opcode | $flags);
+ $header.=pack("nnnn",1,0,0,0);
+ $header.=$question_binary;
+ $header.=pack("n",$typeid);
+ $header.=pack("n",0x0001); // internet class
+ $headersize=strlen($header);
+ $headersizebin=pack("n",$headersize);
+
+ $this->Debug("Header Length: ".$headersize." Bytes");
+ $this->DebugBinary($header);
+
+ if ( ($this->udp) && ($headersize>=512) )
+ {
+ $this->SetError("Question too big for UDP (".$headersize." bytes)");
+ fclose($socket);
+ return false;
+ }
+
+ if ($this->udp) // UDP method
+ {
+ if (!fwrite($socket,$header,$headersize))
+ {
+ $this->SetError("Failed to write question to socket");
+ fclose($socket);
+ return false;
+ }
+ if (!$this->rawbuffer=fread($socket,4096)) // read until the end with UDP
+ {
+ $this->SetError("Failed to write read data buffer");
+ fclose($socket);
+ return false;
+ }
+ }
+ else // TCP
+ {
+ if (!fwrite($socket,$headersizebin)) // write the socket
+ {
+ $this->SetError("Failed to write question length to TCP socket");
+ fclose($socket);
+ return false;
+ }
+ if (!fwrite($socket,$header,$headersize))
+ {
+ $this->SetError("Failed to write question to TCP socket");
+ fclose($socket);
+ return false;
+ }
+ if (!$returnsize=fread($socket,2))
+ {
+ $this->SetError("Failed to read size from TCP socket");
+ fclose($socket);
+ return false;
+ }
+ $tmplen=unpack("nlength",$returnsize);
+ $datasize=$tmplen['length'];
+ $this->Debug("TCP Stream Length Limit ".$datasize);
+ if (!$this->rawbuffer=fread($socket,$datasize))
+ {
+ $this->SetError("Failed to read data buffer");
+ fclose($socket);
+ return false;
+ }
+ }
+ fclose($socket);
+
+ $buffersize=strlen($this->rawbuffer);
+ $this->Debug("Read Buffer Size ".$buffersize);
+
+ if ($buffersize<12)
+ {
+ $this->SetError("Return Buffer too Small");
+ return false;
+ }
+
+ $this->rawheader=substr($this->rawbuffer,0,12); // first 12 bytes is the header
+ $this->rawresponse=substr($this->rawbuffer,12); // after that the response
+
+ $this->responsecounter=12; // start parsing response counter from 12 - no longer using response so can do pointers
+
+ $this->DebugBinary($this->rawbuffer);
+
+ $this->header=unpack("nid/nspec/nqdcount/nancount/nnscount/narcount",$this->rawheader);
+
+ $answers=$this->header['ancount'];
+ $this->Debug("Query Returned ".$answers." Answers");
+
+ $dns_answer=new DNSAnswer();
+
+ // Deal with the header question data
+ if ($this->header['qdcount']>0)
+ {
+ $this->Debug("Found ".$this->header['qdcount']." Questions");
+ for ($a=0; $a<$this->header['qdcount']; $a++)
+ {
+ $c=1;
+ while ($c!=0)
+ {
+ $c=hexdec(bin2hex($this->ReadResponse(1)));
+ }
+ $extradata=$this->ReadResponse(4);
+ }
+ }
+
+ // New Functional Method
+ for ($a=0; $a<$this->header['ancount']; $a++)
+ {
+ $record=$this->ReadRecord();
+ $dns_answer->AddResult($record['header']['type'],$record['typeid'],$record['header']['class'],$record['header']['ttl'],
+ $record['data'],$record['domain'],$record['string'],$record['extras']);
+ }
+
+ $this->lastnameservers=new DNSAnswer();
+ for ($a=0; $a<$this->header['nscount']; $a++)
+ {
+ $record=$this->ReadRecord();
+ $this->lastnameservers->AddResult($record['header']['type'],$record['typeid'],$record['header']['class'],$record['header']['ttl'],
+ $record['data'],$record['domain'],$record['string'],$record['extras']);
+ }
+
+ $this->lastadditional=new DNSAnswer();
+ for ($a=0; $a<$this->header['arcount']; $a++)
+ {
+ $record=$this->ReadRecord();
+ $this->lastadditional->AddResult($record['header']['type'],$record['typeid'],$record['header']['class'],$record['header']['ttl'],
+ $record['data'],$record['domain'],$record['string'],$record['extras']);
+ }
+
+
+
+
+ return $dns_answer;
+ }
+
+
+function SmartALookup($hostname,$depth=0)
+ {
+ $this->Debug("SmartALookup for ".$hostname." depth ".$depth);
+ if ($depth>5) return ""; // avoid recursive lookups
+ // The SmartALookup function will resolve CNAMES using the additional properties if possible
+ $answer=$this->Query($hostname,"A");
+
+ if ($answer===false) return ""; // failed totally
+ if ($answer->count<=0) return ""; // no records at all returned
+
+ $best_answer="";
+ $best_answer_typeid=0;
+
+ $records=$answer->count;
+ for ($a=0; $a<$records; $a++)
+ {
+ $data=$answer->results[$a]->data;
+ $answer_typeid=$answer->results[$a]->typeid;
+
+ if ($answer_typeid=="A") // found it
+ {
+ $best_answer=$data;
+ $best_answer_typeid="A";
+ $a=$records+10;
+ }
+ else if ($answer_typeid=="CNAME") // alias
+ {
+ $best_answer=$data;
+ $best_answer_typeid="CNAME";
+ // and keep going
+ }
+
+ }
+
+ if ( ($best_answer=="") || ($best_answer_typeid=="") ) return "";
+
+ if ($best_answer_typeid=="A") return $best_answer; // got an IP ok
+
+ if ($best_answer_typeid!="CNAME") return ""; // shouldn't ever happen
+
+ $newtarget=$best_answer; // this is what we now need to resolve
+
+ // First is it in the additional section
+ for ($a=0; $a<$this->lastadditional->count; $a++)
+ {
+ if ( ($this->lastadditional->results[$a]->domain==$hostname) &&
+ ($this->lastadditional->results[$a]->typeid=="A") )
+ return $this->lastadditional->results[$a]->data;
+ }
+
+ // Not in the results
+
+ return $this->SmartALookup($newtarget,++$depth);
+ }
+
+}
+
+?>
\ No newline at end of file
diff --git a/src/server/base/tests/imap.inc.php b/src/server/base/tests/imap.inc.php
new file mode 100755
index 0000000..888bea1
--- /dev/null
+++ b/src/server/base/tests/imap.inc.php
@@ -0,0 +1,152 @@
+0) $timeout=$timeout; // use specific for test if set
+else
+ {
+ // otherwise use system if available
+ if (isset($NATS)) $timeout=$NATS->Cfg->Get("test.imap.timeout",0);
+ if ($timeout<=0) $timeout=0; // unset specifically or in environment
+ }
+
+if ($timeout>0) imap_timeout(IMAP_OPENTIMEOUT,$timeout);
+
+if ($port<=0)
+ {
+ $port=143; // default
+ if ( ($protocol=="imap") && ($ssl) ) $port=993;
+ else if ($protocol=="pop3")
+ {
+ if ($ssl) $port=995;
+ else $port=110;
+ }
+ }
+
+$mailbox="{".$host.":".$port."/service=".$protocol;
+if ($ssl) $mailbox.="/ssl";
+$mailbox.="/novalidate-cert";
+$mailbox.="}INBOX";
+if ($debug) echo $user.":".$pass."@".$mailbox."\n";
+$imap=@imap_open($mailbox,$user,$pass);
+if ($imap===false) return -1; // failed to connect/open
+
+@imap_close($imap);
+return 1;
+}
+
+function imap_test_time($host,$user,$pass,$timeout=-1,$protocol="imap",$port=-1,$ssl=false,$debug=false)
+{
+$timer=new TFNTimer();
+$timer->Start();
+$res=imap_test_connect($host,$user,$pass,$timeout,$protocol,$port,$ssl,$debug);
+$time=$timer->Stop();
+if ($res<=0) return $res; // test failed to connect
+$time=round($time,4);
+if ($time==0) $time=0.0001;
+return $time;
+}
+
+if (isset($NATS))
+{
+class FreeNATS_IMAP_Test extends FreeNATS_Local_Test
+ {
+ function DoTest($testname,$param,$hostname,$timeout,$params)
+ { // 0: host, 1: user, 2: pass, 3: protocol, 4: port, 5: ssl (1/0)
+ if ($params[5]==1) $ssl=true;
+ else $ssl=false;
+
+ $ip=ip_lookup($params[0]);
+ if ($ip=="0") return -1;
+
+ return imap_test_time($ip,$params[1],$params[2],$timeout,$params[3],$params[4],$ssl);
+
+ }
+ function Evaluate($result)
+ {
+ if ($result<=0) return 2; // failed
+ return 0; // passed
+ }
+
+ function ProtectOutput(&$test)
+ {
+ $test['testparam2']="";
+ }
+
+ function DisplayForm(&$row)
+ {
+ echo "
";
+ }
+
+ }
+$params=array();
+$NATS->Tests->Register("imap","FreeNATS_IMAP_Test",$params,"IMAP Connect",2,"FreeNATS IMAP/POP Tester");
+$NATS->Tests->SetUnits("imap","Seconds","s");
+}
+
+
+?>
\ No newline at end of file
diff --git a/src/server/base/tests/ldap.inc.php b/src/server/base/tests/ldap.inc.php
new file mode 100755
index 0000000..4d2605f
--- /dev/null
+++ b/src/server/base/tests/ldap.inc.php
@@ -0,0 +1,90 @@
+";
+ echo "
";
+ echo "LDAP URL:";
+ echo "
";
+ echo "";
+ echo "
";
+
+ echo "
";
+ echo "Bind DN:";
+ echo "
";
+ echo "";
+ echo "
Leave empty for anonymous bind
";
+
+ echo "
";
+ echo "Bind Password:";
+ echo "
";
+ echo "";
+ echo "
Leave empty for anonymous bind
";
+
+ echo "
";
+ echo "Search Base:";
+ echo "
";
+ echo "";
+ echo "
Leave empty for only test bind
";
+
+ echo "
";
+ echo "Search Filter:";
+ echo "
";
+ echo "";
+ echo "
Leave empty for only test bind
";
+
+ echo "
";
+ }
+}
+
+$params=array();
+$NATS->Tests->Register("ldap","LDAP_Test",$params,"LDAP Bind",1,"FreeNATS LDAP Test");
+
+?>
diff --git a/src/server/base/tests/mysql.inc.php b/src/server/base/tests/mysql.inc.php
new file mode 100755
index 0000000..3456d6f
--- /dev/null
+++ b/src/server/base/tests/mysql.inc.php
@@ -0,0 +1,313 @@
+Event("MySQL Test: ".$error,2,"Test","MySQL");
+}
+
+
+
+// Data Test
+function mysql_test_data($host,$user,$pass,$database="",$timeout=0,$query="",$column=0,$debug=false)
+{
+global $NATS;
+if ($timeout>0) $timeout=$timeout; // use specific for test if set
+else
+ {
+ // otherwise use system if available
+ if (isset($NATS)) $timeout=$NATS->Cfg->Get("test.mysql.timeout",0);
+ if ($timeout<=0) $timeout=0; // unset specifically or in environment
+ }
+// this will return a 0 at any stage if connect etc is ok but no rows are returned
+// negative if something actually fails
+if ($timeout>0)
+ {
+ $oldtimeout=ini_get("mysql.timeout");
+ ini_set("mysql.timeout",$timeout);
+ }
+
+if (!is_numeric($column)) $column=0;
+if ($column<0) $column=0;
+
+$sql=@mysql_connect($host,$user,$pass,true);
+
+if ((!$sql)||($database==""))
+ {
+ if ($timeout>0) ini_set("mysql.timeout",$oldtimeout);
+ if (!$sql)
+ {
+ if ($debug) echo "Connect Error: Failed to Connect\n";
+ fnmysql_error("Failed to Connect");
+ return -1; // total connect failed
+ }
+ // otherwise is no database so close and return -1 to indicate failure (for the data requires a DB+qry etc)
+ @mysql_close($sql);
+ return -1;
+ }
+
+@mysql_select_db($database,$sql);
+
+if (mysql_errno($sql)!=0) // failed to select DB
+ {
+ if ($timeout>0) ini_set("mysql.timeout",$oldtimeout);
+ fnmysql_error(mysql_error($sql));
+ @mysql_close($sql);
+ return -2; // select database failed
+ }
+
+if ($query=="")
+ { // no query to perform
+ if ($timeout>0) ini_set("mysql.timeout",$oldtimeout);
+ @mysql_close($sql);
+ return -1; // all ok but no query/rows
+ }
+
+$r=@mysql_query($query,$sql);
+if (mysql_errno($sql)==0) // successful query
+ {
+ if (is_bool($r)) // didn't return any data
+ {
+ $return=-4; // so for this purpose (data) the query failed
+ }
+ else
+ {
+ if ($row=mysql_fetch_array($r))
+ { // got data ok
+ if (isset($row[$column])) $return=$row[$column];
+ else $return=$row[0];
+ }
+ else $return=-5; // query seemed to succeed but no data at all here
+ @mysql_free_result($r,$sql); // free if a result
+ }
+ }
+else
+ {
+ fnmysql_error(mysql_error($sql));
+ $return=-3; // query failed
+ }
+
+@mysql_close($sql);
+if ($timeout>0) ini_set("mysql.timeout",$oldtimeout);
+return $return;
+}
+
+
+
+// Row Test
+function mysql_test_rows($host,$user,$pass,$database="",$timeout=0,$query="",$debug=false)
+{
+global $NATS;
+if ($timeout>0) $timeout=$timeout; // use specific for test if set
+else
+ {
+ // otherwise use system if available
+ if (isset($NATS)) $timeout=$NATS->Cfg->Get("test.mysql.timeout",0);
+ if ($timeout<=0) $timeout=0; // unset specifically or in environment
+ }
+// this will return a 0 at any stage if connect etc is ok but no rows are returned
+// negative if something actually fails
+if ($timeout>0)
+ {
+ $oldtimeout=ini_get("mysql.timeout");
+ ini_set("mysql.timeout",$timeout);
+ }
+
+if ($debug) echo "mysql://".$user.":".$pass."@".$host."/".$database."\n";
+
+$sql=@mysql_connect($host,$user,$pass,true);
+
+if ((!$sql)||($database==""))
+ {
+ if ($timeout>0) ini_set("mysql.timeout",$oldtimeout);
+ if (!$sql)
+ {
+ if ($debug) echo "Connect Error: Failed to Connect\n";
+ fnmysql_error("Failed to Connect");
+ return -1; // total connect failed
+ }
+ // otherwise is no database so close and return 0
+ @mysql_close($sql);
+ return 0;
+ }
+
+@mysql_select_db($database,$sql);
+
+if (mysql_errno($sql)!=0) // failed to select DB
+ {
+ if ($timeout>0) ini_set("mysql.timeout",$oldtimeout);
+ fnmysql_error(mysql_error($sql));
+ @mysql_close($sql);
+ return -2; // select database failed
+ }
+
+if ($query=="")
+ { // no query to perform
+ if ($timeout>0) ini_set("mysql.timeout",$oldtimeout);
+ @mysql_close($sql);
+ return 0; // all ok but no query/rows
+ }
+
+$r=@mysql_query($query,$sql);
+if (mysql_errno($sql)==0) // successful query
+ {
+ if (is_bool($r)) // didn't return any daya
+ {
+ $return=mysql_affected_rows($sql);
+ }
+ else
+ {
+ $return=mysql_num_rows($r);
+ @mysql_free_result($r,$sql); // free if a result
+ }
+ }
+else
+ {
+ fnmysql_error(mysql_error($sql));
+ $return=-3; // query failed
+ }
+
+@mysql_close($sql);
+if ($timeout>0) ini_set("mysql.timeout",$oldtimeout);
+return $return;
+}
+
+function mysql_test_time($host,$user,$pass,$database="",$timeout=0,$query="",$debug=false)
+{
+$timer=new TFNTimer();
+$timer->Start();
+$val=mysql_test_rows($host,$user,$pass,$database,$timeout,$query,$debug);
+$time=$timer->Stop();
+
+if ($val<0) return $val; // connect/select/query failed
+
+// if $val is 0 then nothing was returned - maybe check the query here? Complicates the idea
+// though for the user so left. Will have to do two tests for both time and rows 0 as fails
+
+$time=round($time,4);
+if ($time==0) return "0.0001";
+return $time;
+}
+
+
+if (isset($NATS))
+{
+class FreeNATS_MySQL_Test extends FreeNATS_Local_Test
+ {
+ function DoTest($testname,$param,$hostname,$timeout,$params)
+ { // 0: host, 1: user, 2: pass, 3: database, 4: query
+
+ if ($testname=="mysql")
+ {
+ $ip=ip_lookup($param);
+ if ($ip=="0") return -1; // cache only as 127.0.0.1 is not the same connection as localhost for MySQL auth!
+
+ return mysql_test_time($param,$params[1],$params[2],$params[3],$timeout,$params[4]);
+ }
+
+ else if ($testname=="mysqlrows")
+ {
+ $ip=ip_lookup($param);
+ if ($ip=="0") return -1; // cache only - see above
+ return mysql_test_rows($param,$params[1],$params[2],$params[3],$timeout,$params[4]);
+ }
+
+ else if ($testname=="mysqldata")
+ {
+ $ip=ip_lookup($param);
+ if ($ip=="0") return -1;
+ return mysql_test_data($param,$params[1],$params[2],$params[3],$timeout,$params[4],$params[5]);
+ }
+
+ else return -1;
+
+ }
+ function Evaluate($result)
+ { // same for all types
+ if ($result<0) return 2; // failed
+ return 0; // passed
+ }
+
+ function ProtectOutput(&$test)
+ {
+ $test['testparam2']="";
+ }
+
+ function DisplayForm(&$row)
+ {
+ $optional=true;
+ if ($row['testtype']=="mysqldata") $optional=false;
+ echo "
";
+ echo "
";
+ echo "Hostname :";
+ echo "
";
+ echo "";
+ echo "
";
+ echo "
";
+ echo "Username :";
+ echo "
";
+ echo "";
+ echo "
";
+ echo "
";
+ echo "Password :";
+ echo "
";
+ echo "";
+ echo "";
+ echo "
";
+ echo "
Leave blank to not change or click to clear
";
+ echo "
";
+ echo "Database :";
+ echo "
";
+ echo "";
+ echo "
";
+ if ($optional) echo "
Optional - leave blank to not bother with select_db
";
+ echo "
";
+ echo "Query :";
+ echo "
";
+ echo "";
+ echo "
";
+ if ($optional) echo "
Optional - leave blank to not bother with a query
";
+ if ($row['testtype']=="mysqldata")
+ {
+ echo "
";
+ echo "Column :";
+ echo "
";
+ echo "";
+ echo "
";
+ echo "
Which field (0 is first and the default) of the first record to use
";
+ }
+ echo "
";
+ }
+
+ }
+$params=array();
+$NATS->Tests->Register("mysql","FreeNATS_MySQL_Test",$params,"MySQL Connect",2,"FreeNATS MySQL Tester");
+$NATS->Tests->SetUnits("mysql","Seconds","s");
+$NATS->Tests->Register("mysqlrows","FreeNATS_MySQL_Test",$params,"MySQL Rows",2,"FreeNATS MySQL Tester");
+$NATS->Tests->SetUnits("mysqlrows","Rows","rows");
+$NATS->Tests->Register("mysqldata","FreeNATS_MySQL_Test",$params,"MySQL Data",2,"FreeNATS MySQL Tester");
+}
+
+
+?>
\ No newline at end of file
diff --git a/src/server/base/tests/nats-dns.inc.php b/src/server/base/tests/nats-dns.inc.php
new file mode 100755
index 0000000..c1c88ad
--- /dev/null
+++ b/src/server/base/tests/nats-dns.inc.php
@@ -0,0 +1,114 @@
+Start();
+ $answer=$dns_query->Query($query,$type);
+ $elapsedTime=$timer->Stop();
+
+ if ( ($answer===false) || ($dns_query->error) ) return -2; // query error
+ if ($answer->count<=0) return -1; // no records returned
+
+ // otherwise we've got some results ok
+ $elapsedTime=round($elapsedTime,4);
+ if ($elapsedTime<=0) return 0.0001;
+ return $elapsedTime;
+ break;
+ }
+ function Evaluate($result)
+ {
+ if ($result<0) return 2; // failed
+ return 0; // passed
+ }
+ function DisplayForm(&$row)
+ {
+ echo "
";
+ $out.=" ";
+ $out.=" ";
+ $out.="";
+ $out.=" String(s) to search for - all defined must be found for the test to pass ";
+ $out.="Blank strings are ignored.";
+ $out.="
";
+ $out.="
No Strings :
";
+ $out.="
";
+ $out.=" ";
+ $out.=" ";
+ $out.="";
+ $out.=" String(s) to NOT find - fails if any are present Leave blank to not use this portion of the test";
+ $out.="
";
+
+ $out.="
Username :
";
+ $out.="
";
+ $out.="";
+ $out.=" Specify to use HTTP-AUTH on the URL";
+ $out.="
";
+
+ $out.="
Password :
";
+ $out.="
";
+ $out.=""; // dont display it
+ $out.=""; // don't update testparam3 (if blank)
+ $out.=" Enter a new password to set or... ";
+ $out.=" "; // clears testparam3 if set
+ $out.="clear it";
+ $out.="
";
+ echo $out; // output the buffer
+ }
+}
+
+// Now we have defined the class we must register it with FreeNATS
+
+$params=array(); // blank parameters array as we have implemented DisplayForm above
+
+$NATS->Tests->Register(
+ "advpagecheck", // the internal simple test name (must not conflict with anything else)
+ "Advanced_Pagecheck_Test", // the class name (above)
+ $params, // parameters (blank for now)
+ "Web Content Test", // the display name of the test in the interface
+ 3, // the revision number of the test
+ "Advanced Page Checker"); // extended description for the test module used in overview
+
+?>
diff --git a/src/server/extras/tests/dynamic_dns_test.php b/src/server/extras/tests/dynamic_dns_test.php
new file mode 100755
index 0000000..865007a
--- /dev/null
+++ b/src/server/extras/tests/dynamic_dns_test.php
@@ -0,0 +1,160 @@
+0) return 0; // FreeNATS passed (0) flag if > 0
+ return 2; // FreeNATS failed (2) flag ( <= 0 )
+ }
+
+ function ProtectOutput(&$test)
+ {
+ $test['testparam3']=""; // blank password for output
+ return true;
+ }
+
+ function DisplayForm(&$test)
+ {
+ $out="";
+ $out.="
";
+ $out.="
Hostname:
";
+ $out.="
";
+ $out.="";
+ $out.=" Dynamic DNS Hostname to Check (i.e. myhost.dyndns.org)";
+ $out.="
";
+ $out.="
IP:
";
+ $out.="
";
+ $out.=" Use xml.purplepixie.org IP Address Service ";
+ $out.=" URL: ";
+ $out.="This setting tells FreeNATS where to get your external IP from. You can either use ";
+ $out.="the PurplePixie XML App gateway or put in your own URL. The URL must return a plain IP.";
+ $out.="
";
+ $out.="
";
+ echo $out; // output the buffer
+ }
+}
+
+// Now we have defined the class we must register it with FreeNATS
+
+$params=array(); // blank parameters array as we have implemented DisplayForm above
+
+$NATS->Tests->Register(
+ "dynamicdns", // the internal simple test name (must not conflict with anything else)
+ "Dynamic_DNS_Test", // the class name (above)
+ $params, // parameters (blank for now)
+ "Dynamic DNS Test", // the display name of the test in the interface
+ 1, // the revision number of the test
+ "Check Dyanamic DNS Host Against External IP"); // extended description for the test module used in overview
+
+?>
diff --git a/src/server/test/.htaccess b/src/server/test/.htaccess
new file mode 100755
index 0000000..ff2beb8
--- /dev/null
+++ b/src/server/test/.htaccess
@@ -0,0 +1,2 @@
+order deny,allow
+deny from all
diff --git a/src/server/test/curl.sh b/src/server/test/curl.sh
new file mode 100755
index 0000000..87581cd
--- /dev/null
+++ b/src/server/test/curl.sh
@@ -0,0 +1,65 @@
+#!/usr/bin/php -q
+Start();
+passthru($cmd);
+$curl=$timer->Stop();
+echo "\n";
+echo "FN Timer : ".$curl." (".($curl*1000)." ms)\n\n";
+
+$timer->Start();
+$wtime=DoTest("wtime",$argv[1]);
+$wtimer=$timer->Stop();
+echo "WTime : ".$wtime."\n";
+echo "Timer : ".$wtimer."\n";
+echo "\n";
+
+
+$timer->Start();
+$ch=curl_init();
+curl_setopt($ch,CURLOPT_URL,$argv[1]);
+curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
+curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,0);
+curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,0);
+if (!$output=curl_exec($ch))
+ {
+ echo "CURL Error\n";
+ $size=0;
+ }
+else $size=curl_getinfo($ch,CURLINFO_SIZE_DOWNLOAD);
+curl_close($ch);
+$curltime=$timer->Stop();
+
+echo "PHP CURL : ".$curltime."\n";
+echo "Size : ".$size."\n";
+echo "\n";
+
+$timer->Start();
+$fp=fopen($argv[1],"r")
+ or die("fopen failed");
+$fopen=$timer->Stop();
+while (!feof($fp))
+ {
+ $s=fgets($fp,1024);
+ }
+$fgets=$timer->Stop();
+fclose($fp);
+
+echo "fopen : ".$fopen."\n";
+echo "fopen Tot : ".$fgets."\n";
+echo "\n";
+
+?>
diff --git a/src/server/test/curl.txt b/src/server/test/curl.txt
new file mode 100755
index 0000000..79f867a
--- /dev/null
+++ b/src/server/test/curl.txt
@@ -0,0 +1,791 @@
+
+
+
+
+
+Welcome to Demon.net
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Utilise the enhanced speeds and lower contention ratios offered as part of our business broadband range.
+
+
+
+ Special offer available
+ From £34.00 a month exc VAT
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Home/HomeOffice Broadband
+
+
+
+ Our Home/HomeOffice products now support speeds of up to 8Mbps. They are tailored to meet the needs of both small businesses and professionals working from home.
+
+
+ Free set up and router
+ From £17.99 a month inc VAT
+
+
+
+
+
+
+
+
+
+
+
+
+
Help and Support
+
+
+
+
+
+Visit our support pages to get your questions answered
+and your problems solved. Whatever your enquiry, there will be an FAQ or tutorial to help.
+Win an iPod!
+Your feedback is important to us. Please spare a few minutes to fill in our customer satisfaction survey so that we can continue to improve our service to you.
+