Strabon

changeset 1335:2c2e2b77c225 MonetDB

Merging with default branch
author Kostis Kyzirakos <kostis@cwi.nl>
date Fri May 02 17:39:27 2014 +0200 (2014-05-02)
parents c928e602a509 8248e96ae606
children 9ea15e4a930c
files .hgtags endpoint/WebContent/teleios-header.html endpoint/pom.xml evaluation/pom.xml evaluation/src/main/java/org/openrdf/query/algebra/evaluation/function/spatial/GeoConstants.java evaluation/src/main/java/org/openrdf/query/algebra/evaluation/function/spatial/stsparql/relation/AnyInteractFunc.java evaluation/src/main/java/org/openrdf/query/algebra/evaluation/function/spatial/stsparql/relation/CoveredByFunc.java evaluation/src/main/java/org/openrdf/query/algebra/evaluation/function/spatial/stsparql/relation/CoversFunc.java evaluation/src/main/java/org/openrdf/query/algebra/evaluation/function/spatial/stsparql/relation/InsideFunc.java evaluation/src/main/java/org/openrdf/query/algebra/evaluation/function/spatial/stsparql/relation/OverlapFunc.java evaluation/src/main/java/org/openrdf/query/algebra/evaluation/function/spatial/stsparql/relation/TouchFunc.java generaldb/pom.xml generaldb/src/main/java/org/openrdf/sail/generaldb/algebra/GeneralDBSqlAnyInteract.java generaldb/src/main/java/org/openrdf/sail/generaldb/algebra/GeneralDBSqlCoveredBy.java generaldb/src/main/java/org/openrdf/sail/generaldb/algebra/GeneralDBSqlCovers.java generaldb/src/main/java/org/openrdf/sail/generaldb/algebra/GeneralDBSqlInside.java generaldb/src/main/java/org/openrdf/sail/generaldb/algebra/GeneralDBSqlOverlap.java generaldb/src/main/java/org/openrdf/sail/generaldb/algebra/GeneralDBSqlTouch.java generaldb/src/main/java/org/openrdf/sail/generaldb/managers/TransTableManager.java generaldb/src/main/java/org/openrdf/sail/generaldb/managers/TripleTableManager.java monetdb/pom.xml pom.xml postgis/pom.xml resultio-spatial/pom.xml resultio/pom.xml resultio/src/main/java/org/openrdf/query/resultio/Format.java resultio/src/main/java/org/openrdf/query/resultio/sparqlgeojson/stSPARQLResultsGeoJSONWriter.java resultio/src/main/java/org/openrdf/query/resultio/sparqlgeojson/stSPARQLResultsGeoJSONWriterFactory.java resultio/src/main/java/org/openrdf/query/resultio/sparqlhtml/stSPARQLResultsHTMLWriter.java resultio/src/main/java/org/openrdf/query/resultio/sparqlhtml/stSPARQLResultsHTMLWriterFactory.java resultio/src/main/java/org/openrdf/query/resultio/sparqlkml/stSPARQLResultsKMLWriter.java resultio/src/main/java/org/openrdf/query/resultio/sparqlkml/stSPARQLResultsKMLWriterFactory.java resultio/src/main/java/org/openrdf/query/resultio/sparqlkml/stSPARQLResultsKMZWriter.java resultio/src/main/java/org/openrdf/query/resultio/sparqlkml/stSPARQLResultsKMZWriterFactory.java resultio/src/main/java/org/openrdf/query/resultio/sparqlxml/stSPARQLResultsXMLWriter.java resultio/src/main/java/org/openrdf/query/resultio/sparqlxml/stSPARQLResultsXMLWriterFactory.java resultio/src/main/java/org/openrdf/query/resultio/sparqlxml/stSPARQLXMLWriter.java resultio/src/main/java/org/openrdf/query/resultio/stSPARQLQueryResultFormat.java resultio/src/main/java/org/openrdf/query/resultio/stSPARQLQueryResultWriterFactory.java resultio/src/main/java/org/openrdf/query/resultio/text/stSPARQLResultsTSVWriter.java resultio/src/main/java/org/openrdf/query/resultio/text/stSPARQLResultsTSVWriterFactory.java runtime/pom.xml runtime/src/main/java/eu/earthobservatory/runtime/postgis/testCRS.java scripts/v2.1/DeleteInSea.sparql scripts/v2.1/Refine.sparql scripts/v2.1/TimePersistence.sparql scripts/v2.1/count.sparql scripts/v2.1/discover.sparql scripts/v2.1/endpoint scripts/v2.1/runNoaRefinementChain.sh scripts/v2.1/runNoaRefinementChain.sh-bakcup scripts/v2.2/count.sparql scripts/v2.2/deleteSeaHotspots.sparql scripts/v2.2/discover.sparql scripts/v2.2/insertMunicipalities.sparql scripts/v2.2/landUseInvalidForFires.sparql scripts/v2.2/refinePartialSeaHotspots.sparql scripts/v2.2/refineTimePersistence.sparql scripts/v2.2/runNoaRefinementChain-papos.sh scripts/v2.2/runNoaRefinementChain.sh scripts/v2.3/count.sparql scripts/v2.3/deleteSeaHotspots.sparql scripts/v2.3/discover.sparql scripts/v2.3/insertMunicipalities.sparql scripts/v2.3/landUseInvalidForFires.sparql scripts/v2.3/refinePartialSeaHotspots.sparql scripts/v2.3/refineTimePersistence.sparql scripts/v2.3/runNoaRefinementChain-papos.sh scripts/v2.3/runNoaRefinementChain.sh scripts/v2/DeleteInSea.sparql scripts/v2/Refine.sparql scripts/v2/TimePersistence.sparql scripts/v2/chain.log scripts/v2/count.sparql scripts/v2/discover.sparql scripts/v2/endpoint scripts/v2/runNoaRefinementChain.sh scripts/v2/runNoaRefinementChain.sh-bakcup scripts/v2/runNoaRefinementChain.sh~ scripts/v3/DeleteInSea.sparql scripts/v3/DeleteInSea.sparql~ scripts/v3/Refine.sparql scripts/v3/TimePersistence.sparql scripts/v3/ValidateInLand.sparql scripts/v3/ValidateInLand.sparql~ scripts/v3/chain.log scripts/v3/runNoaRefinementChain.sh scripts/v3/runNoaRefinementChain.sh~
line diff
     1.1 --- a/.hgignore	Fri May 02 17:27:46 2014 +0200
     1.2 +++ b/.hgignore	Fri May 02 17:39:27 2014 +0200
     1.3 @@ -1,4 +1,5 @@
     1.4  /target$
     1.5 +target$
     1.6  \.project$
     1.7  \.settings$
     1.8  \.classpath$
     1.9 @@ -11,3 +12,5 @@
    1.10  stdout\.txt
    1.11  stderr\.log
    1.12  stdout\.log
    1.13 +endpoint-client/dependency-reduced-pom\.xml
    1.14 +WEB-INF/faces-config.xml
     2.1 --- a/.hgtags	Fri May 02 17:27:46 2014 +0200
     2.2 +++ b/.hgtags	Fri May 02 17:39:27 2014 +0200
     2.3 @@ -9,3 +9,13 @@
     2.4  30b26e89d0850f73d51aafb6e7450962e0bd64b8 v3.1.9
     2.5  f98df7d45ce21e527813cfe46d60308ca68a228b v3.2.1
     2.6  cba4fb36f4a6dade24b4e50509856e4df79be0fb v3.2.2-MonetDB
     2.7 +8378166a566968b5ba00683384605f6232ef0aaa v3.2.2
     2.8 +331163be068281f22f61b79b31484eb0f4cfc564 v3.2.3
     2.9 +66fbe30eb2e9dcd5c36bf29336efcb1bd3ce45fb v3.2.4
    2.10 +73521cf81d1383a7fd885de46ffd7ed6e844851b Teleios_System_v1-1-1
    2.11 +331163be068281f22f61b79b31484eb0f4cfc564 Teleios_System_v1-1-1
    2.12 +7089b2d52c7f36b40301063efc73476a093f2134 v3.2.5
    2.13 +97afadc6d589b318924ca774659418c055fdf3a0 v3.2.6
    2.14 +b3e0d7415823df2e814aa6fa45aa13374a81e706 v3.2.7
    2.15 +389213ce7843a9c490be447400c1a5c46d44cc96 v3.2.8
    2.16 +92b90ac06d39f8fcf76de046f22bb64526d5ff28 v3.2.9
     3.1 --- a/AUTHORS	Fri May 02 17:27:46 2014 +0200
     3.2 +++ b/AUTHORS	Fri May 02 17:39:27 2014 +0200
     3.3 @@ -3,3 +3,7 @@
     3.4  Manolis Koubarakis	<koubarak@di.uoa.gr>
     3.5  Giorgos Garbis		<ggarbis@di.uoa.gr>
     3.6  Konstantina Bereta	<konstantina.bereta@di.uoa.gr>
     3.7 +Charalampos Nikolaou	<charnik@di.uoa.gr>
     3.8 +Stella Gianakopoulou	<sgian@di.uoa.gr>
     3.9 +Panagiotis Smeros	<psmeros@di.uoa.gr>
    3.10 +Kallirroi Dogani	<kallirroi@di.uoa.gr>
     4.1 --- a/COPYING	Fri May 02 17:27:46 2014 +0200
     4.2 +++ b/COPYING	Fri May 02 17:39:27 2014 +0200
     4.3 @@ -0,0 +1,373 @@
     4.4 +Mozilla Public License Version 2.0
     4.5 +==================================
     4.6 +
     4.7 +1. Definitions
     4.8 +--------------
     4.9 +
    4.10 +1.1. "Contributor"
    4.11 +    means each individual or legal entity that creates, contributes to
    4.12 +    the creation of, or owns Covered Software.
    4.13 +
    4.14 +1.2. "Contributor Version"
    4.15 +    means the combination of the Contributions of others (if any) used
    4.16 +    by a Contributor and that particular Contributor's Contribution.
    4.17 +
    4.18 +1.3. "Contribution"
    4.19 +    means Covered Software of a particular Contributor.
    4.20 +
    4.21 +1.4. "Covered Software"
    4.22 +    means Source Code Form to which the initial Contributor has attached
    4.23 +    the notice in Exhibit A, the Executable Form of such Source Code
    4.24 +    Form, and Modifications of such Source Code Form, in each case
    4.25 +    including portions thereof.
    4.26 +
    4.27 +1.5. "Incompatible With Secondary Licenses"
    4.28 +    means
    4.29 +
    4.30 +    (a) that the initial Contributor has attached the notice described
    4.31 +        in Exhibit B to the Covered Software; or
    4.32 +
    4.33 +    (b) that the Covered Software was made available under the terms of
    4.34 +        version 1.1 or earlier of the License, but not also under the
    4.35 +        terms of a Secondary License.
    4.36 +
    4.37 +1.6. "Executable Form"
    4.38 +    means any form of the work other than Source Code Form.
    4.39 +
    4.40 +1.7. "Larger Work"
    4.41 +    means a work that combines Covered Software with other material, in 
    4.42 +    a separate file or files, that is not Covered Software.
    4.43 +
    4.44 +1.8. "License"
    4.45 +    means this document.
    4.46 +
    4.47 +1.9. "Licensable"
    4.48 +    means having the right to grant, to the maximum extent possible,
    4.49 +    whether at the time of the initial grant or subsequently, any and
    4.50 +    all of the rights conveyed by this License.
    4.51 +
    4.52 +1.10. "Modifications"
    4.53 +    means any of the following:
    4.54 +
    4.55 +    (a) any file in Source Code Form that results from an addition to,
    4.56 +        deletion from, or modification of the contents of Covered
    4.57 +        Software; or
    4.58 +
    4.59 +    (b) any new file in Source Code Form that contains any Covered
    4.60 +        Software.
    4.61 +
    4.62 +1.11. "Patent Claims" of a Contributor
    4.63 +    means any patent claim(s), including without limitation, method,
    4.64 +    process, and apparatus claims, in any patent Licensable by such
    4.65 +    Contributor that would be infringed, but for the grant of the
    4.66 +    License, by the making, using, selling, offering for sale, having
    4.67 +    made, import, or transfer of either its Contributions or its
    4.68 +    Contributor Version.
    4.69 +
    4.70 +1.12. "Secondary License"
    4.71 +    means either the GNU General Public License, Version 2.0, the GNU
    4.72 +    Lesser General Public License, Version 2.1, the GNU Affero General
    4.73 +    Public License, Version 3.0, or any later versions of those
    4.74 +    licenses.
    4.75 +
    4.76 +1.13. "Source Code Form"
    4.77 +    means the form of the work preferred for making modifications.
    4.78 +
    4.79 +1.14. "You" (or "Your")
    4.80 +    means an individual or a legal entity exercising rights under this
    4.81 +    License. For legal entities, "You" includes any entity that
    4.82 +    controls, is controlled by, or is under common control with You. For
    4.83 +    purposes of this definition, "control" means (a) the power, direct
    4.84 +    or indirect, to cause the direction or management of such entity,
    4.85 +    whether by contract or otherwise, or (b) ownership of more than
    4.86 +    fifty percent (50%) of the outstanding shares or beneficial
    4.87 +    ownership of such entity.
    4.88 +
    4.89 +2. License Grants and Conditions
    4.90 +--------------------------------
    4.91 +
    4.92 +2.1. Grants
    4.93 +
    4.94 +Each Contributor hereby grants You a world-wide, royalty-free,
    4.95 +non-exclusive license:
    4.96 +
    4.97 +(a) under intellectual property rights (other than patent or trademark)
    4.98 +    Licensable by such Contributor to use, reproduce, make available,
    4.99 +    modify, display, perform, distribute, and otherwise exploit its
   4.100 +    Contributions, either on an unmodified basis, with Modifications, or
   4.101 +    as part of a Larger Work; and
   4.102 +
   4.103 +(b) under Patent Claims of such Contributor to make, use, sell, offer
   4.104 +    for sale, have made, import, and otherwise transfer either its
   4.105 +    Contributions or its Contributor Version.
   4.106 +
   4.107 +2.2. Effective Date
   4.108 +
   4.109 +The licenses granted in Section 2.1 with respect to any Contribution
   4.110 +become effective for each Contribution on the date the Contributor first
   4.111 +distributes such Contribution.
   4.112 +
   4.113 +2.3. Limitations on Grant Scope
   4.114 +
   4.115 +The licenses granted in this Section 2 are the only rights granted under
   4.116 +this License. No additional rights or licenses will be implied from the
   4.117 +distribution or licensing of Covered Software under this License.
   4.118 +Notwithstanding Section 2.1(b) above, no patent license is granted by a
   4.119 +Contributor:
   4.120 +
   4.121 +(a) for any code that a Contributor has removed from Covered Software;
   4.122 +    or
   4.123 +
   4.124 +(b) for infringements caused by: (i) Your and any other third party's
   4.125 +    modifications of Covered Software, or (ii) the combination of its
   4.126 +    Contributions with other software (except as part of its Contributor
   4.127 +    Version); or
   4.128 +
   4.129 +(c) under Patent Claims infringed by Covered Software in the absence of
   4.130 +    its Contributions.
   4.131 +
   4.132 +This License does not grant any rights in the trademarks, service marks,
   4.133 +or logos of any Contributor (except as may be necessary to comply with
   4.134 +the notice requirements in Section 3.4).
   4.135 +
   4.136 +2.4. Subsequent Licenses
   4.137 +
   4.138 +No Contributor makes additional grants as a result of Your choice to
   4.139 +distribute the Covered Software under a subsequent version of this
   4.140 +License (see Section 10.2) or under the terms of a Secondary License (if
   4.141 +permitted under the terms of Section 3.3).
   4.142 +
   4.143 +2.5. Representation
   4.144 +
   4.145 +Each Contributor represents that the Contributor believes its
   4.146 +Contributions are its original creation(s) or it has sufficient rights
   4.147 +to grant the rights to its Contributions conveyed by this License.
   4.148 +
   4.149 +2.6. Fair Use
   4.150 +
   4.151 +This License is not intended to limit any rights You have under
   4.152 +applicable copyright doctrines of fair use, fair dealing, or other
   4.153 +equivalents.
   4.154 +
   4.155 +2.7. Conditions
   4.156 +
   4.157 +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
   4.158 +in Section 2.1.
   4.159 +
   4.160 +3. Responsibilities
   4.161 +-------------------
   4.162 +
   4.163 +3.1. Distribution of Source Form
   4.164 +
   4.165 +All distribution of Covered Software in Source Code Form, including any
   4.166 +Modifications that You create or to which You contribute, must be under
   4.167 +the terms of this License. You must inform recipients that the Source
   4.168 +Code Form of the Covered Software is governed by the terms of this
   4.169 +License, and how they can obtain a copy of this License. You may not
   4.170 +attempt to alter or restrict the recipients' rights in the Source Code
   4.171 +Form.
   4.172 +
   4.173 +3.2. Distribution of Executable Form
   4.174 +
   4.175 +If You distribute Covered Software in Executable Form then:
   4.176 +
   4.177 +(a) such Covered Software must also be made available in Source Code
   4.178 +    Form, as described in Section 3.1, and You must inform recipients of
   4.179 +    the Executable Form how they can obtain a copy of such Source Code
   4.180 +    Form by reasonable means in a timely manner, at a charge no more
   4.181 +    than the cost of distribution to the recipient; and
   4.182 +
   4.183 +(b) You may distribute such Executable Form under the terms of this
   4.184 +    License, or sublicense it under different terms, provided that the
   4.185 +    license for the Executable Form does not attempt to limit or alter
   4.186 +    the recipients' rights in the Source Code Form under this License.
   4.187 +
   4.188 +3.3. Distribution of a Larger Work
   4.189 +
   4.190 +You may create and distribute a Larger Work under terms of Your choice,
   4.191 +provided that You also comply with the requirements of this License for
   4.192 +the Covered Software. If the Larger Work is a combination of Covered
   4.193 +Software with a work governed by one or more Secondary Licenses, and the
   4.194 +Covered Software is not Incompatible With Secondary Licenses, this
   4.195 +License permits You to additionally distribute such Covered Software
   4.196 +under the terms of such Secondary License(s), so that the recipient of
   4.197 +the Larger Work may, at their option, further distribute the Covered
   4.198 +Software under the terms of either this License or such Secondary
   4.199 +License(s).
   4.200 +
   4.201 +3.4. Notices
   4.202 +
   4.203 +You may not remove or alter the substance of any license notices
   4.204 +(including copyright notices, patent notices, disclaimers of warranty,
   4.205 +or limitations of liability) contained within the Source Code Form of
   4.206 +the Covered Software, except that You may alter any license notices to
   4.207 +the extent required to remedy known factual inaccuracies.
   4.208 +
   4.209 +3.5. Application of Additional Terms
   4.210 +
   4.211 +You may choose to offer, and to charge a fee for, warranty, support,
   4.212 +indemnity or liability obligations to one or more recipients of Covered
   4.213 +Software. However, You may do so only on Your own behalf, and not on
   4.214 +behalf of any Contributor. You must make it absolutely clear that any
   4.215 +such warranty, support, indemnity, or liability obligation is offered by
   4.216 +You alone, and You hereby agree to indemnify every Contributor for any
   4.217 +liability incurred by such Contributor as a result of warranty, support,
   4.218 +indemnity or liability terms You offer. You may include additional
   4.219 +disclaimers of warranty and limitations of liability specific to any
   4.220 +jurisdiction.
   4.221 +
   4.222 +4. Inability to Comply Due to Statute or Regulation
   4.223 +---------------------------------------------------
   4.224 +
   4.225 +If it is impossible for You to comply with any of the terms of this
   4.226 +License with respect to some or all of the Covered Software due to
   4.227 +statute, judicial order, or regulation then You must: (a) comply with
   4.228 +the terms of this License to the maximum extent possible; and (b)
   4.229 +describe the limitations and the code they affect. Such description must
   4.230 +be placed in a text file included with all distributions of the Covered
   4.231 +Software under this License. Except to the extent prohibited by statute
   4.232 +or regulation, such description must be sufficiently detailed for a
   4.233 +recipient of ordinary skill to be able to understand it.
   4.234 +
   4.235 +5. Termination
   4.236 +--------------
   4.237 +
   4.238 +5.1. The rights granted under this License will terminate automatically
   4.239 +if You fail to comply with any of its terms. However, if You become
   4.240 +compliant, then the rights granted under this License from a particular
   4.241 +Contributor are reinstated (a) provisionally, unless and until such
   4.242 +Contributor explicitly and finally terminates Your grants, and (b) on an
   4.243 +ongoing basis, if such Contributor fails to notify You of the
   4.244 +non-compliance by some reasonable means prior to 60 days after You have
   4.245 +come back into compliance. Moreover, Your grants from a particular
   4.246 +Contributor are reinstated on an ongoing basis if such Contributor
   4.247 +notifies You of the non-compliance by some reasonable means, this is the
   4.248 +first time You have received notice of non-compliance with this License
   4.249 +from such Contributor, and You become compliant prior to 30 days after
   4.250 +Your receipt of the notice.
   4.251 +
   4.252 +5.2. If You initiate litigation against any entity by asserting a patent
   4.253 +infringement claim (excluding declaratory judgment actions,
   4.254 +counter-claims, and cross-claims) alleging that a Contributor Version
   4.255 +directly or indirectly infringes any patent, then the rights granted to
   4.256 +You by any and all Contributors for the Covered Software under Section
   4.257 +2.1 of this License shall terminate.
   4.258 +
   4.259 +5.3. In the event of termination under Sections 5.1 or 5.2 above, all
   4.260 +end user license agreements (excluding distributors and resellers) which
   4.261 +have been validly granted by You or Your distributors under this License
   4.262 +prior to termination shall survive termination.
   4.263 +
   4.264 +************************************************************************
   4.265 +*                                                                      *
   4.266 +*  6. Disclaimer of Warranty                                           *
   4.267 +*  -------------------------                                           *
   4.268 +*                                                                      *
   4.269 +*  Covered Software is provided under this License on an "as is"       *
   4.270 +*  basis, without warranty of any kind, either expressed, implied, or  *
   4.271 +*  statutory, including, without limitation, warranties that the       *
   4.272 +*  Covered Software is free of defects, merchantable, fit for a        *
   4.273 +*  particular purpose or non-infringing. The entire risk as to the     *
   4.274 +*  quality and performance of the Covered Software is with You.        *
   4.275 +*  Should any Covered Software prove defective in any respect, You     *
   4.276 +*  (not any Contributor) assume the cost of any necessary servicing,   *
   4.277 +*  repair, or correction. This disclaimer of warranty constitutes an   *
   4.278 +*  essential part of this License. No use of any Covered Software is   *
   4.279 +*  authorized under this License except under this disclaimer.         *
   4.280 +*                                                                      *
   4.281 +************************************************************************
   4.282 +
   4.283 +************************************************************************
   4.284 +*                                                                      *
   4.285 +*  7. Limitation of Liability                                          *
   4.286 +*  --------------------------                                          *
   4.287 +*                                                                      *
   4.288 +*  Under no circumstances and under no legal theory, whether tort      *
   4.289 +*  (including negligence), contract, or otherwise, shall any           *
   4.290 +*  Contributor, or anyone who distributes Covered Software as          *
   4.291 +*  permitted above, be liable to You for any direct, indirect,         *
   4.292 +*  special, incidental, or consequential damages of any character      *
   4.293 +*  including, without limitation, damages for lost profits, loss of    *
   4.294 +*  goodwill, work stoppage, computer failure or malfunction, or any    *
   4.295 +*  and all other commercial damages or losses, even if such party      *
   4.296 +*  shall have been informed of the possibility of such damages. This   *
   4.297 +*  limitation of liability shall not apply to liability for death or   *
   4.298 +*  personal injury resulting from such party's negligence to the       *
   4.299 +*  extent applicable law prohibits such limitation. Some               *
   4.300 +*  jurisdictions do not allow the exclusion or limitation of           *
   4.301 +*  incidental or consequential damages, so this exclusion and          *
   4.302 +*  limitation may not apply to You.                                    *
   4.303 +*                                                                      *
   4.304 +************************************************************************
   4.305 +
   4.306 +8. Litigation
   4.307 +-------------
   4.308 +
   4.309 +Any litigation relating to this License may be brought only in the
   4.310 +courts of a jurisdiction where the defendant maintains its principal
   4.311 +place of business and such litigation shall be governed by laws of that
   4.312 +jurisdiction, without reference to its conflict-of-law provisions.
   4.313 +Nothing in this Section shall prevent a party's ability to bring
   4.314 +cross-claims or counter-claims.
   4.315 +
   4.316 +9. Miscellaneous
   4.317 +----------------
   4.318 +
   4.319 +This License represents the complete agreement concerning the subject
   4.320 +matter hereof. If any provision of this License is held to be
   4.321 +unenforceable, such provision shall be reformed only to the extent
   4.322 +necessary to make it enforceable. Any law or regulation which provides
   4.323 +that the language of a contract shall be construed against the drafter
   4.324 +shall not be used to construe this License against a Contributor.
   4.325 +
   4.326 +10. Versions of the License
   4.327 +---------------------------
   4.328 +
   4.329 +10.1. New Versions
   4.330 +
   4.331 +Mozilla Foundation is the license steward. Except as provided in Section
   4.332 +10.3, no one other than the license steward has the right to modify or
   4.333 +publish new versions of this License. Each version will be given a
   4.334 +distinguishing version number.
   4.335 +
   4.336 +10.2. Effect of New Versions
   4.337 +
   4.338 +You may distribute the Covered Software under the terms of the version
   4.339 +of the License under which You originally received the Covered Software,
   4.340 +or under the terms of any subsequent version published by the license
   4.341 +steward.
   4.342 +
   4.343 +10.3. Modified Versions
   4.344 +
   4.345 +If you create software not governed by this License, and you want to
   4.346 +create a new license for such software, you may create and use a
   4.347 +modified version of this License if you rename the license and remove
   4.348 +any references to the name of the license steward (except to note that
   4.349 +such modified license differs from this License).
   4.350 +
   4.351 +10.4. Distributing Source Code Form that is Incompatible With Secondary
   4.352 +Licenses
   4.353 +
   4.354 +If You choose to distribute Source Code Form that is Incompatible With
   4.355 +Secondary Licenses under the terms of this version of the License, the
   4.356 +notice described in Exhibit B of this License must be attached.
   4.357 +
   4.358 +Exhibit A - Source Code Form License Notice
   4.359 +-------------------------------------------
   4.360 +
   4.361 +  This Source Code Form is subject to the terms of the Mozilla Public
   4.362 +  License, v. 2.0. If a copy of the MPL was not distributed with this
   4.363 +  file, You can obtain one at http://mozilla.org/MPL/2.0/.
   4.364 +
   4.365 +If it is not possible or desirable to put the notice in a particular
   4.366 +file, then You may include the notice in a location (such as a LICENSE
   4.367 +file in a relevant directory) where a recipient would be likely to look
   4.368 +for such a notice.
   4.369 +
   4.370 +You may add additional accurate notices of copyright ownership.
   4.371 +
   4.372 +Exhibit B - "Incompatible With Secondary Licenses" Notice
   4.373 +---------------------------------------------------------
   4.374 +
   4.375 +  This Source Code Form is "Incompatible With Secondary Licenses", as
   4.376 +  defined by the Mozilla Public License, v. 2.0.
     5.1 --- a/ChangeLog	Fri May 02 17:27:46 2014 +0200
     5.2 +++ b/ChangeLog	Fri May 02 17:39:27 2014 +0200
     5.3 @@ -0,0 +1,224 @@
     5.4 +Sat Oct 19 23:37:23 2013   Pyravlos Team
     5.5 +
     5.6 +	* Version 3.2.9 released.
     5.7 +
     5.8 +	* Added support for the following google chart types: PieChart, 
     5.9 +	AreaChart and ColumnChart to strabon endpoint. 
    5.10 +	
    5.11 +	* Added Timemap as new results format in Strabon endpoint. This 
    5.12 +	option displays results in a map and a timeline on the same time, 
    5.13 +	using the Timemap js library (http://code.google.com/p/timemap/).
    5.14 +	The KMLWriter has been extended for that purpose, by transforming
    5.15 +	dateTime values that are included in the result set into the respective
    5.16 +	TimeStamp KML primitive (https://developers.google.com/kml/documentation/time). 
    5.17 +	In the "temporals" branch, the values of the strdf:period datatype 
    5.18 +	are converted into the respective KML TimeSpan primitive. 
    5.19 +	
    5.20 +	* Added extension function <http://postgis.net/ST_Centroid> which is
    5.21 +	mapped to the ST_Centroid(geometry) extension function of PostGIS.
    5.22 +	See also: <http://postgis.org/docs/ST_Centroid.html>.
    5.23 +
    5.24 +	* Added extension function <http://postgis.net/ST_MakeLine> which is
    5.25 +	mapped to the ST_MakeLine(geometry, geometry) extension function of
    5.26 +	PostGIS. See also: <http://postgis.org/docs/ST_MakeLine.html>.
    5.27 +
    5.28 +	* Added PostGIS vocabulary class.
    5.29 +
    5.30 +	* Added support of all SPARQL result types provided by Sesame (json,
    5.31 +	xml, csv, tsv, binary). To get the respective writer, just prepend the
    5.32 +	string "SPARQL/", e.g., "SPARQL/JSON". This is to ensure that we
    5.33 +	support all SPARQL result formats of the SPARQL Protocol.
    5.34 +
    5.35 +	* Fixed a bug where a non-implemented extension function would make
    5.36 +	Strabon throw a NULL pointer exception. Now we get away with it
    5.37 +	through a warning.
    5.38 +
    5.39 +	* Strabon endpoint now publishes the URIs of the supported units of
    5.40 +	measure for use in strdf:distance and geof:distance functions of
    5.41 +	stSPARQL and GeoSPARQL, respectively. The URIs are those defined by
    5.42 +	OGC Units of Measure 1.0 specification which may be found at
    5.43 +	http://www.opengis.net/def/uom/OGC/1.0/. Strabon endpoint publishes
    5.44 +	the URIs at http://localhost:8080/endpoint/Capabilities.
    5.45 +
    5.46 +	* Created new module with name 'vocab` and artifactId
    5.47 +	'strabon-vocabulary` and moved GeoConstants.java there. Other
    5.48 +	vocabularies have been added as well, such as Simple Features, and
    5.49 +	GeoSPARQL.
    5.50 +
    5.51 +	* Strabon endpoint now publishes the URIs of the supported extension
    5.52 +	functions for stSPARQL and GeoSPARQL. One should access them by
    5.53 +	hitting the link http://localhost:8080/endpoint/Capabilities.
    5.54 +
    5.55 +	* Support for parsing EPSG URIs in geometry literals with datatype
    5.56 +	geo:wktLiteral.
    5.57 +	(bug #33: http://bug.strabon.di.uoa.gr/ticket/33)
    5.58 +
    5.59 +	* Endpoint Client now supports querying of Virtuoso and Parliament endpoints.
    5.60 +
    5.61 +	* Endpoint Client now supports store and update operations, but only
    5.62 +	for Strabon Endpoints.
    5.63 +
    5.64 +	* GeoSPARQL functions sfCrosses, sfOverlaps, ehOverlaps do not use the 
    5.65 +	ST_Relate PostGIS function (bug #24: http://bug.strabon.di.uoa.gr/ticket/24)
    5.66 +
    5.67 +	* All Simple Features functions of GeoSPARQL do not use the ST_Relate 
    5.68 +	PostGIS function
    5.69 +
    5.70 +	* Added diffTime function. This function performs the difference 
    5.71 +	between two literals of xsd:time datatype and returns a literal of
    5.72 +	the xsd:time datatype as well.
    5.73 +	
    5.74 +	* Added a testsuite package in default branch. Full tester guide can be found
    5.75 +	in README. Among other, most of GeoSPARQL compliance tests  
    5.76 +	(https://portal.opengeospatial.org/files/?artifact_id=47664, pg. 53) have been 
    5.77 +	implemented.
    5.78 +
    5.79 +	* Changed the definition and implementation of strdf:distance function, by
    5.80 +	adopting the definition of GeoSPARQL.
    5.81 +	(bug #23: http://bug.strabon.di.uoa.gr/ticket/23) 
    5.82 +
    5.83 +	* Changed the definition and implementation of strdf:buffer function, by
    5.84 +        adopting the definition of GeoSPARQL.
    5.85 +        (bug #35: http://bug.strabon.di.uoa.gr/ticket/35)
    5.86 +
    5.87 +	* Added geof:distance and geof:buffer functions, which have the same definition
    5.88 +	with strdf:distance and strdf:buffer respectively.
    5.89 +	(bug #32: http://bug.strabon.di.uoa.gr/ticket/32)
    5.90 +
    5.91 +	* Added a download button when performing describe and construct queries at the
    5.92 +        endpoint.
    5.93 +        (bug #38: http://bug.strabon.di.uoa.gr/ticket/38)
    5.94 +
    5.95 +	* Fixed a bug, where XMLWriter and TSVWriter did not return geometries with the
    5.96 +	SRID.
    5.97 +	(bug #47: http://bug.strabon.di.uoa.gr/ticket/47)
    5.98 +
    5.99 +	* Fixed a bug where the GeoSPARQL construct functions did not return the datatype 
   5.100 +	geo:wktLiteral datatype but strdf:WKT.
   5.101 +
   5.102 +Tue Mar 26 13:28:26 2013   Pyravlos Team
   5.103 +
   5.104 +	* Version 3.2.8 released.
   5.105 +
   5.106 +	* Added support for handling (storing/querying) GeoSPARQL datatypes.
   5.107 +	(bug #31: http://bug.strabon.di.uoa.gr/ticket/31)
   5.108 +
   5.109 +	* Fixed a bug in StoreOp that wouldn't close the connection, neither
   5.110 +	rollback the transaction upon an exception. This had as a side effect
   5.111 +	the abnormal termination of StoreOp (through for example the use of
   5.112 +	Ctrl-C signal) which was leaving the database locked.
   5.113 +
   5.114 +	* Fixed bug where spatial aggregates (e.g., union) didn't work as
   5.115 +	expected when the query didn't contain a `GROUP BY' clause.
   5.116 +	(bug #22: http://bug.strabon.di.uoa.gr/ticket/22)
   5.117 +
   5.118 +	* Updated GeoSPARQL namespaces and fixed function names to comply with
   5.119 +	the GeoSPARQL specification.
   5.120 +	(bug #25: http://bug.strabon.di.uoa.gr/ticket/25)
   5.121 +
   5.122 +Wed Jan 09 18:06:41 2013   Pyravlos Team
   5.123 +
   5.124 +	* Version 3.2.7 released.
   5.125 +
   5.126 +	* Add an extension function 
   5.127 +	<http://strdf.di.uoa.gr/extensions/ontology#diffDateTime> for computing the
   5.128 +	span (in milliseconds) between two timestamps.
   5.129 +
   5.130 +	* Added an <endpoint-exec> module. This module builds an executable jar file 
   5.131 +	with an embedded Apache Tomcat 7. To create and run the executable jar just 
   5.132 +	type:
   5.133 +		$ mvn clean package
   5.134 +		$ java -jar endpoint-exec/target/strabon-endpoint-executable-*.jar
   5.135 +
   5.136 +	* Modified strabon script and postgis/monetdb.StoreOP class to get an
   5.137 +	option for storing a RDF file in a named graph. Moreover, the RDF
   5.138 +	format of the input RDF file now is given as an option (still, if it
   5.139 +	is missing, it is assumed that the input is in N-TRIPLES format). The
   5.140 +	option for the format is -f and the option for the named graph is -g
   5.141 +	(takes a URI as an argument).
   5.142 +
   5.143 +	* Modified the names of the stSPARQL extension functions that
   5.144 +	utilize the minimum bounding boxes of the involved geometries.
   5.145 +
   5.146 +Tue Dec 11 19:33:45 2012   Pyravlos Team
   5.147 +
   5.148 +	* Version 3.2.6 released.
   5.149 +
   5.150 +	* Modified the names of the stSPARQL extension functions to comply  
   5.151 +	with the OGC Simple Features Access standard.
   5.152 +
   5.153 +Tue Dec 11 00:11:43 2012   Pyravlos Team
   5.154 +
   5.155 +	* Version 3.2.5 released.
   5.156 +
   5.157 +	* Added support for querying temporal information. This functionality
   5.158 +	may be found in the `temporals' branch. 
   5.159 +	
   5.160 +		The datatypes <http://strdf.di.uoa.gr/ontology#period> and
   5.161 +		<http://www.w3.org/2001/XMLSchema#dateTime> are used to
   5.162 +		represent periods and instants respectively.
   5.163 +	
   5.164 +		The valid time time of triples is represented using quadtruples,
   5.165 +		with the valid time annotation(instant or period) being the
   5.166 +		fourth element of the quad. In the same way, temporal triple
   5.167 +		patterns are used in queries to retrieve the valid time of
   5.168 +		triples.
   5.169 +		
   5.170 +		Some functions have been renamed (their URIs have changed) to
   5.171 +		follow the names of the respective relations of Allen's
   5.172 +		interval algebra and other functions have been added. 
   5.173 +		
   5.174 +		The following temporal functions are supported:
   5.175 +		during, periodOverlaps, equalsPeriod, nequalsPeriod, adjacent,
   5.176 +		before, after, overleft, overright, meets, starts, finishes, 
   5.177 +		period_intersect, period_union, preceding_period, and
   5.178 +		succeeding_period.
   5.179 +	
   5.180 +	* Changed behaviour of Strabon and Strabon Endpoint for connecting to
   5.181 +	a spatially-enabled database. Only one instance of Strabon is allowed
   5.182 +	at a time.
   5.183 +
   5.184 +	* Implemented a Java client for Strabon Endpoint. The client should be
   5.185 +	used only with endpoint versions >=3.2.5. The implementation may be
   5.186 +	found int the `endpoint-client' submodule of maven. Currently, only
   5.187 +	querying of Strabon Endpoints is supported.
   5.188 +
   5.189 +	* Added support for requesting the capabilities of Strabon Endpoint
   5.190 +	(fixes Bug #20 <http://bug.strabon.di.uoa.gr/ticket/20>). See
   5.191 +	changesets f840796400bf and ?<TBC>? for specific details and how you
   5.192 +	can determine the capabilities of older endpoints (versions <= 3.2.4).
   5.193 +
   5.194 +	* Updated KML writer to include the projected variables of an stSPARQL
   5.195 +	query in "ExtendedData" and "Data" tags. This is the proper way to
   5.196 +	do it if we need to convert a KML to a ESRI shapefile and also include
   5.197 +	such information as attributes for a feature. See related pages from
   5.198 +	KML specification:
   5.199 +		<https://developers.google.com/kml/documentation/kmlreference#extendeddata>
   5.200 +		<https://developers.google.com/kml/documentation/extendeddata>
   5.201 +
   5.202 +	* Added user authentication for storing RDF data through Strabon
   5.203 +	Endpoint. The credentials are specified in
   5.204 +	WEB-INF/credentials.properties file.
   5.205 +
   5.206 +	* Strabon Endpoints now limits the number of the results to a maximum
   5.207 +	one. The maximum number is specified in the beans.xml file. This
   5.208 +	corresponds to parameter "maxLimit". The endpoint script has also been
   5.209 +	updated correspondingly; the limit can be given using the option "-l".
   5.210 +	One can disable limiting of query results, by setting the "maxLimit"
   5.211 +	parameter to 0. Addresses Bug #6
   5.212 +	(<http://bug.strabon.di.uoa.gr/ticket/6>).
   5.213 +
   5.214 +	* Added "Known Issues" section to README.
   5.215 +
   5.216 +	* Added -m (more memory) and -M (much more memory) options in strabon
   5.217 +	script for out-of-memory exceptions.
   5.218 +
   5.219 +	* Fixed Bug #10 (<http://bug.strabon.di.uoa.gr/ticket/10>). Now
   5.220 +	KMLWriter handles more geometric types (other than polygons). See
   5.221 +	changeset 9a3bfee64a39.
   5.222 +
   5.223 +	* Menu and navigation in Strabon Endpoint has changed to use jquery.
   5.224 +	The menu is now populated using the queries placed inside the beans.xml.
   5.225 +
   5.226 +	* Added BrowseBean and browse.jsp for browsing the RDF data using the
   5.227 +	Strabon Endpoint.
     6.1 --- a/README	Fri May 02 17:27:46 2014 +0200
     6.2 +++ b/README	Fri May 02 17:39:27 2014 +0200
     6.3 @@ -27,6 +27,22 @@
     6.4  Currently, only the geospatial features of stSPARQL have been implemented fully.
     6.5  The temporal features are the subject of current work.
     6.6  
     6.7 +Given the very close relationship between stSPARQL and GeoSPARQL which is a 
     6.8 +recent OGC standard for an extension of SPARQL for querying geospatial metadata,
     6.9 +we recently provided support for the Core, Geometry and Geometry Topology 
    6.10 +extension of GeoSPARQL. 
    6.11 +
    6.12 +
    6.13 +Conformance to GeoSPARQL
    6.14 +========================
    6.15 +Strabon implements the `Core', the `Topology Vocabulary Extension', the
    6.16 +`Geometry Extension', the `Geometry Topology Extension', and the `RDFS Entailment
    6.17 +Extension' except for Req. 25
    6.18 +(http://www.opengis.net/spec/geosparql/1.0/req/rdfs-entailment-extension/bgp-rdfs-ent).
    6.19 +
    6.20 +With respect to GML, Strabon supports the GML Profile corresponding to Simple
    6.21 +Features, that is, GML Simple Features Profile 2.0. 
    6.22 +
    6.23  
    6.24  Strabon Homepage
    6.25  ================
    6.26 @@ -38,6 +54,84 @@
    6.27  You can find a demo of the system Strabon at http://test.strabon.di.uoa.gr/NOA/.
    6.28  
    6.29  
    6.30 +How to build and run Strabon from command line
    6.31 +==============================================
    6.32 +Assuming you have already downloaded Strabon and you are in the top-level
    6.33 +directory of Strabon, issue the following command to build it from command line:
    6.34 +
    6.35 +	$ mvn clean package
    6.36 +
    6.37 +In order to run automatically the JUnit tests, pass the option `-DskipTests=false' 
    6.38 +to the above command. The complete command is the following:
    6.39 +
    6.40 +	$ mvn -DskipTests=false clean package
    6.41 +
    6.42 +In case of an error during building of Strabon and assuming that the error does
    6.43 +not come from the JUnit tests, please have a look at the `Known Issues' section
    6.44 +below. If none of the known issues of that section applies, please contact the
    6.45 +developers through the Strabon mailing-list or submit a corresponding bug
    6.46 +(see `Bugs' section below).
    6.47 +
    6.48 +After you have successfully built Strabon, you have access to the following
    6.49 +components:
    6.50 +
    6.51 +  * Strabon Endpoint
    6.52 +
    6.53 +    This is a SPARQL endpoint for Strabon. It is distributed as a war file so
    6.54 +    you may deploy it in a Tomcat container. You may find the war file under
    6.55 +    directory `endpoint/target'.
    6.56 +
    6.57 +  * Strabon Endpoint (standalone)
    6.58 +
    6.59 +    This is a SPARQL endpoint for Strabon like the above one, but it differs
    6.60 +    only in that it does not require the user to have already set up a Tomcat
    6.61 +    container. The standalone Strabon Endpoint may be run by issuing the
    6.62 +    following command:
    6.63 +
    6.64 +    	$ java -jar endpoint-exec/target/strabon-endpoint-executable-${version}.jar
    6.65 +
    6.66 +    After issuing the above command, you may access the Strabon Endpoint at
    6.67 +    the following URL: <http://localhost:8080/>.
    6.68 +
    6.69 +    Please see the page at <http://hg.strabon.di.uoa.gr/Strabon/rev/674f8f91162b>
    6.70 +    to find out other options that you may pass to the Tomcat container that
    6.71 +    will run by the above command.
    6.72 +
    6.73 +    SPECIAL NOTE: if you need to configure the connection details to the
    6.74 +    underlying database, you may do so in two ways:
    6.75 +      1. By modifying file `endpoint/WebContent/WEB-INF/connection.properties'
    6.76 +         before building Strabon and executing the above command.
    6.77 +      2. After executing the above command, by visiting the following page by a
    6.78 +         browser: <http://localhost:8080/ChangeConnection>
    6.79 +
    6.80 +  * Strabon Endpoint Client
    6.81 +
    6.82 +    This is a Java client for interacting with Strabon Endpoint or any other
    6.83 +    SPARQL endpoint. It is packaged as a jar file and may be found under
    6.84 +    directory `endpoint-client/target/' with name
    6.85 +    `strabon-endpoint-client-${version}.jar'. This jar contains any dependencies
    6.86 +    to other code, so may copy and paste it to your project and start playing
    6.87 +    with the code immediately.
    6.88 +
    6.89 +  * Strabon script
    6.90 +
    6.91 +    The `strabon' script is located under the `scripts/' directory and it is the
    6.92 +    main command-line tool for interacting with Strabon. You may use it to store
    6.93 +    RDF data with geospatial information or query/update it using one of
    6.94 +    stSPARQL or GeoSPARQL query languages.
    6.95 +
    6.96 +  * Endpoint script
    6.97 +
    6.98 +    The `endpoint' script is located under the `scripts' directory and it is the
    6.99 +    main command-line tool for interacting with a `Strabon Endpoint'. You may
   6.100 +    use it to do any operation you would like to do with the `strabon' script
   6.101 +    above, but in contrast to the `strabon' script you need to have access to a
   6.102 +    Strabon endpoint. Of course, the `Strabon Endpoint Client' component above
   6.103 +    can be used as well as a command-line tool. At the time of writing, the
   6.104 +    `Strabon Endpoint Client' component supports only querying of RDF data with
   6.105 +    geospatial information.
   6.106 +
   6.107 +
   6.108  Getting Started
   6.109  ===============
   6.110  To get started  with Strabon please have a look at the tutorial for the stRDF
   6.111 @@ -46,6 +140,14 @@
   6.112  stRDF and stSPARQL tutorial
   6.113  	http://www.strabon.di.uoa.gr/files/stSPARQL_tutorial.pdf
   6.114  
   6.115 +
   6.116 +stSPARQL Reference
   6.117 +~~~~~~~~~~~~~~~~~~
   6.118 +The reference for the spatial and temporal extension functions defined in 
   6.119 +stSPARQL can be found at http://www.strabon.di.uoa.gr/stSPARQL#spatial and
   6.120 +http://www.strabon.di.uoa.gr/stSPARQL#temporals respectively.
   6.121 +
   6.122 +
   6.123  User Guide
   6.124  ~~~~~~~~~~
   6.125  Assuming that you are familiar with Maven, the following steps need to be
   6.126 @@ -76,6 +178,114 @@
   6.127  You can see some examples in the classes gr.uoa.di.strabon.example.PostgisExample
   6.128  and gr.uoa.di.strabon.example.PostgisExample2.
   6.129  
   6.130 +	Tuning PostgreSQL
   6.131 +	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   6.132 +The default settings of Postgres are rather conservative. As a result, parameter 
   6.133 +tuning is neccessary for speeding up Postgres, therefore Strabon. If you are 
   6.134 +using Strabon to compare its performance against your implementation of 
   6.135 +stSPARQL/GeoSPARQL, you are *strongly* encouraged to contact us using the Strabon
   6.136 +Users mailing list for assistance on tuning Postgres.
   6.137 +
   6.138 +You can follow the instructions below for tuning a Postgres server running on an 
   6.139 +Ubuntu machine that is dedicated to PostgreSQL and Strabon.
   6.140 +
   6.141 +1. Append the following text at the end of postgresql.conf. 
   6.142 +*Uncomment* the appropriate lines.
   6.143 +
   6.144 +### RAM
   6.145 +## 4 GB of RAM
   6.146 +#shared_buffers       =  3GB
   6.147 +#effective_cache_size =  3GB
   6.148 +#maintenance_work_mem =  1GB
   6.149 +#work_mem             =  2GB
   6.150 +## 8 GB of RAM
   6.151 +#shared_buffers       =  5GB
   6.152 +#effective_cache_size =  6GB
   6.153 +#maintenance_work_mem =  2GB
   6.154 +#work_mem             =  5GB
   6.155 +## 16 GB of RAM
   6.156 +#shared_buffers       = 10GB
   6.157 +#effective_cache_size = 14GB
   6.158 +#maintenance_work_mem =  4GB
   6.159 +#work_mem             = 10GB
   6.160 +## 24 GB of RAM
   6.161 +#shared_buffers       = 16GB 
   6.162 +#effective_cache_size = 22GB 
   6.163 +#maintenance_work_mem =  6GB 
   6.164 +#work_mem             = 15GB
   6.165 +## 48 GB of RAM
   6.166 +#shared_buffers       = 32GB
   6.167 +#effective_cache_size = 46GB
   6.168 +#maintenance_work_mem =  8GB
   6.169 +#work_mem             = 30GB
   6.170 +## 64 GB of RAM
   6.171 +# contact us to find out!
   6.172 +### HD
   6.173 +## RAID with ordinary 7.200 disks
   6.174 +#random_page_cost = 3.5 #3.0-3.5
   6.175 +## High-End NAS/SAN
   6.176 +#random_page_cost = 2 #1.5-2.5
   6.177 +## Amazon EBS/Heroku
   6.178 +#random_page_cost = 1.3 #1.1-2.0
   6.179 +## SSD array
   6.180 +#random_page_cost = 2.0 #1.5-2.5
   6.181 +### Planner options
   6.182 +# Increase the following values in order to avoid using the GEQO planner. 
   6.183 +# Small values (<8) reduce planning time but may produce inferior query plans
   6.184 +# 
   6.185 +geqo_threshold = 15 # keep this value larger that the following two parameters
   6.186 +from_collapse_limit = 14
   6.187 +join_collapse_limit = 14
   6.188 +### Misc
   6.189 +default_statistics_target    = 10000 
   6.190 +constraint_exclusion         = on 
   6.191 +checkpoint_completion_target = 0.9 
   6.192 +wal_buffers                  = 32MB 
   6.193 +checkpoint_segments          = 64 
   6.194 +### Connections
   6.195 +max_connections              = 10
   6.196 +
   6.197 +2. Append the following lines at the end of /etc/sysctl.conf
   6.198 +*Uncomment* the appropriate lines.
   6.199 +
   6.200 +## 4 GB of RAM
   6.201 +#kernel.shmmax = 3758096384
   6.202 +#kernel.shmall = 3758096384
   6.203 +#kernel.shmmni = 4096
   6.204 +## 8 GB of RAM
   6.205 +#kernel.shmmax = 5905580032
   6.206 +#kernel.shmall = 5905580032
   6.207 +#kernel.shmmni = 4096
   6.208 +## 16 GB of RAM
   6.209 +#kernel.shmmax = 11274289152
   6.210 +#kernel.shmall = 11274289152
   6.211 +#kernel.shmmni = 4096
   6.212 +## 24 GB of RAM
   6.213 +#kernel.shmmax = 17716740096
   6.214 +#kernel.shmall = 17716740096
   6.215 +#kernel.shmmni = 4096
   6.216 +## 48 GB of RAM
   6.217 +#kernel.shmmax = 35433480192
   6.218 +#kernel.shmall = 35433480192
   6.219 +#kernel.shmmni = 4224
   6.220 +## 64 GB of RAM
   6.221 +# contact us to find out!
   6.222 +
   6.223 +3. Apply all changes by executing
   6.224 +
   6.225 +$ sudo sysctl -p
   6.226 +$ sudo /etc/init.d/postgresql restart
   6.227 +
   6.228 +4. Prepare for the next run by issuing the command 
   6.229 +
   6.230 +$ sudo -u postgres psql -c 'VACUUM ANALYZE;' db
   6.231 +
   6.232 +or 
   6.233 +
   6.234 +$ psql -c 'VACUUM ANALYZE;' db
   6.235 +
   6.236 +where db is the name of the Postgres database that Strabon will use.
   6.237 +
   6.238  
   6.239  Developer Guide
   6.240  ~~~~~~~~~~~~~~~
   6.241 @@ -102,8 +312,46 @@
   6.242     project, download any dependencies and build the project. 
   6.243  
   6.244  
   6.245 -	Storing stRDF graphs and evaluating stSPARQL queries
   6.246 -	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   6.247 +Tester Guide
   6.248 +~~~~~~~~~~~~
   6.249 +Assuming again that you are familiar with Maven and Junit these are the steps
   6.250 +you need to follow to test the functionality of Strabon:
   6.251 +
   6.252 +
   6.253 +* Using Eclipse
   6.254 +
   6.255 +	If you want to create a new test:
   6.256 +
   6.257 +	1. Import Strabon into Eclipse as explained in the Developer Guide.
   6.258 +	2. Go to strabon-testsuite project.
   6.259 +	3. Create a new folder (Recommended folder name: <test's name>) and place inside the following files:
   6.260 +		3.1. An ntriples or nquads file with the test dataset (with .nt or .nq extension).
   6.261 +		3.2. Pairs of files with sparql test queries and expected test results in xml format.
   6.262 +			 Notice that each pair must have the same name and .rq extension for the queryFile and .srx extension for the resultsFile.
   6.263 +	4. Create a test class that extends TemplateTest class.
   6.264 +	5. If you have followed the recommendations the test is ready. If you have different names or location for your
   6.265 +	files, insert them explicitly in the constructor of the class. WARNING: All prefixes must be placed in file "prefixes" so that
   6.266 +	every time a namespace changes, we have to change it just once.
   6.267 +	
   6.268 +	If you want to run a test:
   6.269 +	
   6.270 +	1. Right-click on the test class.
   6.271 +	2. Select "Run as JUnit Test".
   6.272 +	3. Database properties are retrieved from database.properties file. If you want, you can change a property
   6.273 +	"on the fly" with an environment variable.
   6.274 +
   6.275 +	
   6.276 +* Command Line
   6.277 +	
   6.278 +	If you want to run all the tests:
   6.279 +	
   6.280 +	1. Go to Strabon directory (root directory of all the subprojects).
   6.281 +	2. Run "mvn test -DskipTests=false".
   6.282 +	3. Optionally you can pass an environment variable with "-DvariableName=variableValue".
   6.283 +
   6.284 +
   6.285 +Storing stRDF graphs and evaluating stSPARQL queries
   6.286 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   6.287  You can see some examples in the classes
   6.288  eu.earthobservatory.runtime.postgis.StoreOp and
   6.289  eu.earthobservatory.runtime.postgis.QueryOp.
   6.290 @@ -125,6 +373,11 @@
   6.291  
   6.292  The current versions of stRDF and stSPARQL which are based on OGC standards are
   6.293  presented in the following document:
   6.294 +  * K. Kyzirakos, M. Karpathiotakis, and M. Koubarakis. Strabon: A Semantic 
   6.295 +    Geospatial DBMS. In Internatioanl Semantic Web Conference (ISWC'12). Boston,
   6.296 +    USA, November 11-15, 2012.
   6.297 +    [pdf: http://strabon.di.uoa.gr/files/strabon-iswc.pdf]
   6.298 +
   6.299    * Manolis Koubarakis, Kostis Kyzirakos, Babis Nikolaou, Michael Sioutis, and
   6.300      Stavros Vassos. A data model and query language for an extension of RDF with
   6.301      time and space. Deliverable D2.1, European ICT project TELEIOS, 2011.
   6.302 @@ -173,24 +426,42 @@
   6.303      Barcelona, Spain.
   6.304      [pdf: http://www.earthobservatory.eu/publications/SciQL_ADASS2011.pdf]
   6.305  
   6.306 +  * C. Nikolaou and M. Koubarakis: "Querying Linked Geospatial Data with
   6.307 +    Incomplete Information". In 5th International Terra Cognita Workshop - 
   6.308 +    Foundations, Technologies and Applications of the Geospatial Web. In
   6.309 +    conjunction with the 11th International Semantic Web Conference, Boston,
   6.310 +    USA, November, 2012.
   6.311 +    [http://www.earthobservatory.eu/publications/iswc-workshop.pdf]
   6.312 +
   6.313  
   6.314  Contributors
   6.315  ============
   6.316  The system Strabon has been developed by the following members of our team:
   6.317  
   6.318  * Manos Karpathiotakis	<mk@di.uoa.gr>
   6.319 -* Kostis Kyzirakos	<kkyzir@di.uoa.gr>
   6.320 +* Kostis Kyzirakos	<Kostis.Kyzirakos@cwi.nl>
   6.321  * Manolis Koubarakis	<koubarak@di.uoa.gr>
   6.322  * Giorgos Garbis	<ggarbis@di.uoa.gr>
   6.323  * Konstantina Bereta	<konstantina.bereta@di.uoa.gr>
   6.324 +* Charalampos Nikolaou	<charnik@di.uoa.gr>
   6.325 +* Stella Gianakopoulou	<sgian@di.uoa.gr>
   6.326 +* Panayiotis Smeros	<psmeros@di.uoa.gr>
   6.327 +* Kallirroi Dogani	<kallirroi@di.uoa.gr>
   6.328  
   6.329  
   6.330  Mailing-list
   6.331  ============
   6.332 -Currently, there is only a developers mailing-list, Strabon-devel, for support
   6.333 -and other questions concerning Strabon. To subscribe to the mailing-list, please
   6.334 -visit page http://cgi.di.uoa.gr/~mailman/listinfo/strabon-devel. To post e-mails
   6.335 -to Strabon-devel mailing-list, write to Strabon-devel@di.uoa.gr.
   6.336 +Currently, we maintain the following mailing lists:
   6.337 +
   6.338 +* Strabon-users, is used as a communication channel for Strabon users.
   6.339 +To subscribe to the mailing-list, please visit page 
   6.340 +http://cgi.di.uoa.gr/~mailman/listinfo/strabon-users. To post e-mails
   6.341 +to Strabon-users mailing-list, write to strabon-users@di.uoa.gr.
   6.342 +
   6.343 +* Strabon-devel, is used as a communication channel with the developers
   6.344 +of Strabon. To subscribe to the mailing-list, please visit page 
   6.345 +http://cgi.di.uoa.gr/~mailman/listinfo/strabon-devel. To post e-mails
   6.346 +to Strabon-devel mailing-list, write to strabon-devel@di.uoa.gr.
   6.347  
   6.348  
   6.349  Bugs
   6.350 @@ -199,6 +470,100 @@
   6.351  the Strabon-devel mailing-list Strabon-devel@di.uoa.gr.
   6.352  
   6.353  
   6.354 +Known Issues
   6.355 +============
   6.356 +* Strabon depends on a version of Sesame OpenRDF that is not hosted at the central
   6.357 +  repository of Maven. These artifacts resided on the Maven repository of Aduna 
   6.358 +  which is not maintained any more. For this reason, you can use a mirror repository 
   6.359 +  hosted by Ontotext. To configure maven to use the Ontotext mirror for the Aduna 
   6.360 +  repository, you append to your settings file ${user.home}/.m2/settings.xml) the 
   6.361 +  following:
   6.362 +
   6.363 +<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
   6.364 +  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   6.365 +  xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
   6.366 +                      http://maven.apache.org/xsd/settings-1.0.0.xsd">
   6.367 +...
   6.368 +...
   6.369 +  <mirrors>
   6.370 +    <mirror>
   6.371 +      <id>aduna-mirror</id>
   6.372 +      <name>Aduna Maven Repository - Mirror</name>
   6.373 +      <url>http://maven.ontotext.com/content/repositories/aduna/</url>
   6.374 +      <mirrorOf>aduna-opensource.releases</mirrorOf>
   6.375 +    </mirror>
   6.376 +  </mirrors>
   6.377 +...
   6.378 +...
   6.379 +</settings>
   6.380 +
   6.381 + * By default, Tomcat uses ISO-8859-1 character encoding when decoding URLs received 
   6.382 +   from a browser. This can cause problems when encoding is UTF-8, and you are using 
   6.383 +   international characters. In order to fix this, edit conf/server.xml and find the 
   6.384 +   line where the Connector is defined. Add the parameter URIEncoding and set it to 
   6.385 +   UTF-8. For example:
   6.386 +
   6.387 +   <Connector port="8080" protocol="HTTP/1.1" 
   6.388 +                  connectionTimeout="20000" 
   6.389 +                  URIEncoding="UTF-8"
   6.390 +                  redirectPort="8443" />
   6.391 +
   6.392 + * Building and executing any maven goals fails for maven versions <3.0 due to a
   6.393 +   dependency to the `shade' plugin that is available only for maven version 3.0
   6.394 +   (http://maven.apache.org/plugins/maven-shade-plugin/). In such systems, you may
   6.395 +   disable execution of this plugin by setting the environmental variable
   6.396 +   `shade.skip'. For example, to build Strabon using maven version 2.0 you may
   6.397 +   execute the following command:
   6.398 +
   6.399 +   	$ mvn clean package -Dshade.skip
   6.400 +
   6.401 + * When using MonetDB as a backend, the following source code of MonetDB must be 
   6.402 +   used:
   6.403 +	https://hg.strabon.di.uoa.gr/MonetDB/   
   6.404 +
   6.405 +
   6.406  License
   6.407  =======
   6.408 -Copyright (C) 2010-2012 Strabon Team
   6.409 +This Source Code Form is subject to the terms of the Mozilla Public
   6.410 +License, v. 2.0. If a copy of the MPL was not distributed with this
   6.411 +file, You can obtain one at http://mozilla.org/MPL/2.0/.
   6.412 +
   6.413 +Copyright (C) 2010, 2011, 2012, Pyravlos Team
   6.414 +
   6.415 +http://www.strabon.di.uoa.gr/
   6.416 +
   6.417 +
   6.418 +How to apply the license
   6.419 +========================
   6.420 + * In the beginning of script files (after the shell directive) paste the
   6.421 +   following statement:
   6.422 +#
   6.423 +# This Source Code Form is subject to the terms of the Mozilla Public
   6.424 +# License, v. 2.0. If a copy of the MPL was not distributed with this
   6.425 +# file, You can obtain one at http://mozilla.org/MPL/2.0/.
   6.426 +#
   6.427 +# Copyright (C) 2010, 2011, 2012, Pyravlos Team
   6.428 +#
   6.429 +# http://www.strabon.di.uoa.gr/
   6.430 +#
   6.431 +
   6.432 + * In the beginning of Java source code files paste the following statement:
   6.433 +/**
   6.434 + * This Source Code Form is subject to the terms of the Mozilla Public
   6.435 + * License, v. 2.0. If a copy of the MPL was not distributed with this
   6.436 + * file, You can obtain one at http://mozilla.org/MPL/2.0/.
   6.437 + * 
   6.438 + * Copyright (C) 2010, 2011, 2012, Pyravlos Team
   6.439 + * 
   6.440 + * http://www.strabon.di.uoa.gr/
   6.441 + */
   6.442 +
   6.443 + * In the beginning of HTML/XML files paste the following statement:
   6.444 +<!-- This Source Code Form is subject to the terms of the Mozilla Public
   6.445 +   - License, v. 2.0. If a copy of the MPL was not distributed with this
   6.446 +   - file, You can obtain one at http://mozilla.org/MPL/2.0/. 
   6.447 +   -
   6.448 +   - Copyright (C) 2010, 2011, 2012, Pyravlos Team
   6.449 +   -
   6.450 +   - http://www.strabon.di.uoa.gr/
   6.451 +-->
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/endpoint-client/pom.xml	Fri May 02 17:39:27 2014 +0200
     7.3 @@ -0,0 +1,176 @@
     7.4 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
     7.5 +
     7.6 +	<modelVersion>4.0.0</modelVersion>
     7.7 +
     7.8 +	<parent>
     7.9 +		<groupId>eu.earthobservatory</groupId>
    7.10 +		<artifactId>strabon</artifactId>
    7.11 +		<version>3.2.10-SNAPSHOT</version>
    7.12 +	</parent>
    7.13 +
    7.14 +	<artifactId>strabon-endpoint-client</artifactId>
    7.15 +
    7.16 +	<name>Strabon: Endpoint client</name>
    7.17 +	<description>A java client for Strabon endpoint</description>
    7.18 +	<packaging>jar</packaging>
    7.19 +
    7.20 +	<dependencies>
    7.21 +		<dependency>
    7.22 +			<groupId>org.openrdf.sesame</groupId>
    7.23 +			<artifactId>sesame-rio-api</artifactId>
    7.24 +		</dependency>
    7.25 +		<dependency>
    7.26 +			<groupId>org.openrdf.sesame</groupId>
    7.27 +			<artifactId>sesame-queryresultio-spatial-api</artifactId>
    7.28 +		</dependency>
    7.29 +		
    7.30 +		<dependency>
    7.31 +			<groupId>org.apache.httpcomponents</groupId>
    7.32 +			<artifactId>httpclient</artifactId>
    7.33 +			<!-- version was put in purpose! do not remove it; -->
    7.34 +			<version>4.2</version>
    7.35 +		</dependency>
    7.36 +
    7.37 +		<!-- Testing: JUnit -->
    7.38 +		<dependency>
    7.39 +			<groupId>junit</groupId>
    7.40 +			<artifactId>junit</artifactId>
    7.41 +			<scope>test</scope>
    7.42 +		</dependency>
    7.43 +		<dependency>
    7.44 +			<groupId>org.openrdf.sesame</groupId>
    7.45 +			<artifactId>
    7.46 +				sesame-queryresultio-spatial-sparqlkml
    7.47 +			</artifactId>
    7.48 +		</dependency>
    7.49 +	</dependencies>
    7.50 +
    7.51 +	<build>
    7.52 +		<pluginManagement>
    7.53 +			<plugins>
    7.54 +				<plugin>
    7.55 +					<groupId>org.eclipse.m2e</groupId>
    7.56 +					<artifactId>lifecycle-mapping</artifactId>
    7.57 +					<version>1.0.0</version>
    7.58 +					<configuration>
    7.59 +						<lifecycleMappingMetadata>
    7.60 +							<pluginExecutions>
    7.61 +								<pluginExecution>
    7.62 +									<pluginExecutionFilter>
    7.63 +										<groupId>org.apache.maven.plugins</groupId>
    7.64 +										<artifactId>maven-dependency-plugin</artifactId>
    7.65 +										<versionRange>[2.4,)</versionRange>
    7.66 +										<goals>
    7.67 +											<goal>copy-dependencies</goal>
    7.68 +										</goals>
    7.69 +									</pluginExecutionFilter>
    7.70 +									<action>
    7.71 +										<ignore />
    7.72 +									</action>
    7.73 +								</pluginExecution>
    7.74 +							</pluginExecutions>
    7.75 +						</lifecycleMappingMetadata>
    7.76 +					</configuration>
    7.77 +				</plugin>
    7.78 +			</plugins>
    7.79 +		</pluginManagement>
    7.80 +
    7.81 +		<plugins>
    7.82 +			<plugin>
    7.83 +				<groupId>org.apache.maven.plugins</groupId>
    7.84 +				<artifactId>maven-compiler-plugin</artifactId>
    7.85 +				<version>2.3.2</version>
    7.86 +				<configuration>
    7.87 +					<source>1.6</source>
    7.88 +					<target>1.6</target>
    7.89 +					<encoding>utf8</encoding>
    7.90 +				</configuration>
    7.91 +			</plugin>
    7.92 +			<plugin>
    7.93 +				<groupId>org.apache.maven.plugins</groupId>
    7.94 +				<artifactId>maven-dependency-plugin</artifactId>
    7.95 +				<version>2.4</version>
    7.96 +				<executions>
    7.97 +					<execution>
    7.98 +						<id>copy-dependencies</id>
    7.99 +						<phase>package</phase>
   7.100 +						<goals>
   7.101 +							<goal>copy-dependencies</goal>
   7.102 +						</goals>
   7.103 +						<configuration>
   7.104 +							<outputDirectory>${project.build.directory}</outputDirectory>
   7.105 +							<overWriteReleases>false</overWriteReleases>
   7.106 +							<overWriteSnapshots>false</overWriteSnapshots>
   7.107 +							<overWriteIfNewer>true</overWriteIfNewer>
   7.108 +						</configuration>
   7.109 +					</execution>
   7.110 +				</executions>
   7.111 +			</plugin>
   7.112 +
   7.113 +			<plugin>
   7.114 +				<groupId>org.apache.maven.plugins</groupId>
   7.115 +				<artifactId>maven-jar-plugin</artifactId>
   7.116 +				<version>2.4</version>
   7.117 +				<configuration>
   7.118 +					<skipIfEmpty>true</skipIfEmpty>
   7.119 +				</configuration>
   7.120 +				<executions>
   7.121 +					<execution>
   7.122 +						<goals>
   7.123 +							<goal>test-jar</goal>
   7.124 +						</goals>
   7.125 +					</execution>
   7.126 +				</executions>
   7.127 +			</plugin>
   7.128 +		</plugins>
   7.129 +	</build>
   7.130 +
   7.131 +<profiles>
   7.132 +	<profile>
   7.133 +		<id>conditional-shade-plugin</id>
   7.134 +
   7.135 +		<activation>
   7.136 +			<property><name>!shade.skip</name></property>
   7.137 +		</activation>
   7.138 +		<build>
   7.139 +			<plugins>
   7.140 +			<plugin>
   7.141 +                                <groupId>org.apache.maven.plugins</groupId>
   7.142 +                                <artifactId>maven-shade-plugin</artifactId>
   7.143 +                                <version>2.2</version>
   7.144 +                        <!--
   7.145 +                                <configuration>
   7.146 +                                </configuration>
   7.147 +                        -->
   7.148 +                                <executions>
   7.149 +                                        <execution>
   7.150 +                                                <phase>package</phase>
   7.151 +                                                <goals>
   7.152 +                                                        <goal>shade</goal>
   7.153 +                                                </goals>
   7.154 +                                                <configuration>
   7.155 +                                                        <transformers>
   7.156 +                                                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
   7.157 +                                                                        <mainClass>eu.earthobservatory.org.StrabonEndpoint.client.StrabonEndpoint</mainClass>
   7.158 +                                                                </transformer>
   7.159 +                                                        </transformers>
   7.160 +                                                        <filters>
   7.161 +															<filter>
   7.162 +																<artifact>*:*</artifact>
   7.163 +																<excludes>
   7.164 +																	<exclude>META-INF/*.SF</exclude>
   7.165 +																	<exclude>META-INF/*.DSA</exclude>
   7.166 +																	<exclude>META-INF/*.RSA</exclude>
   7.167 +																</excludes>
   7.168 +															</filter>
   7.169 +														</filters>
   7.170 +                                                </configuration>
   7.171 +                                        </execution>
   7.172 +                                </executions>
   7.173 +                        </plugin>
   7.174 +			</plugins>
   7.175 +		</build>
   7.176 +	</profile>
   7.177 +</profiles>
   7.178 +</project>
   7.179 +
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/endpoint-client/src/main/java/eu/earthobservatory/org/StrabonEndpoint/client/EndpointResult.java	Fri May 02 17:39:27 2014 +0200
     8.3 @@ -0,0 +1,39 @@
     8.4 +/**
     8.5 + * This Source Code Form is subject to the terms of the Mozilla Public
     8.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     8.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/.
     8.8 + * 
     8.9 + * Copyright (C) 2012, Pyravlos Team
    8.10 + * 
    8.11 + * http://www.strabon.di.uoa.gr/
    8.12 + */
    8.13 +package eu.earthobservatory.org.StrabonEndpoint.client;
    8.14 +
    8.15 +/**
    8.16 + * @author Charalampos Nikolaou <charnik@di.uoa.gr>
    8.17 + *
    8.18 + */
    8.19 +public class EndpointResult {
    8.20 +
    8.21 +	private int statusCode;
    8.22 +	private String statusText;
    8.23 +	private String response;
    8.24 +	
    8.25 +	public EndpointResult(int statusCode, String statusLine, String response) {
    8.26 +		this.statusCode = statusCode;
    8.27 +		this.statusText = statusLine;
    8.28 +		this.response = response;
    8.29 +	}
    8.30 +	
    8.31 +	public int getStatusCode() {
    8.32 +		return statusCode;
    8.33 +	}
    8.34 +
    8.35 +	public String getStatusText() {
    8.36 +		return statusText;
    8.37 +	}
    8.38 +
    8.39 +	public String getResponse() {
    8.40 +		return response;
    8.41 +	}
    8.42 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/endpoint-client/src/main/java/eu/earthobservatory/org/StrabonEndpoint/client/HTTPClient.java	Fri May 02 17:39:27 2014 +0200
     9.3 @@ -0,0 +1,112 @@
     9.4 +/**
     9.5 + * This Source Code Form is subject to the terms of the Mozilla Public
     9.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     9.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/.
     9.8 + *
     9.9 + * Copyright (C) 2012, Pyravlos Team
    9.10 + *
    9.11 + * http://www.strabon.di.uoa.gr/
    9.12 + */
    9.13 +package eu.earthobservatory.org.StrabonEndpoint.client;
    9.14 +
    9.15 +import org.apache.http.client.HttpClient;
    9.16 +import org.apache.http.conn.ClientConnectionManager;
    9.17 +import org.apache.http.impl.client.DefaultHttpClient;
    9.18 +import org.apache.http.impl.conn.PoolingClientConnectionManager;
    9.19 +
    9.20 +/**
    9.21 + * @author Charalampos Nikolaou <charnik@di.uoa.gr>
    9.22 + *
    9.23 + */
    9.24 +public abstract class HTTPClient {
    9.25 +
    9.26 +	/**
    9.27 +	 * The host on which the endpoint is located.
    9.28 +	 */
    9.29 +	protected String host;
    9.30 +	
    9.31 +	/**
    9.32 +	 * The port of the host.
    9.33 +	 */
    9.34 +	protected int port;
    9.35 +	
    9.36 +	/**
    9.37 +	 * The name of the endpoint.
    9.38 +	 * 
    9.39 +	 * This is useful for {@link SPARQLEndpoint} instances that are usually
    9.40 +	 * deployed in a tomcat container as web applications.
    9.41 +	 */
    9.42 +	protected String endpointName;
    9.43 +	
    9.44 +	/**
    9.45 +	 * The username to be used in case the endpoint requires authentication.
    9.46 +	 */
    9.47 +	protected String user;
    9.48 +	
    9.49 +	/**
    9.50 +	 * The password to be used in case the endpoint requires authentication.
    9.51 +	 */
    9.52 +	protected String password;
    9.53 +	
    9.54 +	/**
    9.55 +	 * The connection manager that manages sharing of connections to endpoints
    9.56 +	 * among several threads.
    9.57 +	 */
    9.58 +	private ClientConnectionManager connectionManager;
    9.59 +	
    9.60 +	/**
    9.61 +	 * The HttpClient to be used for connecting to an endpoint.
    9.62 +	 */
    9.63 +	protected HttpClient hc;
    9.64 +	
    9.65 +	public HTTPClient(String host, int port) {
    9.66 +		this(host, port, "/");
    9.67 +	}
    9.68 +	
    9.69 +	public HTTPClient(String host, int port, String endpointName) {
    9.70 +		this.host = host;
    9.71 +		this.port = port;
    9.72 +		
    9.73 +		this.endpointName = (endpointName == null ? "":endpointName);
    9.74 +		
    9.75 +		// create a connection manager for allowing the users of this class use threads
    9.76 +		connectionManager = new PoolingClientConnectionManager();
    9.77 +		
    9.78 +		// create an HttpClient instance that establishes connections based on the connection manager
    9.79 +		hc = new DefaultHttpClient(connectionManager);
    9.80 +	}
    9.81 +		
    9.82 +	public String getHost() {
    9.83 +		return host;
    9.84 +	}
    9.85 +	
    9.86 +	public int getPort() {
    9.87 +		return port;
    9.88 +	}
    9.89 +	
    9.90 +	public void setUser(String user) {
    9.91 +		this.user = user;
    9.92 +	}
    9.93 +	
    9.94 +	public void setPassword(String pass) {
    9.95 +		this.password = pass;
    9.96 +	}
    9.97 +	
    9.98 +	public String getUser() {
    9.99 +		return user;
   9.100 +	}
   9.101 +	
   9.102 +	public String getPassword() {
   9.103 +		return password;
   9.104 +	}
   9.105 +	
   9.106 +	/**
   9.107 +	 * Returns a URL (actually a {@link String}) for establishing connections
   9.108 +	 * to an endpoint based on the information given to the constructor. 
   9.109 +	 * 
   9.110 +	 * @return
   9.111 +	 */
   9.112 +	public String getConnectionURL() {
   9.113 +		return "http://" + host + ((port == 80) ? "":":" + port) + "/" + endpointName; 
   9.114 +	}
   9.115 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/endpoint-client/src/main/java/eu/earthobservatory/org/StrabonEndpoint/client/SPARQLEndpoint.java	Fri May 02 17:39:27 2014 +0200
    10.3 @@ -0,0 +1,404 @@
    10.4 +/**
    10.5 + * This Source Code Form is subject to the terms of the Mozilla Public
    10.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
    10.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/.
    10.8 + *
    10.9 + * Copyright (C) 2012, 2013 Pyravlos Team
   10.10 + *
   10.11 + * http://www.strabon.di.uoa.gr/
   10.12 + */
   10.13 +package eu.earthobservatory.org.StrabonEndpoint.client;
   10.14 +
   10.15 +import java.io.BufferedReader;
   10.16 +import java.io.IOException;
   10.17 +import java.io.InputStream;
   10.18 +import java.io.InputStreamReader;
   10.19 +import java.net.URL;
   10.20 +import java.nio.charset.Charset;
   10.21 +import java.util.ArrayList;
   10.22 +import java.util.List;
   10.23 +
   10.24 +import org.apache.commons.httpclient.params.HostParams;
   10.25 +import org.apache.commons.httpclient.params.HttpMethodParams;
   10.26 +import org.apache.commons.httpclient.params.HttpParams;
   10.27 +import org.apache.http.HttpEntity;
   10.28 +import org.apache.http.HttpResponse;
   10.29 +import org.apache.http.NameValuePair;
   10.30 +import org.apache.http.client.entity.UrlEncodedFormEntity;
   10.31 +import org.apache.http.client.methods.HttpPost;
   10.32 +import org.apache.http.entity.StringEntity;
   10.33 +import org.apache.http.message.BasicNameValuePair;
   10.34 +import org.apache.xerces.impl.dv.util.Base64;
   10.35 +import org.openrdf.query.resultio.TupleQueryResultFormat;
   10.36 +import org.openrdf.query.resultio.stSPARQLQueryResultFormat;
   10.37 +import org.openrdf.rio.RDFFormat;
   10.38 +
   10.39 +/**
   10.40 + * This class is the implementation of a java client for accessing
   10.41 + * SPARQLEndpoint instances.
   10.42 + * 
   10.43 + * @author Charalampos Nikolaou <charnik@di.uoa.gr>
   10.44 + * @author Kallirroi Dogani <kallirroi@di.uoa.gr.
   10.45 + */
   10.46 +public class SPARQLEndpoint extends HTTPClient{
   10.47 +
   10.48 +	public SPARQLEndpoint(String host, int port) {
   10.49 +		super(host, port);
   10.50 +	}
   10.51 +	
   10.52 +	public SPARQLEndpoint(String host, int port, String endpointName) {
   10.53 +		super(host, port, endpointName);
   10.54 +	}
   10.55 +
   10.56 +	
   10.57 +	/**
   10.58 +	 * Executes a SPARQL query on the Endpoint and get the results
   10.59 +	 * in the format specified by stSPARQLQueryResultFormat, which is
   10.60 +	 * an instance of class (or a subclass) {@link TupleQueryResultFormat}.   
   10.61 +	 * 
   10.62 +	 * @param sparqlQuery
   10.63 +	 * @param format
   10.64 +	 * @return
   10.65 +	 * @throws IOException
   10.66 +	 */
   10.67 +	public EndpointResult query(String sparqlQuery, stSPARQLQueryResultFormat format) throws IOException {
   10.68 +		assert(format != null);
   10.69 +		
   10.70 +		// create a post method to execute
   10.71 +		HttpPost method = new HttpPost(getConnectionURL());
   10.72 +		
   10.73 +		// set the query parameter
   10.74 +		List<NameValuePair> params = new ArrayList<NameValuePair>();
   10.75 +		params.add(new BasicNameValuePair("query", sparqlQuery));
   10.76 +		UrlEncodedFormEntity encodedEntity = new UrlEncodedFormEntity(params, Charset.defaultCharset());
   10.77 +		method.setEntity(encodedEntity);
   10.78 +		
   10.79 +		// set the content type
   10.80 +		method.setHeader("Content-Type", "application/x-www-form-urlencoded");
   10.81 +		
   10.82 +		// set the accept format
   10.83 +		method.addHeader("Accept", format.getDefaultMIMEType());
   10.84 +		
   10.85 +		try {
   10.86 +			// response that will be filled next
   10.87 +			String responseBody = "";
   10.88 +			
   10.89 +			// execute the method
   10.90 +			HttpResponse response = hc.execute(method);
   10.91 +			int statusCode = response.getStatusLine().getStatusCode();
   10.92 +			
   10.93 +			// If the response does not enclose an entity, there is no need
   10.94 +			// to worry about connection release
   10.95 +			HttpEntity entity = response.getEntity();
   10.96 +			if (entity != null) {
   10.97 +				InputStream instream = entity.getContent();
   10.98 +				try {
   10.99 +
  10.100 +					BufferedReader reader = new BufferedReader(new InputStreamReader(instream));
  10.101 +					StringBuffer strBuf = new StringBuffer();
  10.102 +					
  10.103 +					// do something useful with the response
  10.104 +					String nextLine;
  10.105 +					while ((nextLine = reader.readLine()) != null) {
  10.106 +						strBuf.append(nextLine + "\n");
  10.107 +					}
  10.108 +					
  10.109 +					// remove last newline character
  10.110 +					if (strBuf.length() > 0) {
  10.111 +						strBuf.setLength(strBuf.length() - 1);
  10.112 +					}
  10.113 +					
  10.114 +					responseBody = strBuf.toString();
  10.115 +
  10.116 +				} catch (IOException ex) {
  10.117 +					// In case of an IOException the connection will be released
  10.118 +					// back to the connection manager automatically
  10.119 +					throw ex;
  10.120 +
  10.121 +				} catch (RuntimeException ex) {
  10.122 +					// In case of an unexpected exception you may want to abort
  10.123 +					// the HTTP request in order to shut down the underlying
  10.124 +					// connection and release it back to the connection manager.
  10.125 +					method.abort();
  10.126 +					throw ex;
  10.127 +
  10.128 +				} finally {
  10.129 +					// Closing the input stream will trigger connection release
  10.130 +					instream.close();
  10.131 +				}
  10.132 +			}
  10.133 +			 
  10.134 +			return new EndpointResult(statusCode, response.getStatusLine().getReasonPhrase(), responseBody);
  10.135 +
  10.136 +		} catch (IOException e) {
  10.137 +			throw e;
  10.138 +			
  10.139 +		} finally {
  10.140 +			// release the connection.
  10.141 +			method.releaseConnection();
  10.142 +		}
  10.143 +	}
  10.144 +
  10.145 +	
  10.146 +	/* Functions 'store' and 'update' do not follow the SPARQL Protocol.
  10.147 +	 * This means that only Strabon Endpoint supports these operations.
  10.148 +	 * In future they must be modified in order to be compatible with
  10.149 +	 * Virtuso and Parliament endpoints.
  10.150 +	 */
  10.151 +	
  10.152 +	
  10.153 +	/**
  10.154 +	 * Stores the RDF <code>data</code> which are in the RDF format
  10.155 +	 * <code>format</code> in the named graph specified by the URL
  10.156 +	 * <code>namedGraph</code>.
  10.157 +	 * 
  10.158 +	 * @param data 
  10.159 +	 * @param format
  10.160 +	 * @param namedGraph
  10.161 +	 * @return <code>true</code> if store was successful, <code>false</code> otherwise
  10.162 +	 * @throws IOException 
  10.163 +	 */
  10.164 +	
  10.165 +	public boolean store(String data, RDFFormat format, URL namedGraph) throws IOException {
  10.166 +assert(format != null);
  10.167 +		
  10.168 +		// create a post method to execute
  10.169 +		HttpPost method = new HttpPost(getConnectionURL());
  10.170 +		
  10.171 +		// set the url and fromurl parameters
  10.172 +		List<NameValuePair> params = new ArrayList<NameValuePair>();
  10.173 +		params.add(new BasicNameValuePair("data", data));
  10.174 +		if (namedGraph!=null)
  10.175 +			params.add(new BasicNameValuePair("graph", namedGraph.toString()));
  10.176 +		UrlEncodedFormEntity encodedEntity = new UrlEncodedFormEntity(params, Charset.defaultCharset());
  10.177 +		method.setEntity(encodedEntity);
  10.178 +		
  10.179 +		// set the content type
  10.180 +		method.setHeader("Content-Type", "application/x-www-form-urlencoded");
  10.181 +		
  10.182 +		// set the accept format
  10.183 +		method.addHeader("Accept", format.getDefaultMIMEType());
  10.184 +		
  10.185 +		//set username and password
  10.186 +		if (getUser()!=null && getPassword()!=null){
  10.187 +			
  10.188 +			String userPass = getUser()+":"+ getPassword();
  10.189 +			String encoding = Base64.encode(userPass.getBytes());
  10.190 +			method.setHeader("Authorization", "Basic "+ encoding);
  10.191 +		}
  10.192 +		
  10.193 +		try {
  10.194 +			// response that will be filled next
  10.195 +		//	String responseBody = "";
  10.196 +			
  10.197 +			// execute the method
  10.198 +			HttpResponse response = hc.execute(method);
  10.199 +			int statusCode = response.getStatusLine().getStatusCode();
  10.200 +			
  10.201 +			if (statusCode==200)
  10.202 +				return true;
  10.203 +			else{
  10.204 +				System.err.println("Status code " + statusCode);
  10.205 +				return false;
  10.206 +			}
  10.207 +				
  10.208 +			
  10.209 +
  10.210 +		} catch (IOException e) {
  10.211 +			throw e;
  10.212 +			
  10.213 +		} finally {
  10.214 +			// release the connection.
  10.215 +			method.releaseConnection();
  10.216 +		}
  10.217 +	}
  10.218 +
  10.219 +	/**
  10.220 +	 * Stores the RDF data located at <code>data</code> which are in the
  10.221 +	 * RDF format <code>format</code> in the named graph specified by the
  10.222 +	 * URL <code>namedGraph</code>.
  10.223 +	 * 
  10.224 +	 * @param data
  10.225 +	 * @param format
  10.226 +	 * @param namedGraph
  10.227 +	 * @return <code>true</code> if store was successful, <code>false</code> otherwise
  10.228 +	 */
  10.229 +
  10.230 +
  10.231 +	/*
  10.232 +	 * Comment: in order to make queries to strabon endpoint we must create a SPARQLEndpoint
  10.233 +	 * with endpointName ".../Query". To store data to strabon endpoint the endpointName of
  10.234 +	 * SPARQLEndpoint must be something like ".../Store". This means that the same object of
  10.235 +	 * SPARQLEndpoint cannot execute store and query operations for strabon endpoints.
  10.236 +	 * This is wrong and must be fixed. Also, the main idea is that the SPARQLEndpoint client 
  10.237 +	 * should be a general endpoint client that supports strabon, virtuoso and parliament endpoints.
  10.238 +	 */
  10.239 +	public boolean store(URL data, RDFFormat format, URL namedGraph) throws IOException{
  10.240 +		
  10.241 +		assert(format != null);
  10.242 +		
  10.243 +		// create a post method to execute
  10.244 +		HttpPost method = new HttpPost(getConnectionURL());
  10.245 +		
  10.246 +		// set the url and fromurl parameters
  10.247 +		List<NameValuePair> params = new ArrayList<NameValuePair>();
  10.248 +		params.add(new BasicNameValuePair("url", data.toString()));
  10.249 +		params.add(new BasicNameValuePair("fromurl", ""));
  10.250 +		if (namedGraph!=null)
  10.251 +			params.add(new BasicNameValuePair("graph", namedGraph.toString()));
  10.252 +		UrlEncodedFormEntity encodedEntity = new UrlEncodedFormEntity(params, Charset.defaultCharset());
  10.253 +		method.setEntity(encodedEntity);
  10.254 +		
  10.255 +		// set the content type
  10.256 +		method.setHeader("Content-Type", "application/x-www-form-urlencoded");
  10.257 +		
  10.258 +		// set the accept format
  10.259 +		method.addHeader("Accept", format.getDefaultMIMEType());
  10.260 +		
  10.261 +		//set username and password
  10.262 +		if (getUser()!=null && getPassword()!=null){
  10.263 +			
  10.264 +			String userPass = getUser()+":"+ getPassword();
  10.265 +			String encoding = Base64.encode(userPass.getBytes());
  10.266 +			method.setHeader("Authorization", "Basic "+ encoding);
  10.267 +		}
  10.268 +		
  10.269 +		try {
  10.270 +			// response that will be filled next
  10.271 +		//	String responseBody = "";
  10.272 +			
  10.273 +			// execute the method
  10.274 +			HttpResponse response = hc.execute(method);
  10.275 +			int statusCode = response.getStatusLine().getStatusCode();
  10.276 +			
  10.277 +			if (statusCode==200)
  10.278 +				return true;
  10.279 +			else{
  10.280 +				System.err.println("Status code " + statusCode);
  10.281 +				return false;
  10.282 +			}
  10.283 +				
  10.284 +			
  10.285 +
  10.286 +		} catch (IOException e) {
  10.287 +			throw e;
  10.288 +			
  10.289 +		} finally {
  10.290 +			// release the connection.
  10.291 +			method.releaseConnection();
  10.292 +		}
  10.293 +	}
  10.294 +		
  10.295 +
  10.296 +	/**
  10.297 +	 * Executes the SPARQL Update query specified in <code>sparqlUpdate</code>.
  10.298 +	 * 
  10.299 +	 * @param sparqlUpdate
  10.300 +	 * @return <code>true</code> if store was successful, <code>false</code> otherwise
  10.301 +	 * @throws IOException 
  10.302 +	 */
  10.303 +
  10.304 +	public boolean update(String sparqlUpdate) throws IOException {
  10.305 +		
  10.306 +		// create a post method to execute
  10.307 +		HttpPost method = new HttpPost(getConnectionURL());
  10.308 +		
  10.309 +		// set the query parameter
  10.310 +		List<NameValuePair> params = new ArrayList<NameValuePair>();
  10.311 +		params.add(new BasicNameValuePair("query", sparqlUpdate));
  10.312 +		UrlEncodedFormEntity encodedEntity = new UrlEncodedFormEntity(params, Charset.defaultCharset());
  10.313 +		method.setEntity(encodedEntity);
  10.314 +		
  10.315 +		// set the content type
  10.316 +		method.setHeader("Content-Type", "application/x-www-form-urlencoded");
  10.317 +		
  10.318 +		// set the accept format
  10.319 +		method.addHeader("Accept", "text/xml");
  10.320 +		
  10.321 +		//set username and password
  10.322 +		if (getUser()!=null && getPassword()!=null){
  10.323 +			
  10.324 +			String userPass = getUser()+":"+ getPassword();
  10.325 +			String encoding = Base64.encode(userPass.getBytes());
  10.326 +			method.setHeader("Authorization", "Basic "+ encoding);
  10.327 +		}
  10.328 +		
  10.329 +		try {
  10.330 +			// response that will be filled next
  10.331 +			
  10.332 +			// execute the method
  10.333 +			HttpResponse response = hc.execute(method);
  10.334 +			int statusCode = response.getStatusLine().getStatusCode();
  10.335 +			
  10.336 +			if (statusCode==200)
  10.337 +				return true;
  10.338 +			else{
  10.339 +				System.err.println("Status code " + statusCode);
  10.340 +				return false;
  10.341 +			}
  10.342 +				
  10.343 +			
  10.344 +
  10.345 +		} catch (IOException e) {
  10.346 +			throw e;
  10.347 +			
  10.348 +		} finally {
  10.349 +			// release the connection.
  10.350 +			method.releaseConnection();
  10.351 +		}
  10.352 +		
  10.353 +	}
  10.354 +
  10.355 +	public EndpointResult describe(String sparqlDescribe) {
  10.356 +		throw new UnsupportedOperationException();
  10.357 +	}
  10.358 +
  10.359 +	public EndpointResult construct(String sparqlConstruct) {
  10.360 +		throw new UnsupportedOperationException();
  10.361 +	}
  10.362 +	
  10.363 +	public EndpointResult ask(String sparqlAsk) {
  10.364 +		throw new UnsupportedOperationException();
  10.365 +	}
  10.366 +	
  10.367 +	
  10.368 +	public static void main(String args[]) {
  10.369 +		if (args.length < 4) {
  10.370 +			System.err.println("Usage: eu.earthobservatory.org.StrabonEndpoint.client.SPARQLEndpoint <HOST> <PORT> <APPNAME> [<FORMAT>]");
  10.371 +			System.err.println("       where <HOST>       is the hostname of the Strabon Endpoint");
  10.372 +			System.err.println("             <PORT>       is the port to connect to on the host");
  10.373 +			System.err.println("             <APPNAME>    is the application name of Strabon Endpoint as deployed in the Tomcat container");
  10.374 +			System.err.println("             <QUERY>      is the query to execute on the endpoint");
  10.375 +			System.err.println("             [<FORMAT>]   is the format of your results. Should be one of XML (default), KML, KMZ, GeoJSON, TSV, or HTML.");
  10.376 +			System.exit(1);
  10.377 +		}
  10.378 +		
  10.379 +		String host = args[0];
  10.380 +		Integer port = new Integer(args[1]);
  10.381 +		String appName = args[2];
  10.382 +		String query = args[3];
  10.383 +		String format = "";
  10.384 +		
  10.385 +		if (args.length == 5) {
  10.386 +			format = args[4];
  10.387 +			
  10.388 +		} else {
  10.389 +			format = "XML";
  10.390 +		}
  10.391 +		
  10.392 +		SPARQLEndpoint endpoint = new SPARQLEndpoint(host, port, appName);
  10.393 +		
  10.394 +		try {
  10.395 +			EndpointResult result = endpoint.query(query, (stSPARQLQueryResultFormat) stSPARQLQueryResultFormat.valueOf(format));
  10.396 +			
  10.397 +			System.out.println("Status code: " + result.getStatusCode());
  10.398 +			System.out.println("Status text: " + result.getStatusText());
  10.399 +			System.out.println("<----- Result ----->");
  10.400 +			System.out.println(result.getResponse().replaceAll("\n", "\n\t"));
  10.401 +			System.out.println("<----- Result ----->");
  10.402 +			
  10.403 +		} catch (IOException e) {
  10.404 +			e.printStackTrace();
  10.405 +		}
  10.406 +	}
  10.407 +}
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/endpoint-client/src/main/java/eu/earthobservatory/org/StrabonEndpoint/client/SpatialEndpoint.java	Fri May 02 17:39:27 2014 +0200
    11.3 @@ -0,0 +1,75 @@
    11.4 +/**
    11.5 + * This Source Code Form is subject to the terms of the Mozilla Public
    11.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
    11.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/.
    11.8 + *
    11.9 + * Copyright (C) 2012, 2013, Pyravlos Team
   11.10 + *
   11.11 + * http://www.strabon.di.uoa.gr/
   11.12 + */
   11.13 +package eu.earthobservatory.org.StrabonEndpoint.client;
   11.14 +
   11.15 +import java.io.ByteArrayInputStream;
   11.16 +import java.io.ByteArrayOutputStream;
   11.17 +import java.io.IOException;
   11.18 +import java.io.InputStream;
   11.19 +import java.util.Vector;
   11.20 +
   11.21 +import org.openrdf.query.QueryEvaluationException;
   11.22 +import org.openrdf.query.TupleQueryResult;
   11.23 +import org.openrdf.query.TupleQueryResultHandlerException;
   11.24 +import org.openrdf.query.resultio.QueryResultIO;
   11.25 +import org.openrdf.query.resultio.QueryResultParseException;
   11.26 +import org.openrdf.query.resultio.TupleQueryResultFormat;
   11.27 +import org.openrdf.query.resultio.UnsupportedQueryResultFormatException;
   11.28 +import org.openrdf.query.resultio.stSPARQLQueryResultFormat;
   11.29 +import org.openrdf.query.resultio.sparqlkml.stSPARQLResultsKMLWriter;
   11.30 +
   11.31 +/**
   11.32 + * SpatialEndpoint is a SPARQLEndpoint which can store and 
   11.33 + * query for spatial data. It also supports KML format for 
   11.34 + * this kind of data.
   11.35 + * 
   11.36 + * @author Charalampos Nikolaou <charnik@di.uoa.gr>
   11.37 + * @author Kallirroi Dogani <kallirroi@di.uoa.gr>
   11.38 + */
   11.39 +public class SpatialEndpoint extends SPARQLEndpoint {
   11.40 +	
   11.41 +	public SpatialEndpoint(String host, int port) {
   11.42 +		super(host, port);
   11.43 +	}
   11.44 +	
   11.45 +	public SpatialEndpoint(String host, int port, String endpointName) {
   11.46 +		super(host, port, endpointName);
   11.47 +	}
   11.48 +	
   11.49 +	public EndpointResult queryForKML(String sparqlQuery) throws IOException, QueryResultParseException, TupleQueryResultHandlerException, UnsupportedQueryResultFormatException, QueryEvaluationException{
   11.50 +		
   11.51 +		EndpointResult xmlResult = query(sparqlQuery, stSPARQLQueryResultFormat.XML);
   11.52 +		
   11.53 +		if (xmlResult.getStatusCode() != 200) {
   11.54 +			throw new RuntimeException("Failed : HTTP error code : " + xmlResult.getStatusCode() + " " + xmlResult.getStatusText());
   11.55 +		}
   11.56 +		
   11.57 +		String xml = xmlResult.getResponse();
   11.58 +		
   11.59 +		InputStream inputStream = new ByteArrayInputStream(xml.getBytes("UTF-8"));  
   11.60 +		TupleQueryResult results = QueryResultIO.parse(inputStream, TupleQueryResultFormat.SPARQL);
   11.61 +		
   11.62 +		ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
   11.63 +		stSPARQLResultsKMLWriter kmlWriter = new stSPARQLResultsKMLWriter(outputStream);
   11.64 +			
   11.65 +		kmlWriter.startQueryResult(new Vector<String>());
   11.66 +					
   11.67 +		while(results.hasNext()){
   11.68 +		
   11.69 +				kmlWriter.handleSolution(results.next());
   11.70 +		}	
   11.71 +					
   11.72 +		kmlWriter.endQueryResult();
   11.73 +			
   11.74 +		EndpointResult kmlResult = new EndpointResult(xmlResult.getStatusCode(), xmlResult.getStatusText(), outputStream.toString());
   11.75 +		return kmlResult;
   11.76 +	}
   11.77 +
   11.78 +}
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/endpoint-client/src/test/java/eu/earthobservatory/org/StrabonEndpoint/client/TestLimit.java	Fri May 02 17:39:27 2014 +0200
    12.3 @@ -0,0 +1,109 @@
    12.4 +///**
    12.5 +// * This Source Code Form is subject to the terms of the Mozilla Public
    12.6 +// * License, v. 2.0. If a copy of the MPL was not distributed with this
    12.7 +// * file, You can obtain one at http://mozilla.org/MPL/2.0/.
    12.8 +// * 
    12.9 +// * Copyright (C) 2012, Pyravlos Team
   12.10 +// * 
   12.11 +// * http://www.strabon.di.uoa.gr/
   12.12 +// */
   12.13 +//package eu.earthobservatory.org.StrabonEndpoint.client;
   12.14 +//
   12.15 +//
   12.16 +//import static org.junit.Assert.assertTrue;
   12.17 +//
   12.18 +//import java.io.IOException;
   12.19 +//import org.junit.Before;
   12.20 +//import org.junit.Test;
   12.21 +//import org.openrdf.query.resultio.stSPARQLQueryResultFormat;
   12.22 +//
   12.23 +///**
   12.24 +// * @author Stella Giannakopoulou <sgian@di.uoa.gr>
   12.25 +// *
   12.26 +// */
   12.27 +//public class TestLimit {
   12.28 +//
   12.29 +//	private SPARQLEndpoint endpoint; 
   12.30 +//	private String [] testQueries;
   12.31 +//	private stSPARQLQueryResultFormat format;			
   12.32 +//	
   12.33 +//	@Before
   12.34 +//	public void init() {
   12.35 +//		
   12.36 +//		// initialize endpoint		
   12.37 +//		endpoint = new SPARQLEndpoint("localhost", 8080, "strabon-endpoint/Query");		
   12.38 +//		testQueries = new String[6];
   12.39 +//		
   12.40 +//		 // set queries
   12.41 +//		 testQueries[0] = "SELECT *\n" +
   12.42 +//				"WHERE\n"+							
   12.43 +//				"{\n"+
   12.44 +//				"	?x ?y ?z\n" +
   12.45 +//				"}\n" +
   12.46 +//				"limit 3";	
   12.47 +//		 
   12.48 +//		 testQueries[1] = "SELECT *\n" +
   12.49 +//					"WHERE\n"+							
   12.50 +//					"{\n"+
   12.51 +//					"	?x ?limit 5\n" +
   12.52 +//					"}\n" +
   12.53 +//					"limit 3";
   12.54 +//		 
   12.55 +//		 testQueries[2] = "SELECT *\n" +
   12.56 +//					"WHERE\n"+							
   12.57 +//					"{\n"+
   12.58 +//					"	?x ?limit 5\n" +
   12.59 +//					"}\n" +
   12.60 +//					"limit 3\n" +
   12.61 +//					"offset 4";
   12.62 +//		 
   12.63 +//		 testQueries[3] = "SELECT *\n" +
   12.64 +//					"WHERE\n"+							
   12.65 +//					"{\n"+
   12.66 +//					"	?x ?y ?z\n" +
   12.67 +//					"}\n" +
   12.68 +//					"limit 3000";
   12.69 +//		 
   12.70 +//		 testQueries[4] = "SELECT *\n" +
   12.71 +//					"WHERE\n"+							
   12.72 +//					"{\n"+
   12.73 +//					"	?x ?y ?z\n" +
   12.74 +//					"}\n" +
   12.75 +//					"offset 5" +
   12.76 +//					"limit 3000";
   12.77 +//		 
   12.78 +//		 testQueries[5] = "SELECT *\n" +
   12.79 +//					"WHERE\n"+							
   12.80 +//					"{\n"+
   12.81 +//					"	?x ?z 5\n" +
   12.82 +//					"}\n" +
   12.83 +//					"limit3000\n" +
   12.84 +//					"offset 2";
   12.85 +//		
   12.86 +//		// format does not matter for the test
   12.87 +//		format = stSPARQLQueryResultFormat.HTML;								
   12.88 +//	}
   12.89 +//	
   12.90 +//	/**
   12.91 +//	 * Test method for {@link eu.earthobservatory.org.StrabonEndpoint.client.StrabonEndpoint#query(java.lang.String, org.openrdf.query.resultio.stSPARQLQueryResultFormat)}.
   12.92 +//	 */
   12.93 +//	@Test
   12.94 +//	public void testQuery() {				
   12.95 +//				 
   12.96 +//		for (String query : testQueries) {			
   12.97 +//			try {
   12.98 +//				EndpointResult response = endpoint.query(query, format);
   12.99 +//				
  12.100 +//				if (response.getStatusCode() != 200) {
  12.101 +//					System.err.println("Status code ("+response.getStatusCode()+"):" + response.getStatusText());
  12.102 +//					
  12.103 +//				}
  12.104 +//				
  12.105 +//				assertTrue(response.getStatusCode() == 200);
  12.106 +//
  12.107 +//			} catch (IOException e) {
  12.108 +//				e.printStackTrace();
  12.109 +//			}					
  12.110 +//		}
  12.111 +//	}	
  12.112 +//}
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/endpoint-client/src/test/java/eu/earthobservatory/org/StrabonEndpoint/client/TestSPARQLEndpointStoreWithStrabon.java	Fri May 02 17:39:27 2014 +0200
    13.3 @@ -0,0 +1,90 @@
    13.4 +/**
    13.5 + * This Source Code Form is subject to the terms of the Mozilla Public
    13.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
    13.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/.
    13.8 + * 
    13.9 + * Copyright (C) 2013, Pyravlos Team
   13.10 + * 
   13.11 + * http://www.strabon.di.uoa.gr/
   13.12 + */
   13.13 +package eu.earthobservatory.org.StrabonEndpoint.client;
   13.14 +
   13.15 +import static org.junit.Assert.assertTrue;
   13.16 +
   13.17 +import java.io.IOException;
   13.18 +import java.net.MalformedURLException;
   13.19 +import java.net.URL;
   13.20 +import java.util.Vector;
   13.21 +
   13.22 +import org.junit.Before;
   13.23 +import org.junit.Test;
   13.24 +import org.openrdf.query.resultio.TupleQueryResultFormat;
   13.25 +import org.openrdf.query.resultio.stSPARQLQueryResultFormat;
   13.26 +import org.openrdf.rio.RDFFormat;
   13.27 +
   13.28 +/**
   13.29 + * @author Kallirroi Dogani <kallirroi@di.uoa.gr>
   13.30 + *
   13.31 + */
   13.32 +public class TestSPARQLEndpointStoreWithStrabon {
   13.33 +
   13.34 +	private SPARQLEndpoint endpoint; 
   13.35 +	private URL data;
   13.36 +	
   13.37 +	@Before
   13.38 +	public void init() {
   13.39 +		// initialize endpoint
   13.40 +		endpoint = new SPARQLEndpoint("luna.di.uoa.gr", 8080, "sextant-endpoint/Store");
   13.41 +		
   13.42 +		// set url data
   13.43 +		try {
   13.44 +			data = new URL("http://luna.di.uoa.gr:8080/strabon-endpoint-gwt/mapontology/map.nt");
   13.45 +		} catch (MalformedURLException e) {
   13.46 +			// TODO Auto-generated catch block
   13.47 +			e.printStackTrace();
   13.48 +		}
   13.49 +		
   13.50 +		endpoint.setUser("endpoint");
   13.51 +		endpoint.setPassword("3ndpo1nt");
   13.52 +		
   13.53 +				
   13.54 +	}
   13.55 +	
   13.56 +	/**
   13.57 +	 * Test method for {@link eu.earthobservatory.org.StrabonEndpoint.client.SPARQLEndpoint#store(java.net.URL, org.openrdf.rio.RDFFormat, java.net.URL)}.
   13.58 +	 * @throws IOException 
   13.59 +	 */
   13.60 +	@Test
   13.61 +	public void testStoreFromUrl() throws IOException {
   13.62 +		
   13.63 +			URL namedGraph = new URL("http://geo.linkedopendata.gr/map/example");
   13.64 +			Boolean response = endpoint.store(data, RDFFormat.NTRIPLES , namedGraph);
   13.65 +			
   13.66 +			if (response != true) 
   13.67 +				System.err.println("Error");
   13.68 +			
   13.69 +			
   13.70 +		//	assertTrue(response == true);
   13.71 +		
   13.72 +	}
   13.73 +	
   13.74 +	
   13.75 +	/**
   13.76 +	 * Test method for {@link eu.earthobservatory.org.StrabonEndpoint.client.SPARQLEndpoint#store(java.lang.String, org.openrdf.rio.RDFFormat, java.net.URL)}.
   13.77 +	 * @throws IOException 
   13.78 +	 */
   13.79 +	@Test
   13.80 +	public void testStore() throws IOException {
   13.81 +		
   13.82 +			URL namedGraph = new URL("http://geo.linkedopendata.gr/map/example");
   13.83 +			String data = "<http://geo.linkedopendata.gr/map/id/l22> <http://geo.linkedopendata.gr/map/hasName> \"layer22\" . ";
   13.84 +			Boolean response = endpoint.store(data, RDFFormat.NTRIPLES , namedGraph);
   13.85 +			
   13.86 +			if (response != true) 
   13.87 +				System.err.println("Error");
   13.88 +			
   13.89 +			
   13.90 +		//	assertTrue(response == true);
   13.91 +		
   13.92 +	}
   13.93 +}
   13.94 \ No newline at end of file
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/endpoint-client/src/test/java/eu/earthobservatory/org/StrabonEndpoint/client/TestSPARQLEndpointUpdateWithStrabon.java	Fri May 02 17:39:27 2014 +0200
    14.3 @@ -0,0 +1,51 @@
    14.4 +package eu.earthobservatory.org.StrabonEndpoint.client;
    14.5 +
    14.6 +import static org.junit.Assert.assertTrue;
    14.7 +
    14.8 +import java.io.IOException;
    14.9 +import java.net.MalformedURLException;
   14.10 +import java.net.URL;
   14.11 +
   14.12 +import org.junit.Before;
   14.13 +import org.junit.Test;
   14.14 +import org.openrdf.rio.RDFFormat;
   14.15 +
   14.16 +public class TestSPARQLEndpointUpdateWithStrabon {
   14.17 +	
   14.18 +	private SPARQLEndpoint endpoint; 
   14.19 +	private String query;
   14.20 +	
   14.21 +	@Before
   14.22 +	public void init() {
   14.23 +		// initialize endpoint
   14.24 +		endpoint = new SPARQLEndpoint("luna.di.uoa.gr", 8080, "sextant-endpoint/Update");
   14.25 +		
   14.26 +		// set url data
   14.27 +		query = "insert data" +
   14.28 +				"{graph <http://example.com/update> " +
   14.29 +				"{<http://example.com/map/map> <http://example.com/map/hasLayer>  <http://example.com/map/layer>}  }";
   14.30 +		
   14.31 +		endpoint.setUser("endpoint");
   14.32 +		endpoint.setPassword("3ndpo1nt");
   14.33 +		
   14.34 +				
   14.35 +	}
   14.36 +	
   14.37 +	/**
   14.38 +	 * Test method for {@link eu.earthobservatory.org.StrabonEndpoint.client.SPARQLEndpoint#update(java.net.URL, org.openrdf.rio.RDFFormat, java.net.URL)}.
   14.39 +	 * @throws IOException 
   14.40 +	 */
   14.41 +	@Test
   14.42 +	public void testUpdate() throws IOException {
   14.43 +		
   14.44 +			Boolean response = endpoint.update(query);
   14.45 +			
   14.46 +			if (response != true) 
   14.47 +				System.err.println("Error");
   14.48 +			
   14.49 +			
   14.50 +		//	assertTrue(response == true);
   14.51 +		
   14.52 +	}
   14.53 +
   14.54 +}
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/endpoint-client/src/test/java/eu/earthobservatory/org/StrabonEndpoint/client/TestSPARQLEndpointWithParliament.java	Fri May 02 17:39:27 2014 +0200
    15.3 @@ -0,0 +1,75 @@
    15.4 +///* This Source Code Form is subject to the terms of the Mozilla Public
    15.5 +// * License, v. 2.0. If a copy of the MPL was not distributed with this
    15.6 +// * file, You can obtain one at http://mozilla.org/MPL/2.0/.
    15.7 +// * 
    15.8 +// * Copyright (C) 2013, Pyravlos Team
    15.9 +// * 
   15.10 +// * http://www.strabon.di.uoa.gr/
   15.11 +// */
   15.12 +//package eu.earthobservatory.org.StrabonEndpoint.client;
   15.13 +//
   15.14 +//import static org.junit.Assert.assertTrue;
   15.15 +//
   15.16 +//import java.io.IOException;
   15.17 +//
   15.18 +//import org.junit.Before;
   15.19 +//import org.junit.Test;
   15.20 +//import org.openrdf.query.resultio.stSPARQLQueryResultFormat;
   15.21 +//
   15.22 +///**
   15.23 +// * @author Kallirroi Dogani <kallirroi@di.uoa.gr>
   15.24 +// *
   15.25 +// */
   15.26 +//
   15.27 +//public class TestSPARQLEndpointWithParliament {
   15.28 +//
   15.29 +//	private SPARQLEndpoint endpoint; 
   15.30 +//	private String query;
   15.31 +//	
   15.32 +//	@Before
   15.33 +//	public void init() {
   15.34 +//		// initialize endpoint
   15.35 +//		endpoint = new SPARQLEndpoint("luna.di.uoa.gr", 8080, "parliament/sparql");
   15.36 +//		
   15.37 +//		// set query
   15.38 +//		query = "PREFIX ex: <http://example.org/> \n" +
   15.39 +//				"SELECT ?k ?g WHERE {\n" +
   15.40 +//				" ex:pol1 ?k ?g\n" +
   15.41 +//				"}" +
   15.42 +//				"\nLIMIT 1";
   15.43 +//				
   15.44 +//	}
   15.45 +//	
   15.46 +//	/**
   15.47 +//	 * Test method for {@link eu.earthobservatory.org.StrabonEndpoint.client.SPARQLEndpoint#query(java.lang.String, org.openrdf.query.resultio.stSPARQLQueryResultFormat)}.
   15.48 +//	 */
   15.49 +//	@Test
   15.50 +//	public void testQuery() {
   15.51 +//			try {
   15.52 +//				EndpointResult response = endpoint.query(query, stSPARQLQueryResultFormat.XML);
   15.53 +//				
   15.54 +//				System.out.println(response.getResponse());
   15.55 +//				
   15.56 +//				if (response.getStatusCode() != 200) {
   15.57 +//					System.err.println("Status code ("+response.getStatusCode()+"):" + response.getStatusText());
   15.58 +//					
   15.59 +//				}
   15.60 +//				
   15.61 +//				assertTrue(response.getStatusCode() == 200);
   15.62 +//				
   15.63 +//			} catch (IOException e) {
   15.64 +//				e.printStackTrace();
   15.65 +//			}
   15.66 +//			
   15.67 +//	}
   15.68 +//	
   15.69 +//	/**
   15.70 +//	 * Test method for testing that method {@link eu.earthobservatory.org.StrabonEndpoint.client.SPARQLEndpoint#query(java.lang.String, org.openrdf.query.resultio.stSPARQLQueryResultFormat)}.
   15.71 +//	 * returns an IOException when it should do so.
   15.72 +//	 */
   15.73 +//	@Test(expected= IOException.class)
   15.74 +//	public void testIOException() throws Exception {
   15.75 +//		SPARQLEndpoint ep = new SPARQLEndpoint("blabla.dgr", 80, "bla");
   15.76 +//		ep.query(query, stSPARQLQueryResultFormat.XML);
   15.77 +//	}
   15.78 +//}
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/endpoint-client/src/test/java/eu/earthobservatory/org/StrabonEndpoint/client/TestSPARQLEndpointWithStrabon.java	Fri May 02 17:39:27 2014 +0200
    16.3 @@ -0,0 +1,91 @@
    16.4 +/**
    16.5 + * This Source Code Form is subject to the terms of the Mozilla Public
    16.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
    16.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/.
    16.8 + * 
    16.9 + * Copyright (C) 2012, Pyravlos Team
   16.10 + * 
   16.11 + * http://www.strabon.di.uoa.gr/
   16.12 + */
   16.13 +package eu.earthobservatory.org.StrabonEndpoint.client;
   16.14 +
   16.15 +import static org.junit.Assert.assertTrue;
   16.16 +
   16.17 +import java.io.IOException;
   16.18 +import java.util.Vector;
   16.19 +
   16.20 +import org.junit.Before;
   16.21 +import org.junit.Test;
   16.22 +import org.openrdf.query.resultio.TupleQueryResultFormat;
   16.23 +import org.openrdf.query.resultio.stSPARQLQueryResultFormat;
   16.24 +
   16.25 +/**
   16.26 + * @author Charalampos Nikolaou <charnik@di.uoa.gr>
   16.27 + *
   16.28 + */
   16.29 +public class TestSPARQLEndpointWithStrabon {
   16.30 +
   16.31 +	private SPARQLEndpoint endpoint; 
   16.32 +	private String query;
   16.33 +	private Vector<stSPARQLQueryResultFormat> formats = new Vector<stSPARQLQueryResultFormat>();
   16.34 +	
   16.35 +	@Before
   16.36 +	public void init() {
   16.37 +		// initialize endpoint
   16.38 +		endpoint = new SPARQLEndpoint("geo.linkedopendata.gr", 9090, "gag-endpoint/Query");
   16.39 +		
   16.40 +		// set query
   16.41 +		query = "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> " +
   16.42 +				"PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> " +
   16.43 +				"PREFIX gag: <http://geo.linkedopendata.gr/gag/ontology/> " +
   16.44 +
   16.45 +				"SELECT ?geometry " +
   16.46 +				"WHERE {" +
   16.47 +
   16.48 +  				"	?m rdf:type gag:Δήμος . " +
   16.49 +  				"	?m rdfs:label \"ΔΗΜΟΣ ΑΘΗΝΑΙΩΝ\" . " +
   16.50 +  				"	?m gag:έχει_γεωμετρία ?geometry. " +
   16.51 +				" } "  ;
   16.52 +		
   16.53 +		// initialized formats
   16.54 +		for (TupleQueryResultFormat format : stSPARQLQueryResultFormat.values()) {
   16.55 +				if (format instanceof stSPARQLQueryResultFormat) {
   16.56 +					formats.add((stSPARQLQueryResultFormat) format);
   16.57 +				}
   16.58 +		}
   16.59 +				
   16.60 +	}
   16.61 +	
   16.62 +	/**
   16.63 +	 * Test method for {@link eu.earthobservatory.org.StrabonEndpoint.client.SPARQLEndpoint#query(java.lang.String, org.openrdf.query.resultio.stSPARQLQueryResultFormat)}.
   16.64 +	 */
   16.65 +	@Test
   16.66 +	public void testQuery() {
   16.67 +		//for (stSPARQLQueryResultFormat format : formats) {
   16.68 +			try {
   16.69 +				EndpointResult response = endpoint.query(query, stSPARQLQueryResultFormat.XML);
   16.70 +				
   16.71 +				if (response.getStatusCode() != 200) {
   16.72 +					System.err.println("Status code ("+response.getStatusCode()+"):" + response.getStatusText());
   16.73 +					
   16.74 +				}
   16.75 +				
   16.76 +			//	assertTrue(response.getStatusCode() == 200);
   16.77 +
   16.78 +			} catch (IOException e) {
   16.79 +				e.printStackTrace();
   16.80 +			}
   16.81 +			
   16.82 +		//}
   16.83 +	}
   16.84 +	
   16.85 +	/**
   16.86 +	 * Test method for testing that method {@link eu.earthobservatory.org.StrabonEndpoint.client.SPARQLEndpoint#query(java.lang.String, org.openrdf.query.resultio.stSPARQLQueryResultFormat)}.
   16.87 +	 * returns an IOException when it should do so.
   16.88 +	 */
   16.89 +	@Test(expected= IOException.class)
   16.90 +	public void testIOException() throws Exception {
   16.91 +		SPARQLEndpoint ep = new SPARQLEndpoint("blabla.dgr", 80, "bla");
   16.92 +		ep.query(query, formats.get(0));
   16.93 +	}
   16.94 +}
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/endpoint-client/src/test/java/eu/earthobservatory/org/StrabonEndpoint/client/TestSPARQLEndpointWithVirtuoso.java	Fri May 02 17:39:27 2014 +0200
    17.3 @@ -0,0 +1,88 @@
    17.4 +/**
    17.5 + * This Source Code Form is subject to the terms of the Mozilla Public
    17.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
    17.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/.
    17.8 + * 
    17.9 + * Copyright (C) 2013, Pyravlos Team
   17.10 + * 
   17.11 + * http://www.strabon.di.uoa.gr/
   17.12 + */
   17.13 +package eu.earthobservatory.org.StrabonEndpoint.client;
   17.14 +
   17.15 +import static org.junit.Assert.assertTrue;
   17.16 +
   17.17 +import java.io.IOException;
   17.18 +import java.util.Vector;
   17.19 +
   17.20 +import org.junit.Before;
   17.21 +import org.junit.Test;
   17.22 +import org.openrdf.query.resultio.TupleQueryResultFormat;
   17.23 +import org.openrdf.query.resultio.stSPARQLQueryResultFormat;
   17.24 +
   17.25 +/**
   17.26 + * @author Kallirroi Dogani <kallirroi@di.uoa.gr>
   17.27 + *
   17.28 + */
   17.29 +
   17.30 +//Virtuso endpoint also needs to be tested for all formats included in stSPARQLQueryResultFormat
   17.31 +//because some of them are not supported
   17.32 +public class TestSPARQLEndpointWithVirtuoso {
   17.33 +
   17.34 +	private SPARQLEndpoint endpoint; 
   17.35 +	private String query;
   17.36 +	private Vector<stSPARQLQueryResultFormat> formats = new Vector<stSPARQLQueryResultFormat>();
   17.37 +	
   17.38 +	@Before
   17.39 +	public void init() {
   17.40 +		// initialize endpoint
   17.41 +		endpoint = new SPARQLEndpoint("dbpedia.org", 8890, "sparql");
   17.42 +		
   17.43 +		// set query
   17.44 +		query = "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n" +
   17.45 +				"SELECT ?x ?y WHERE {\n" +
   17.46 +				" ?x rdf:type ?y\n" +
   17.47 +				"}" +
   17.48 +				"\nLIMIT 10";
   17.49 +		
   17.50 +		// initialized formats
   17.51 +		for (TupleQueryResultFormat format : stSPARQLQueryResultFormat.values()) {
   17.52 +				if (format instanceof stSPARQLQueryResultFormat) {
   17.53 +					formats.add((stSPARQLQueryResultFormat) format);
   17.54 +				}
   17.55 +		}
   17.56 +				
   17.57 +	}
   17.58 +	
   17.59 +	/**
   17.60 +	 * Test method for {@link eu.earthobservatory.org.StrabonEndpoint.client.SPARQLEndpoint#query(java.lang.String, org.openrdf.query.resultio.stSPARQLQueryResultFormat)}.
   17.61 +	 */
   17.62 +	@Test
   17.63 +	public void testQuery() {
   17.64 +			try {
   17.65 +				EndpointResult response = endpoint.query(query, stSPARQLQueryResultFormat.TSV);
   17.66 +				
   17.67 +			//	System.out.println(response.getResponse());
   17.68 +				
   17.69 +				if (response.getStatusCode() != 200) {
   17.70 +					System.err.println("Status code ("+response.getStatusCode()+"):" + response.getStatusText());
   17.71 +					
   17.72 +				}
   17.73 +				
   17.74 +			//	assertTrue(response.getStatusCode() == 200);
   17.75 +				
   17.76 +			} catch (IOException e) {
   17.77 +				e.printStackTrace();
   17.78 +			}
   17.79 +			
   17.80 +	}
   17.81 +	
   17.82 +	/**
   17.83 +	 * Test method for testing that method {@link eu.earthobservatory.org.StrabonEndpoint.client.SPARQLEndpoint#query(java.lang.String, org.openrdf.query.resultio.stSPARQLQueryResultFormat)}.
   17.84 +	 * returns an IOException when it should do so.
   17.85 +	 */
   17.86 +	@Test(expected= IOException.class)
   17.87 +	public void testIOException() throws Exception {
   17.88 +		SPARQLEndpoint ep = new SPARQLEndpoint("blabla.dgr", 80, "bla");
   17.89 +		ep.query(query, formats.get(0));
   17.90 +	}
   17.91 +}
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/endpoint-client/src/test/java/eu/earthobservatory/org/StrabonEndpoint/client/TestSpatialEndpoint.java	Fri May 02 17:39:27 2014 +0200
    18.3 @@ -0,0 +1,82 @@
    18.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
    18.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
    18.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/.
    18.7 + * 
    18.8 + * Copyright (C) 2013, Pyravlos Team
    18.9 + * 
   18.10 + * http://www.strabon.di.uoa.gr/
   18.11 + */
   18.12 +package eu.earthobservatory.org.StrabonEndpoint.client;
   18.13 +
   18.14 +import static org.junit.Assert.assertTrue;
   18.15 +
   18.16 +import java.io.IOException;
   18.17 +
   18.18 +import org.junit.Before;
   18.19 +import org.junit.Test;
   18.20 +import org.openrdf.query.QueryEvaluationException;
   18.21 +import org.openrdf.query.TupleQueryResultHandlerException;
   18.22 +import org.openrdf.query.resultio.QueryResultParseException;
   18.23 +import org.openrdf.query.resultio.UnsupportedQueryResultFormatException;
   18.24 +
   18.25 +/**
   18.26 + * @author Kallirroi Dogani <kallirroi@di.uoa.gr>
   18.27 + *
   18.28 + */
   18.29 +
   18.30 +public class TestSpatialEndpoint {
   18.31 +
   18.32 +	private SpatialEndpoint endpoint;
   18.33 +	private String query;
   18.34 +	
   18.35 +	@Before
   18.36 +	public void init() {
   18.37 +		// initialize endpoint
   18.38 +		endpoint = new SpatialEndpoint("geo.linkedopendata.gr", 9090, "corine-endpoint/Query");
   18.39 +		
   18.40 +		// set query
   18.41 +		query = "PREFIX corine: <http://geo.linkedopendata.gr/corine/ontology#> \n"+
   18.42 +				"SELECT ?geometry \n" +
   18.43 +				 "WHERE {\n " + 
   18.44 +				 "  ?area corine:hasLandUse corine:burntAreas . \n" +
   18.45 +				 "  ?area corine:hasGeometry ?geometry .  } \n" +
   18.46 +				 "LIMIT 2" ;              
   18.47 +	}
   18.48 +	
   18.49 +	/**
   18.50 +	 * Test method for {@link eu.earthobservatory.org.StrabonEndpoint.client.SpatialEndpoint#query(java.lang.String, org.openrdf.query.resultio.stSPARQLQueryResultFormat)}.
   18.51 +	 * @throws TupleQueryResultHandlerException 
   18.52 +	 */
   18.53 +	@Test
   18.54 +	public void testQuery() {
   18.55 +			try {
   18.56 +					EndpointResult response;
   18.57 +				
   18.58 +					response = endpoint.queryForKML(query); 
   18.59 +					
   18.60 +					//System.out.println("KML format:");
   18.61 +					//System.out.println(response.getResponse());
   18.62 +					
   18.63 +					if (response.getStatusCode() != 200) {
   18.64 +						System.err.println("Status code ("+response.getStatusCode()+"):" + response.getStatusText());
   18.65 +						
   18.66 +					}
   18.67 +					
   18.68 +				//	assertTrue(response.getStatusCode() == 200);	
   18.69 +				
   18.70 +				}catch (QueryResultParseException e) {
   18.71 +					e.printStackTrace();
   18.72 +				} catch (UnsupportedQueryResultFormatException e) {
   18.73 +					e.printStackTrace();
   18.74 +				}
   18.75 +				catch (TupleQueryResultHandlerException e) {
   18.76 +					e.printStackTrace();
   18.77 +				}
   18.78 +				catch (IOException e) {
   18.79 +					e.printStackTrace();
   18.80 +				} catch (QueryEvaluationException e) {
   18.81 +					e.printStackTrace();
   18.82 +				}
   18.83 +			
   18.84 +	}
   18.85 +}
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/endpoint-exec/pom.xml	Fri May 02 17:39:27 2014 +0200
    19.3 @@ -0,0 +1,98 @@
    19.4 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    19.5 +
    19.6 +	<modelVersion>4.0.0</modelVersion>
    19.7 +
    19.8 +	<parent>
    19.9 +		<groupId>eu.earthobservatory</groupId>
   19.10 +		<artifactId>strabon</artifactId>
   19.11 +		<version>3.2.10-SNAPSHOT</version>
   19.12 +	</parent>
   19.13 +
   19.14 +	<artifactId>strabon-endpoint-exec</artifactId>
   19.15 +
   19.16 +	<name>Strabon: Executable endpoint</name>
   19.17 +	<description>A Strabon endpoint packaged with Tomcat 7 as a single executable jar file</description>
   19.18 +	<packaging>pom</packaging>
   19.19 +
   19.20 +	<dependencies>
   19.21 +		<dependency>
   19.22 +			<groupId>eu.earthobservatory</groupId>
   19.23 +			<artifactId>strabon-endpoint</artifactId>
   19.24 +			<version>${eu.earthobservatory.version}</version>
   19.25 +			<type>war</type>
   19.26 +			<scope>compile</scope>
   19.27 +		</dependency>
   19.28 +	</dependencies>
   19.29 +
   19.30 +	<build>
   19.31 +		<plugins>
   19.32 +			<plugin>
   19.33 +				<groupId>org.apache.tomcat.maven</groupId>
   19.34 +				<artifactId>tomcat7-maven-plugin</artifactId>
   19.35 +				<version>2.0</version>
   19.36 +				<executions>
   19.37 +					<execution>
   19.38 +						<id>tomcat-run</id>
   19.39 +						<goals>
   19.40 +							<goal>exec-war-only</goal>
   19.41 +						</goals>
   19.42 +						<phase>package</phase>
   19.43 +						<configuration>
   19.44 +							<path>/</path>
   19.45 +							<uriEncoding>UTF-8</uriEncoding>
   19.46 +							<finalName>strabon-endpoint-executable-${project.version}.jar</finalName>
   19.47 +							<!-- Override the default server.xml if nessecary
   19.48 +							<serverXml>src/main/tomcatconf/server.xml</serverXml>
   19.49 +							-->
   19.50 +							<!--
   19.51 +							<extraResources>
   19.52 +								<extraResource>
   19.53 +									<directory>${basedir}/src/main/resources</directory>
   19.54 +									<includes>
   19.55 +										<include>**/log4j.xml</include>
   19.56 +									</includes>
   19.57 +								</extraResource>
   19.58 +							</extraResources>
   19.59 +							-->
   19.60 +							<warRunDependencies>
   19.61 +								<warRunDependency>
   19.62 +									<dependency>
   19.63 +										<groupId>eu.earthobservatory</groupId>
   19.64 +										<artifactId>strabon-endpoint</artifactId>
   19.65 +										<version>${eu.earthobservatory.version}</version>
   19.66 +										<type>war</type>
   19.67 +									</dependency>
   19.68 +									<contextPath>/</contextPath>
   19.69 +								</warRunDependency>
   19.70 +							</warRunDependencies>
   19.71 +							<!--
   19.72 +							<extraDependencies>
   19.73 +								<extraDependency>
   19.74 +									<groupId>org.slf4j</groupId>
   19.75 +									<artifactId>jul-to-slf4j</artifactId>
   19.76 +									<version>${slf4jVersion}</version>
   19.77 +								</extraDependency>
   19.78 +								<extraDependency>
   19.79 +									<groupId>org.slf4j</groupId>
   19.80 +									<artifactId>slf4j-api</artifactId>
   19.81 +									<version>${slf4jVersion}</version>
   19.82 +								</extraDependency>
   19.83 +								<extraDependency>
   19.84 +									<groupId>org.slf4j</groupId>
   19.85 +									<artifactId>slf4j-log4j12</artifactId>
   19.86 +									<version>${slf4jVersion}</version>
   19.87 +								</extraDependency>
   19.88 +								<extraDependency>
   19.89 +									<groupId>log4j</groupId>
   19.90 +									<artifactId>log4j</artifactId>
   19.91 +									<version>1.2.12</version>
   19.92 +								</extraDependency>	
   19.93 +							</extraDependencies>
   19.94 +							-->
   19.95 +						</configuration>
   19.96 +					</execution>
   19.97 +				</executions>
   19.98 +			</plugin>
   19.99 +		</plugins>
  19.100 +	</build>
  19.101 +</project>
    20.1 --- a/endpoint/WebContent/WEB-INF/beans.xml	Fri May 02 17:27:46 2014 +0200
    20.2 +++ b/endpoint/WebContent/WEB-INF/beans.xml	Fri May 02 17:39:27 2014 +0200
    20.3 @@ -6,6 +6,23 @@
    20.4  		xmlns:jaxws="http://cxf.apache.org/jaxws"
    20.5  		jaxws:schemaLocation="http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
    20.6  
    20.7 +	<bean id="serverProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    20.8 +		<property name="locations">
    20.9 +			<list>
   20.10 +				<value>WEB-INF/connection.properties</value>
   20.11 +			</list>
   20.12 +		</property>
   20.13 +	</bean>
   20.14 +  
   20.15 +	<bean id="capsBean" class="eu.earthobservatory.org.StrabonEndpoint.capabilities.CapabilitiesDelegateBean" destroy-method="destroy">
   20.16 +		<!-- specify which implementation of the Capabilities interface shall be used -->
   20.17 +		<!-- true : AutoDiscoveryCapabilities -->
   20.18 +		<!-- false: EndpointCapabilities -->
   20.19 +		<constructor-arg type="boolean">
   20.20 +            <value>false</value>
   20.21 +        </constructor-arg>
   20.22 +	</bean>
   20.23 +	
   20.24      <bean
   20.25          id="strabonBean"
   20.26          class="eu.earthobservatory.org.StrabonEndpoint.StrabonBeanWrapper"
   20.27 @@ -13,27 +30,27 @@
   20.28  
   20.29          <constructor-arg type="java.lang.String" >
   20.30              <!-- Database name -->
   20.31 -            <value>endpoint</value>
   20.32 +            <value>${dbname}</value>
   20.33          </constructor-arg>
   20.34  
   20.35          <constructor-arg type="java.lang.String" >
   20.36              <!-- Username -->
   20.37 -            <value>postgres</value>
   20.38 +            <value>${username}</value>
   20.39          </constructor-arg>
   20.40  
   20.41          <constructor-arg type="java.lang.String" >
   20.42              <!-- Password -->
   20.43 -	    <value>postgres</value>
   20.44 +	    <value>${password}</value>
   20.45          </constructor-arg>
   20.46  
   20.47          <constructor-arg type="int" >
   20.48              <!-- Port -->
   20.49 -            <value>5432</value>
   20.50 +            <value>${port}</value>
   20.51          </constructor-arg>
   20.52  
   20.53          <constructor-arg type="java.lang.String" >
   20.54              <!-- Database server -->
   20.55 -            <value>localhost</value>
   20.56 +            <value>${hostname}</value>
   20.57          </constructor-arg>
   20.58  
   20.59          <constructor-arg type="boolean" >
   20.60 @@ -43,317 +60,212 @@
   20.61  
   20.62          <constructor-arg type="java.lang.String" >
   20.63              <!-- Database Backend (either "postgis" or "monetdb") -->
   20.64 -            <value>postgis</value>
   20.65 +            <value>${dbengine}</value>
   20.66          </constructor-arg>
   20.67          
   20.68 -         <constructor-arg>
   20.69 +        <constructor-arg type="int" >
   20.70 +            <!-- Query limit -->
   20.71 +            <value>0</value>
   20.72 +        </constructor-arg>
   20.73 +        
   20.74 +        <constructor-arg type="boolean" >
   20.75 +            <!-- Load from File -->
   20.76 +            <value>true</value>
   20.77 +        </constructor-arg>
   20.78 +     
   20.79 +     	<!-- Boolean variable linkURL in stSPARQLResultsHTMLWriter.java (line 115) to change the links between web and describe -->
   20.80 +        
   20.81 +        <constructor-arg type="java.lang.String" >
   20.82 +            <!-- Default prefixes -->
   20.83 +            <!-- PREFIX gag: <http://teleios.di.uoa.gr/ontologies/gagKallikratis.rdf#> -->
   20.84 +            <value><![CDATA[PREFIX lgd:<http://linkedgeodata.org/triplify/>
   20.85 +PREFIX lgdgeo:<http://www.w3.org/2003/01/geo/wgs84_pos#>
   20.86 +PREFIX lgdont:<http://linkedgeodata.org/ontology/>
   20.87 +PREFIX geonames:<http://www.geonames.org/ontology#>
   20.88 +PREFIX clc: <http://geo.linkedopendata.gr/corine/ontology#>
   20.89 +PREFIX gag: <http://geo.linkedopendata.gr/greekadministrativeregion/ontology#>
   20.90 +PREFIX geo: <http://www.opengis.net/ont/geosparql#>
   20.91 +PREFIX geof: <http://www.opengis.net/def/function/geosparql/>
   20.92 +PREFIX geor: <http://www.opengis.net/def/rule/geosparql/>
   20.93 +PREFIX strdf: <http://strdf.di.uoa.gr/ontology#>
   20.94 +PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
   20.95 +PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
   20.96 +PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
   20.97 +]]>
   20.98 +</value>
   20.99 +        </constructor-arg>
  20.100 +        
  20.101 +        <constructor-arg>
  20.102               <list>
  20.103 -	             <list>
  20.104 +             	<list>
  20.105 +             		<!-- Single valued elements correspond to headers -->
  20.106 +					<value>Discovery Queries</value>
  20.107 +	            </list>
  20.108 +				<list>
  20.109  	                 <!-- Bean -->
  20.110  	                <value>Query</value> 
  20.111  	                <!-- Format -->
  20.112  	                <value>HTML</value>   
  20.113  	                <!-- Label -->
  20.114 -	                <value>Query 1: Discover raw data and products</value> 
  20.115 +	                <value>Find all triples in the dataset.</value> 
  20.116  	                <!-- Statement -->
  20.117 -	                <value><![CDATA[# Discovering raw data and products
  20.118 -PREFIX noa: <http://teleios.di.uoa.gr/ontologies/noaOntology.owl#>
  20.119 -PREFIX clc: <http://teleios.di.uoa.gr/ontologies/clcOntology.owl#>
  20.120 -PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
  20.121 -PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
  20.122 -PREFIX strdf: <http://strdf.di.uoa.gr/ontology#>
  20.123 -PREFIX teleios: <http://teleios.di.uoa.gr/ontologies/noaOntology.owl#>
  20.124 -PREFIX gag: <http://www.semanticweb.org/ontologies/2011/gagKallikratis.rdf#>
  20.125 -PREFIX geo: <http://www.w3.org/2003/01/geo/wgs84_pos#>
  20.126 -PREFIX georss: <http://www.georss.org/georss/>
  20.127 -PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
  20.128 -PREFIX lgdo: <http://linkedgeodata.org/ontology/>
  20.129 -PREFIX gn: <http://www.geonames.org/ontology#>
  20.130 -
  20.131 -SELECT ?filename
  20.132 -WHERE {?file rdf:type noa:ShpFile ;
  20.133 -	         noa:hasFilename ?filename ;
  20.134 -	         noa:hasAcquisitionTime ?sensingTime .
  20.135 -	 FILTER( str(?sensingTime) >= "2007-08-26T12:00:00" ) .
  20.136 -	 FILTER( str(?sensingTime) <= "2007-08-26T12:30:00" ) .
  20.137 -	 ?file noa:isDerivedFromSensor ?sensor .
  20.138 -	 FILTER( str(?sensor) = "MSG2" ) .
  20.139 -	 ?file noa:producedFromProcessingChain ?chain .
  20.140 -	 FILTER( str(?chain) = "StaticThresholds" ) . 
  20.141 -}]]></value>
  20.142 -<value>Find all shapefiles derived from sensor MSG2 between [2007-08-26T12:00:00,2007-08-26T12:30:00], using dynamic thresholds.</value>
  20.143 +	                <value><![CDATA[
  20.144 +SELECT *
  20.145 +WHERE { 
  20.146 +	?s ?p ?o	
  20.147 +}
  20.148 +]]></value>
  20.149 +	                <!-- Description -->
  20.150 +					<value></value>
  20.151 +					<!-- Hander (plain, download, map or map_local)-->
  20.152 +					<value>Plain</value>
  20.153  	            </list>
  20.154  	            <list>
  20.155 -	                <!-- Bean -->
  20.156 +	                 <!-- Bean -->
  20.157  	                <value>Query</value> 
  20.158  	                <!-- Format -->
  20.159 -	                <value>KMZMAP</value>
  20.160 +	                <value>HTML</value>   
  20.161  	                <!-- Label -->
  20.162 -	                <value>Query 2: Discover Hotspots</value> 
  20.163 +	                <value>Select all distinct subjects that appear in the dataset.</value> 
  20.164  	                <!-- Statement -->
  20.165 -	                <value><![CDATA[# Get all hotspots 
  20.166 -# - in Pelloponesus 
  20.167 -# - at 2007-08-24
  20.168 -PREFIX noa: <http://teleios.di.uoa.gr/ontologies/noaOntology.owl#>
  20.169 -PREFIX clc: <http://teleios.di.uoa.gr/ontologies/clcOntology.owl#>
  20.170 -PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
  20.171 -PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
  20.172 -PREFIX strdf: <http://strdf.di.uoa.gr/ontology#>
  20.173 -PREFIX teleios: <http://teleios.di.uoa.gr/ontologies/noaOntology.owl#>
  20.174 -PREFIX gag: <http://www.semanticweb.org/ontologies/2011/gagKallikratis.rdf#>
  20.175 -PREFIX geo: <http://www.w3.org/2003/01/geo/wgs84_pos#>
  20.176 -PREFIX georss: <http://www.georss.org/georss/>
  20.177 -PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
  20.178 -PREFIX lgdo: <http://linkedgeodata.org/ontology/>
  20.179 -PREFIX gn: <http://www.geonames.org/ontology#>
  20.180 +	                <value><![CDATA[
  20.181 +SELECT DISTINCT (?s AS ?subject)
  20.182 +WHERE { 
  20.183 +	?s ?p ?o
  20.184 +}
  20.185 +]]></value>
  20.186 +	                <!-- Description -->
  20.187 +					<value></value>
  20.188 +					<!-- Hander (plain, download, map or map_local)-->
  20.189 +					<value>Plain</value>
  20.190 +	            </list>
  20.191 +	            <list>
  20.192 +	                 <!-- Bean -->
  20.193 +	                <value>Query</value> 
  20.194 +	                <!-- Format -->
  20.195 +	                <value>HTML</value>   
  20.196 +	                <!-- Label -->
  20.197 +	                <value>Select all distinct predicates that appear in the dataset.</value> 
  20.198 +	                <!-- Statement -->
  20.199 +	                <value><![CDATA[
  20.200 +SELECT DISTINCT (?p AS ?predicate)
  20.201 +WHERE { 
  20.202 +	?s ?p ?o
  20.203 +}
  20.204 +]]></value>
  20.205 +	                <!-- Description -->
  20.206 +					<value></value>
  20.207 +					<!-- Hander (plain, download, map or map_local)-->
  20.208 +					<value>Plain</value>
  20.209 +	            </list>
  20.210 +	            
  20.211 +	            <list>
  20.212 +	                 <!-- Bean -->
  20.213 +	                <value>Query</value> 
  20.214 +	                <!-- Format -->
  20.215 +	                <value>HTML</value>   
  20.216 +	                <!-- Label -->
  20.217 +	                <value>Select all distinct objets that appear in the dataset.</value> 
  20.218 +	                <!-- Statement -->
  20.219 +	                <value><![CDATA[
  20.220 +SELECT DISTINCT (?o AS ?object)
  20.221 +WHERE { 
  20.222 +	?s ?p ?o	
  20.223 +}
  20.224 +]]></value>
  20.225 +	                <!-- Description -->
  20.226 +					<value></value>
  20.227 +					<!-- Hander (plain, download, map or map_local)-->
  20.228 +					<value>Plain</value>
  20.229 +	            </list>
  20.230 +	            <list>
  20.231 +	                 <!-- Bean -->
  20.232 +	                <value>Query</value> 
  20.233 +	                <!-- Format -->
  20.234 +	                <value>HTML</value>   
  20.235 +	                <!-- Label -->
  20.236 +	                <value>Find all distinct classes of the dataset.</value> 
  20.237 +	                <!-- Statement -->
  20.238 +	                <value><![CDATA[PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>	                
  20.239  
  20.240 -SELECT ?h ?hAcqTime ?hConfidence ?hConfirmation ?hProvider ?hSensor ?hSatellite (strdf:transform(?hGeo, <http://www.opengis.net/def/crs/EPSG/0/4326>) as ?geo) 
  20.241 -WHERE { ?h 	rdf:type noa:Hotspot;
  20.242 -			noa:hasGeometry ?hGeo;
  20.243 -			noa:hasAcquisitionTime ?hAcqTime;
  20.244 -			noa:hasConfidence ?hConfidence;
  20.245 -			noa:isProducedBy ?hProvider;
  20.246 -			noa:hasConfirmation ?hConfirmation;
  20.247 -			noa:isDerivedFromSensor ?hSensor;
  20.248 -			noa:isDerivedFromSatellite ?hSatellite ;
  20.249 -			noa:producedFromProcessingChain ?hChain .
  20.250 -	FILTER(str(?hChain) = "StaticThresholds").
  20.251 -	FILTER(?hAcqTime = "2007-08-24T14:45:00"^^xsd:dateTime) .
  20.252 -	FILTER(strdf:contains("POLYGON((21.027 38.36, 23.77 38.36, 23.77 36.05, 21.027 36.05, 21.027 38.36))"^^ strdf:WKT, ?hGeo)) . 
  20.253 -}]]></value>
  20.254 -<value>Find all hotspots in Pelloponesus derived from the dynamic thresholds processing chain at 2007-08-24T14:45:00.  </value>
  20.255 +SELECT DISTINCT (?o AS ?class)
  20.256 +WHERE { 
  20.257 +	?s rdf:type ?o
  20.258 +}
  20.259 +]]></value>
  20.260 +	                <!-- Description -->
  20.261 +					<value></value>
  20.262 +					<!-- Hander (plain, download, map or map_local)-->
  20.263 +					<value>Plain</value>
  20.264 +	            </list>
  20.265 +	            
  20.266 +	        	<list>
  20.267 +	                 <!-- Bean -->
  20.268 +	                <value>Query</value> 
  20.269 +	                <!-- Format -->
  20.270 +	                <value>HTML</value>   
  20.271 +	                <!-- Label -->
  20.272 +	                <value>Find the number of triples that appear in the dataset.</value> 
  20.273 +	                <!-- Statement -->
  20.274 +	                <value><![CDATA[SELECT (COUNT(?s) AS ?NumOfTriples)
  20.275 +WHERE { 
  20.276 +	?s ?p ?o
  20.277 +}
  20.278 +]]></value>
  20.279 +	                <!-- Description -->
  20.280 +					<value></value>
  20.281 +					<!-- Hander (plain, download, map or map_local)-->
  20.282 +					<value>Plain</value>
  20.283 +	            </list>
  20.284 +	            <list>
  20.285 +	                 <!-- Bean -->
  20.286 +	                <value>Query</value> 
  20.287 +	                <!-- Format -->
  20.288 +	                <value>HTML</value>   
  20.289 +	                <!-- Label -->
  20.290 +	                <value>Present the first ten triples of the dataset.</value> 
  20.291 +	                <!-- Statement -->
  20.292 +	                <value><![CDATA[SELECT *
  20.293 +WHERE { 
  20.294 +	?s ?p ?o
  20.295 +}
  20.296 +LIMIT 10
  20.297 +]]></value>
  20.298 +	                <!-- Description -->
  20.299 +					<value></value>
  20.300 +					<!-- Hander (plain, download, map or map_local)-->
  20.301 +					<value>Plain</value>
  20.302 +	            </list>      
  20.303 +
  20.304 +				<list>
  20.305 +             		<!-- Single valued elements correspond to headers -->
  20.306 +					<value>Explore/Modify operations</value>
  20.307 +	            </list>
  20.308 +	            <list>
  20.309 +             		<!-- Link to bean: two arguemnts -->
  20.310 +					<value>Store</value>
  20.311 +					<value>store.jsp</value>
  20.312 +	            </list>
  20.313 +	            <list>
  20.314 +             		<!-- Link to bean: two arguemnts -->
  20.315 +					<value>Query/Update</value>
  20.316 +					<value>query.jsp</value>
  20.317 +	            </list>
  20.318 +	            <list>
  20.319 +             		<!-- Link to bean: two arguemnts -->
  20.320 +					<value>Describe</value>
  20.321 +					<value>describe.jsp</value>
  20.322 +	            </list>
  20.323 +	            <list>
  20.324 +             		<!-- Link to bean: two arguemnts -->
  20.325 +					<value>Browse</value>
  20.326 +					<value>browse.jsp</value>
  20.327  	            </list>
  20.328  				<list>
  20.329 -	                <!-- Bean -->
  20.330 -	                 <value>Update</value>
  20.331 -	                <!-- Format -->
  20.332 -	                <value>HTML</value>
  20.333 -	                <!-- Label -->
  20.334 -	                <value>Update A: Invalidate hotspots in sea</value> 
  20.335 -	                <!-- Statement -->
  20.336 -	                <value><![CDATA[# Delete hotspots that lie in sea
  20.337 -PREFIX noa: <http://teleios.di.uoa.gr/ontologies/noaOntology.owl#>
  20.338 -PREFIX clc: <http://teleios.di.uoa.gr/ontologies/clcOntology.owl#>
  20.339 -PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
  20.340 -PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
  20.341 -PREFIX strdf: <http://strdf.di.uoa.gr/ontology#>
  20.342 -PREFIX teleios: <http://teleios.di.uoa.gr/ontologies/noaOntology.owl#>
  20.343 -PREFIX gag: <http://www.semanticweb.org/ontologies/2011/gagKallikratis.rdf#>
  20.344 -PREFIX geo: <http://www.w3.org/2003/01/geo/wgs84_pos#>
  20.345 -PREFIX georss: <http://www.georss.org/georss/>
  20.346 -PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
  20.347 -PREFIX lgdo: <http://linkedgeodata.org/ontology/>
  20.348 -PREFIX gn: <http://www.geonames.org/ontology#>
  20.349 -DELETE {?h ?property ?object}
  20.350 -WHERE { ?h 	rdf:type noa:Hotspot;
  20.351 -            noa:hasAcquisitionTime ?hAcqTime;
  20.352 -            noa:producedFromProcessingChain ?hChain;
  20.353 -            noa:hasGeometry ?hGeo;
  20.354 -            ?property ?object.
  20.355 -        FILTER(str(?hChain) = "StaticThresholds").
  20.356 -        FILTER(strdf:contains("POLYGON((21.027 38.36, 23.77 38.36, 23.77 36.05, 21.027 36.05, 21.027 38.36))"^^ strdf:WKT, ?hGeo)).
  20.357 -        FILTER("2007-08-24T14:45:00"^^xsd:dateTime = ?hAcqTime).
  20.358 -        OPTIONAL {
  20.359 -            ?c rdf:type noa:Coastline;
  20.360 -               noa:hasGeometry ?cGeo.
  20.361 -            FILTER(strdf:contains("POLYGON((21.027 38.36, 23.77 38.36, 23.77 36.05, 21.027 36.05, 21.027 38.36))"^^ strdf:WKT, ?cGeo)).
  20.362 -            FILTER(strdf:anyInteract(?hGeo, ?cGeo)) . 
  20.363 -        }
  20.364 -        FILTER(!bound(?c)). 
  20.365 -}]]></value>
  20.366 -<value>Mark as invalid all hotspots produced by the static thresholds processing chain and are acquired at 2007-08-24T14:45:00 which are located in the sea</value>
  20.367 -	            </list>
  20.368 -	            <list>
  20.369 -	                <!-- Bean -->
  20.370 -	                <value>Update</value> 
  20.371 -	                <!-- Format -->
  20.372 -	                <value>HTML</value>
  20.373 -	                <!-- Label -->
  20.374 -	                <value>Update B: Refine hotspots in sea</value>
  20.375 -	                <!-- Statement -->
  20.376 -	                <value><![CDATA[# Refine the geometry of hotspots that partially lie in sea
  20.377 -PREFIX noa: <http://teleios.di.uoa.gr/ontologies/noaOntology.owl#> 
  20.378 -PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> 
  20.379 -PREFIX strdf: <http://strdf.di.uoa.gr/ontology#> 
  20.380 -PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> 
  20.381 -
  20.382 -
  20.383 -INSERT { ?h noa:isDiscarded "1"^^xsd:int . 
  20.384 -	 ?valid rdf:type noa:Hotspot ;
  20.385 -		noa:hasConfidence ?conf ;
  20.386 -	        noa:hasGeometry ?dif ;
  20.387 -		noa:hasAcquisitionTime "TIMESTAMP"^^xsd:dateTime ; 
  20.388 -	        noa:isDerivedFromSensor "SENSOR"^^xsd:string ;
  20.389 -		noa:hasConfirmation noa:unknown ;
  20.390 -	        noa:producedFromProcessingChain "PROCESSING_CHAIN"^^xsd:string ; 
  20.391 -		noa:isProducedBy noa:noa ;
  20.392 -		noa:isDerivedFromSatellite ?sat .
  20.393 -}
  20.394 -WHERE { 
  20.395 -  SELECT DISTINCT ?h ?hGeo (strdf:intersection(?hGeo, strdf:union(?cGeo)) AS ?dif) (BNODE() AS ?valid) ?conf ?sat
  20.396 -  WHERE { 
  20.397 -    ?h rdf:type noa:Hotspot ; 
  20.398 -       noa:hasAcquisitionTime ?hAcqTime ; 
  20.399 -       noa:producedFromProcessingChain "PROCESSING_CHAIN"^^xsd:string ; 
  20.400 -       noa:isDerivedFromSensor "SENSOR"^^xsd:string ;
  20.401 -       noa:hasGeometry ?hGeo ;
  20.402 -       noa:hasConfidence ?conf ;
  20.403 -       noa:isDerivedFromSatellite ?sat .
  20.404 -    FILTER("TIMESTAMP"^^xsd:dateTime = ?hAcqTime) .
  20.405 -    ?c rdf:type noa:Coastline ;
  20.406 -       noa:hasGeometry ?cGeo .
  20.407 -    FILTER(strdf:anyInteract(?hGeo, ?cGeo)) . 
  20.408 -  }
  20.409 -  GROUP BY ?h ?hGeo ?conf ?sat
  20.410 -  HAVING strdf:overlap(?hGeo, strdf:union(?cGeo))
  20.411 -}
  20.412 -]]></value>
  20.413 -	      <value>Refine hotspots acquired at 2007-08-24T14:45:00 removing the part that lies in the sea. </value>
  20.414 -	            </list>
  20.415 -	            <list>
  20.416 -	                <!-- Bean -->
  20.417 -	                <value>Query</value> 
  20.418 -	                <!-- Format -->
  20.419 -	                <value>KMZMAP</value>
  20.420 -	                <!-- Label -->
  20.421 -	                <value>Query 3: Discover coniferous forests</value> 
  20.422 -	                <!-- Statement -->
  20.423 -	                <value><![CDATA[#Get all coniferous forests in Peloponnese
  20.424 -PREFIX noa: <http://teleios.di.uoa.gr/ontologies/noaOntology.owl#>
  20.425 -PREFIX clc: <http://teleios.di.uoa.gr/ontologies/clcOntology.owl#>
  20.426 -PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
  20.427 -PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
  20.428 -PREFIX strdf: <http://strdf.di.uoa.gr/ontology#>
  20.429 -PREFIX teleios: <http://teleios.di.uoa.gr/ontologies/noaOntology.owl#>
  20.430 -PREFIX gag: <http://www.semanticweb.org/ontologies/2011/gagKallikratis.rdf#>
  20.431 -PREFIX geo: <http://www.w3.org/2003/01/geo/wgs84_pos#>
  20.432 -PREFIX georss: <http://www.georss.org/georss/>
  20.433 -PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
  20.434 -PREFIX lgdo: <http://linkedgeodata.org/ontology/>
  20.435 -PREFIX gn: <http://www.geonames.org/ontology#>
  20.436 -
  20.437 -SELECT ?a ?aGeo
  20.438 -WHERE{ ?a rdf:type clc:Area;
  20.439 -          clc:hasLandUse ?aLandUse;
  20.440 -          noa:hasGeometry ?aGeo.
  20.441 -       ?aLandUse rdf:type ?aLandUseType.
  20.442 -       FILTER(?aLandUseType = clc:ConiferousForest).
  20.443 -       FILTER(strdf:contains("POLYGON((21.027 38.36, 23.77 38.36, 23.77 36.05, 21.027 36.05, 21.027 38.36))"^^strdf:WKT,?aGeo)). 
  20.444 -}]]></value>
  20.445 -<value>Discover all coniferous forests using the clc ontology </value>
  20.446 -	            </list>
  20.447 -	            <list>
  20.448 -	                <!-- Bean -->
  20.449 -	                <value>Query</value> 
  20.450 -	                <!-- Format -->
  20.451 -	                <value>KMZMAP</value>
  20.452 -	                <!-- Label -->
  20.453 -	                <value>Query 4: Discover primary roads</value> 
  20.454 -	                <!-- Statement -->
  20.455 -	                <value><![CDATA[# Get all municipalities of Pelloponnese
  20.456 -PREFIX noa: <http://teleios.di.uoa.gr/ontologies/noaOntology.owl#>
  20.457 -PREFIX clc: <http://teleios.di.uoa.gr/ontologies/clcOntology.owl#>
  20.458 -PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
  20.459 -PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
  20.460 -PREFIX strdf: <http://strdf.di.uoa.gr/ontology#>
  20.461 -PREFIX teleios: <http://teleios.di.uoa.gr/ontologies/noaOntology.owl#>
  20.462 -PREFIX gag: <http://www.semanticweb.org/ontologies/2011/gagKallikratis.rdf#>
  20.463 -PREFIX geo: <http://www.w3.org/2003/01/geo/wgs84_pos#>
  20.464 -PREFIX georss: <http://www.georss.org/georss/>
  20.465 -PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
  20.466 -PREFIX lgdo: <http://linkedgeodata.org/lontology/>
  20.467 -PREFIX gn: <http://www.geonames.org/ontology#>
  20.468 -
  20.469 -SELECT  ?d ?dGeo
  20.470 -WHERE { ?d rdf:type gag:Dhmos; 
  20.471 -           strdf:hasGeometry ?dGeo; 
  20.472 -           rdfs:label ?dLabel. 
  20.473 -           FILTER(strdf:contains("POLYGON((21.027 38.36, 23.77 38.36, 23.77 36.05, 21.027 36.05, 21.027 38.36))"^^ strdf:WKT, ?dGeo)). 
  20.474 -}]]></value>
  20.475 -<value>Find all municipalities of Pelloponnese using kallikratis ontology </value>
  20.476 -	            </list>
  20.477 -	            <list>
  20.478 -	                <!-- Bean -->
  20.479 -	                <value>Query</value> 
  20.480 -	                <!-- Format -->
  20.481 -	                <value>KMZMAP</value>
  20.482 -	                <!-- Label -->
  20.483 -	                <value>Query 5: Get all primary roads in Pelloponnese</value> 
  20.484 -	                <!-- Statement -->
  20.485 -	                <value><![CDATA[# Get all primary roads in Pelloponnese
  20.486 -PREFIX noa: <http://teleios.di.uoa.gr/ontologies/noaOntology.owl#>
  20.487 -PREFIX clc: <http://teleios.di.uoa.gr/ontologies/clcOntology.owl#>
  20.488 -PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
  20.489 -PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
  20.490 -PREFIX strdf: <http://strdf.di.uoa.gr/ontology#>
  20.491 -PREFIX teleios: <http://teleios.di.uoa.gr/ontologies/noaOntology.owl#>
  20.492 -PREFIX gag: <http://www.semanticweb.org/ontologies/2011/gagKallikratis.rdf#>
  20.493 -PREFIX geo: <http://www.w3.org/2003/01/geo/wgs84_pos#>
  20.494 -PREFIX georss: <http://www.georss.org/georss/>
  20.495 -PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
  20.496 -PREFIX lgdo: <http://linkedgeodata.org/ontology/>
  20.497 -PREFIX gn: <http://www.geonames.org/ontology#>
  20.498 -
  20.499 -SELECT  ?r ?rGeo
  20.500 -WHERE { ?r rdf:type ?rType ;
  20.501 -           noa:hasGeometry ?rGeo .
  20.502 -        FILTER(?rType = lgdo:Primary) .
  20.503 -        FILTER(strdf:contains("POLYGON((21.027 38.36, 23.77 38.36, 23.77 36.05, 21.027 36.05,21.027 38.36))"^^strdf:WKT, ?rGeo) ). 
  20.504 -}]]></value>
  20.505 -<value>Get all primary roads in Pelloponnese using the linked geodata ontology </value>
  20.506 -	            </list>
  20.507 -	            <list>
  20.508 -	                <!-- Bean -->
  20.509 -	                <value>Query</value> 
  20.510 -	                <!-- Format -->
  20.511 -	                <value>KMZMAP</value>
  20.512 -	                <!-- Label -->
  20.513 -	                <value>Query 6: Discover hotspots</value> 
  20.514 -	                <!-- Statement -->
  20.515 -	                <value><![CDATA[# Get all hotspots 
  20.516 -# - in Pelloponesus 
  20.517 -# - at 2007-08-24
  20.518 -PREFIX noa: <http://teleios.di.uoa.gr/ontologies/noaOntology.owl#>
  20.519 -PREFIX clc: <http://teleios.di.uoa.gr/ontologies/clcOntology.owl#>
  20.520 -PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
  20.521 -PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
  20.522 -PREFIX strdf: <http://strdf.di.uoa.gr/ontology#>
  20.523 -PREFIX teleios: <http://teleios.di.uoa.gr/ontologies/noaOntology.owl#>
  20.524 -PREFIX gag: <http://www.semanticweb.org/ontologies/2011/gagKallikratis.rdf#>
  20.525 -PREFIX geo: <http://www.w3.org/2003/01/geo/wgs84_pos#>
  20.526 -PREFIX georss: <http://www.georss.org/georss/>
  20.527 -PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
  20.528 -PREFIX lgdo: <http://linkedgeodata.org/ontology/>
  20.529 -PREFIX gn: <http://www.geonames.org/ontology#>
  20.530 -
  20.531 -SELECT  ?h ?hAcqTime (strdf:transform(?hGeo, <http://www.opengis.net/def/crs/EPSG/0/4326>) as ?geo) 
  20.532 -WHERE { ?h 	rdf:type noa:Hotspot;
  20.533 -            noa:hasGeometry ?hGeo;
  20.534 -            noa:hasAcquisitionTime ?hAcqTime;
  20.535 -            noa:producedFromProcessingChain ?hChain .
  20.536 -        FILTER(str(?hChain) = "StaticThresholds").
  20.537 -        FILTER(?hAcqTime = "2007-08-24T14:45:00"^^xsd:dateTime) .
  20.538 -        FILTER(strdf:contains("POLYGON((21.027 38.36, 23.77 38.36, 23.77 36.05, 21.027 36.05, 21.027 38.36))"^^ strdf:WKT, ?hGeo)) . 
  20.539 -        ?a rdf:type clc:Area;
  20.540 -           clc:hasLandUse ?aLandUse;
  20.541 -           noa:hasGeometry ?aGeo.
  20.542 -        ?aLandUse rdf:type ?aLandUseType.
  20.543 -        FILTER(?aLandUseType = clc:Forest).
  20.544 -        FILTER(strdf:contains("POLYGON((21.027 38.36, 23.77 38.36, 23.77 36.05, 21.027 36.05, 21.027 38.36))"^^strdf:WKT,?aGeo)). 
  20.545 -        FILTER(strdf:overlap(?aGeo, ?hGeo)) . 
  20.546 -}]]></value>
  20.547 -<value>Find all hotspots located in Pelloponnesian forests and acquired at 2007-08-24T14:45:00 using static thresholds processing chain </value>
  20.548 -	            </list>
  20.549 -<!-- 	            <list> -->
  20.550 -<!-- 	                Bean -->
  20.551 -<!-- 	                <value>Query</value>  -->
  20.552 -<!-- 	                Format -->
  20.553 -<!-- 	                <value>KMZMAP</value> -->
  20.554 -<!-- 	                Label -->
  20.555 -<!-- 	                <value></value>  -->
  20.556 -<!-- 	                Statement -->
  20.557 -<!-- 	                <value></value> -->
  20.558 -<!-- 	            </list> -->
  20.559 +					<!-- Link to bean: two arguemnts -->
  20.560 +					<value>Configuration</value>
  20.561 +					<value>connection.jsp</value>
  20.562 +				</list>
  20.563              </list>
  20.564           </constructor-arg>
  20.565      </bean>
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/endpoint/WebContent/WEB-INF/connection.properties	Fri May 02 17:39:27 2014 +0200
    21.3 @@ -0,0 +1,6 @@
    21.4 +hostname=localhost
    21.5 +port=5432
    21.6 +dbengine=postgis
    21.7 +password=postgres
    21.8 +dbname=endpoint
    21.9 +username=postgres
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/endpoint/WebContent/WEB-INF/credentials.properties	Fri May 02 17:39:27 2014 +0200
    22.3 @@ -0,0 +1,2 @@
    22.4 +username=endpoint
    22.5 +password=3ndpo1nt
    22.6 \ No newline at end of file
    23.1 --- a/endpoint/WebContent/WEB-INF/web.xml	Fri May 02 17:27:46 2014 +0200
    23.2 +++ b/endpoint/WebContent/WEB-INF/web.xml	Fri May 02 17:39:27 2014 +0200
    23.3 @@ -4,6 +4,22 @@
    23.4  	xmlns:base="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    23.5  	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    23.6  	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    23.7 +
    23.8 +	<!-- Uncomment the following lines to enable ip filtering--> 
    23.9 +	<!-- 
   23.10 +	<filter>
   23.11 +		<filter-name>Remote Address Filter</filter-name>
   23.12 +		<filter-class>org.apache.catalina.filters.RemoteAddrFilter</filter-class>
   23.13 +		<init-param> 
   23.14 +			<param-name>allow</param-name>
   23.15 +			<param-value>(195\.134\.(67|71)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))|(88\.197\.4[4-7]\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))|(195\.134\.105\.([01]?[0-9][0-9]?))</param-value> 
   23.16 +		</init-param>
   23.17 +	</filter>
   23.18 +	<filter-mapping>
   23.19 +		<filter-name>Remote Address Filter</filter-name>
   23.20 +		<url-pattern>/*</url-pattern>
   23.21 +	</filter-mapping>       
   23.22 +	-->
   23.23  	
   23.24  	<display-name>StrabonEndpoint</display-name>
   23.25  	<context-param>
   23.26 @@ -47,7 +63,7 @@
   23.27  		<url-pattern>/Update</url-pattern>
   23.28  	</servlet-mapping>
   23.29  
   23.30 -        <servlet>
   23.31 +    <servlet>
   23.32  		<display-name>Describe</display-name>
   23.33  		<servlet-name>Describe</servlet-name>
   23.34  		<servlet-class>eu.earthobservatory.org.StrabonEndpoint.DescribeBean</servlet-class>
   23.35 @@ -59,6 +75,50 @@
   23.36  	</servlet-mapping>
   23.37  	
   23.38  	<servlet>
   23.39 +		<display-name>DBConnect</display-name>
   23.40 +		<servlet-name>DBConnect</servlet-name>
   23.41 +		<servlet-class>eu.earthobservatory.org.StrabonEndpoint.ConnectionBean</servlet-class>
   23.42 +		<load-on-startup>1</load-on-startup>
   23.43 +	</servlet>
   23.44 +	<servlet-mapping>
   23.45 +		<servlet-name>DBConnect</servlet-name>
   23.46 +		<url-pattern>/DBConnect</url-pattern>
   23.47 +	</servlet-mapping>
   23.48 +	
   23.49 +	<servlet>
   23.50 +		<display-name>ChangeConnection</display-name>
   23.51 +		<servlet-name>ChangeConnection</servlet-name>
   23.52 +		<servlet-class>eu.earthobservatory.org.StrabonEndpoint.ChangeConnectionBean</servlet-class>
   23.53 +		<load-on-startup>1</load-on-startup>
   23.54 +	</servlet>
   23.55 +	<servlet-mapping>
   23.56 +		<servlet-name>ChangeConnection</servlet-name>
   23.57 +		<url-pattern>/ChangeConnection</url-pattern>
   23.58 +	</servlet-mapping>
   23.59 +	
   23.60 +	<servlet>
   23.61 +		<display-name>Browse</display-name>
   23.62 +		<servlet-name>Browse</servlet-name>
   23.63 +		<servlet-class>eu.earthobservatory.org.StrabonEndpoint.BrowseBean</servlet-class>
   23.64 +		<load-on-startup>1</load-on-startup>
   23.65 +	</servlet>
   23.66 +	<servlet-mapping>
   23.67 +		<servlet-name>Browse</servlet-name>
   23.68 +		<url-pattern>/Browse</url-pattern>
   23.69 +	</servlet-mapping>
   23.70 +	
   23.71 +	<servlet>
   23.72 +		<display-name>Capabilities</display-name>
   23.73 +		<servlet-name>Capabilities</servlet-name>
   23.74 +		<servlet-class>eu.earthobservatory.org.StrabonEndpoint.capabilities.CapabilitiesBean</servlet-class>
   23.75 +		<load-on-startup>1</load-on-startup>
   23.76 +	</servlet>
   23.77 +	<servlet-mapping>
   23.78 +		<servlet-name>Capabilities</servlet-name>
   23.79 +		<url-pattern>/Capabilities</url-pattern>
   23.80 +	</servlet-mapping>
   23.81 +	
   23.82 +	<servlet>
   23.83  		<servlet-name>query.jsp</servlet-name>
   23.84  		<jsp-file>/query.jsp</jsp-file>
   23.85  	</servlet>
   23.86 @@ -73,6 +133,16 @@
   23.87  		<jsp-file>/describe.jsp</jsp-file>
   23.88  	</servlet>
   23.89   
   23.90 + 	<servlet>
   23.91 +		<servlet-name>connection.jsp</servlet-name>
   23.92 +		<jsp-file>/connection.jsp</jsp-file>
   23.93 +	</servlet>
   23.94 +	
   23.95 +	<servlet>
   23.96 +		<servlet-name>browse.jsp</servlet-name>
   23.97 +		<jsp-file>/browse.jsp</jsp-file>
   23.98 +	</servlet>
   23.99 +	
  23.100     	<mime-mapping>
  23.101         	<extension>kml</extension>
  23.102         	<mime-type>application/vnd.google-earth.kml+xml</mime-type>
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/endpoint/WebContent/browse.jsp	Fri May 02 17:39:27 2014 +0200
    24.3 @@ -0,0 +1,86 @@
    24.4 +<%@page import="java.net.URLDecoder"%>
    24.5 +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
    24.6 +<%@page import="org.springframework.web.context.support.WebApplicationContextUtils"%>
    24.7 +<%@page import="org.springframework.web.context.WebApplicationContext"%>
    24.8 +<%@page import="eu.earthobservatory.org.StrabonEndpoint.StrabonBeanWrapper"%>
    24.9 +<%@page import="eu.earthobservatory.org.StrabonEndpoint.StrabonBeanWrapperConfiguration"%>
   24.10 +<%@page import="java.util.List"%>
   24.11 +<%@page import="java.util.Iterator"%>
   24.12 +<jsp:directive.page import="eu.earthobservatory.org.StrabonEndpoint.Common"/>
   24.13 +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
   24.14 +<html>
   24.15 +<head>
   24.16 +	<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
   24.17 +	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
   24.18 +	<link rel="stylesheet" href="style.css" type="text/css" />
   24.19 +	<script type="text/javascript" src="js/more_link.js"></script>	
   24.20 +	<title>TELEIOS: Strabon Endpoint</title>
   24.21 +	<script>
   24.22 +		$(document).ready(function() {
   24.23 +		var showChar = 100;
   24.24 +		var ellipsestext = "...";
   24.25 +		var moretext = "more";
   24.26 +		var lesstext = "less";
   24.27 +		$('.more').each(function() {
   24.28 +			var content = $(this).html();
   24.29 +	
   24.30 +			if(content.length > showChar) {
   24.31 +	
   24.32 +				var c = content.substr(0, showChar);
   24.33 +				var h = content.substr(showChar-1, content.length - showChar);
   24.34 +	
   24.35 +				var html = c + '<span class="moreelipses">'+ellipsestext+'</span>&nbsp;<span class="morecontent"><span>' + h + '</span>&nbsp;&nbsp;<a href="" class="morelink">'+moretext+'</a></span>';
   24.36 +	
   24.37 +				$(this).html(html);
   24.38 +			}
   24.39 +	
   24.40 +		});
   24.41 +	
   24.42 +		$(".morelink").click(function(){
   24.43 +			if($(this).hasClass("less")) {
   24.44 +				$(this).removeClass("less");
   24.45 +				$(this).html(moretext);
   24.46 +			} else {
   24.47 +				$(this).addClass("less");
   24.48 +				$(this).html(lesstext);
   24.49 +			}
   24.50 +			$(this).parent().prev().toggle();
   24.51 +			$(this).prev().toggle();
   24.52 +			return false;
   24.53 +		});
   24.54 +	});
   24.55 +</script>
   24.56 +</head>
   24.57 +<body topmargin="0" leftmargin="0" link="#FFFFFF" vlink="#FFFFFF" alink="#FFFFFF">
   24.58 +<TABLE width="80%" BORDER=0 CELLPADDING=0 CELLSPACING=0>  
   24.59 +	<TR>
   24.60 +      <TD height="1"></TD>
   24.61 +	</TR>		
   24.62 +	<TR>
   24.63 +      <TD height="60" background="images/nav2_bg.gif"> 
   24.64 +        <table width="100%" border=0>
   24.65 +         <tr>
   24.66 +            <td width="1"><img src="images/nav2_bg.gif" width="1" height="60"></td>
   24.67 +            <td valign="top" width="50px"><a href="query.jsp"><img border="0" src="images/teleios_logo.png" /></a></td>
   24.68 +            <td valign="top" align="left">
   24.69 +            <span class="logo"><a href="query.jsp">&nbsp;stSPARQL Endpoint</a></span><br><span class="style4"></span></td>
   24.70 +          </tr>
   24.71 +        </table>
   24.72 +      </TD>
   24.73 +	</TR>
   24.74 +</TABLE>
   24.75 +	<h1>About: </h1>	
   24.76 +	<a href="#"><%=URLDecoder.decode(request.getAttribute("resource").toString(), "UTF-8")%></a>
   24.77 +	<div id="response">
   24.78 +		<!-- Response -->	
   24.79 +		<% if (request.getAttribute("response") != null) {
   24.80 +			if (Common.getHTMLFormat().equals(request.getParameter("format"))) {%>
   24.81 +				<%=request.getAttribute("response")%>
   24.82 +			<%} else { %>
   24.83 +			<PRE><%=request.getAttribute("response") %></PRE>
   24.84 +			<%}%>
   24.85 +		<%}%>
   24.86 +	</div>
   24.87 +</body>
   24.88 +
   24.89 +</html>
   24.90 \ No newline at end of file
    25.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.2 +++ b/endpoint/WebContent/connection.jsp	Fri May 02 17:39:27 2014 +0200
    25.3 @@ -0,0 +1,107 @@
    25.4 +<jsp:directive.page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"/>
    25.5 +<jsp:directive.page import="eu.earthobservatory.org.StrabonEndpoint.Common"/>
    25.6 +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    25.7 +<html>
    25.8 +	<head>
    25.9 +		<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
   25.10 +		<link rel="stylesheet" href="style.css" type="text/css" />
   25.11 +		 
   25.12 +		<script type="text/javascript">
   25.13 +			function toggleMe(a) {
   25.14 +				var e = document.getElementById(a);
   25.15 +				if (!e) {
   25.16 +					return true;
   25.17 +				}
   25.18 +				if (e.style.display == "none") {
   25.19 +					e.style.display = "block";
   25.20 +				} else {
   25.21 +					e.style.display = "none";
   25.22 +				}
   25.23 +				return true;
   25.24 +			}
   25.25 +		</script>
   25.26 +		
   25.27 +		<style type="text/css">
   25.28 +		/*demo page css*/
   25.29 +		body{ font: 90% "Trebuchet MS", sans-serif; margin: 50px;}
   25.30 +		.container { height:410px; width:165px;}
   25.31 +		.demoHeaders { margin-top: 1em;}
   25.32 +		#dialog_link {padding: .4em 1em .4em 20px;text-decoration: none;position: relative;}
   25.33 +		#dialog_link span.ui-icon {margin: 0 5px 0 0;position: absolute;left: .2em;top: 50%;margin-top: -8px;}
   25.34 +		ul#icons {margin: 0; padding: 0;}
   25.35 +		ul#icons li {margin: 1px; position: relative; padding: 1px 0; cursor: pointer; float: left;  list-style: none;}
   25.36 +		ul#icons span.ui-icon {float: left; margin: 0 1px;}
   25.37 +		</style>
   25.38 +		<title>Strabon Endpoint</title>
   25.39 +	</head>
   25.40 +<body topmargin="0" leftmargin="0" link="#FFFFFF" vlink="#FFFFFF" alink="#FFFFFF">
   25.41 +
   25.42 +<!-- include TELEIOS header and description -->
   25.43 +<jsp:include page="header.html"/>
   25.44 +<!-- include TELEIOS header and description -->
   25.45 +
   25.46 +<FORM method=POST enctype="UTF-8" accept-charset="UTF-8" action="DBConnect">
   25.47 +<input type="hidden" name="query" value="<%=request.getAttribute("query")%>"/>
   25.48 +<input type="hidden" name="handle" value="<%=request.getAttribute("handle")%>"/>
   25.49 +<input type="hidden" name="format" value="<%=request.getAttribute("format")%>"/>
   25.50 +<TABLE class="style4">	
   25.51 +	<% if (request.getAttribute("error") != null) {%>
   25.52 +		<!-- Error Message -->
   25.53 +	  		<TR><TD colspan=2>
   25.54 +	  		<CENTER><P style="color: red;"><%=request.getAttribute("error") %></P></CENTER>
   25.55 +	  		</TD></TR>
   25.56 +		<!-- Error Message -->
   25.57 +	<%}%>
   25.58 +
   25.59 +	<%if (request.getAttribute("info") != null) { %>
   25.60 +		<!-- Info Message -->
   25.61 +  		<TR><TD colspan=2>
   25.62 +  		<CENTER><P><%=request.getAttribute("info") %></P></CENTER>
   25.63 +  		</TD></TR>
   25.64 +		<!-- Info Message -->
   25.65 +	<%}%>
   25.66 +	<tr>
   25.67 +		<td colspan=2 id="output">
   25.68 +			<div style="font-size:13px"> 
   25.69 +				You must be logged in to change configuration, or run in localhost.
   25.70 +			</div>
   25.71 +		</td>	
   25.72 +	</tr>
   25.73 +	<TR> 
   25.74 +		<TD valign="top" class="style4">Database Name:</TD>
   25.75 +		<TD><input type="text" name="dbname" value="<%=request.getAttribute("dbname")%>"/></TD>
   25.76 +	</TR>
   25.77 +	<TR> 
   25.78 +		<TD valign="top" class="style4">Username:</TD>
   25.79 +		<TD><input type="text" name="username" value="<%=request.getAttribute("username")%>"/></TD>
   25.80 +	</TR>
   25.81 +		<TR> 
   25.82 +		<TD valign="top" class="style4">Password:</TD>
   25.83 +		<TD><input type="password" name="password" value="<%=request.getAttribute("password")%>"/></TD>
   25.84 +	</TR>
   25.85 +	<TR> 
   25.86 +		<TD valign="top" class="style4">Port:</TD>
   25.87 +		<TD><input type="text" name="port" value="<%=request.getAttribute("port")%>"/></TD>
   25.88 +	</TR>
   25.89 +	<TR> 
   25.90 +		<TD valign="top" class="style4">Hostname:</TD>
   25.91 +		<TD><input type="text" name="hostname" value="<%=request.getAttribute("hostname")%>"/></TD>
   25.92 +	</TR>
   25.93 +	<TR> 
   25.94 +		<TD valign="top" class="style4">Database Backend:</TD>
   25.95 +		<TD>
   25.96 +			<SELECT name="dbengine">
   25.97 +				<OPTION value="<%=Common.DBBACKEND_POSTGIS%>" <%=Common.DBBACKEND_POSTGIS.equals(request.getAttribute("dbengine")) ? "selected":""%>><%=Common.DBBACKEND_POSTGIS%></OPTION>
   25.98 +				<OPTION value="<%=Common.DBBACKEND_MONETDB%>" <%=Common.DBBACKEND_MONETDB.equals(request.getAttribute("dbengine")) ? "selected":""%>><%=Common.DBBACKEND_MONETDB%></OPTION>
   25.99 +			</SELECT>
  25.100 +		</TD>
  25.101 +	</TR>
  25.102 +	<TR>
  25.103 +		<TD colspan=2><input type="submit" value="Connect"/></TD>
  25.104 +	</TR>
  25.105 +</TABLE>
  25.106 +
  25.107 +</FORM>
  25.108 +<br/><br/><br/><br/><br/>
  25.109 +</BODY>
  25.110 +</HTML>
  25.111 \ No newline at end of file
    26.1 --- a/endpoint/WebContent/describe.jsp	Fri May 02 17:27:46 2014 +0200
    26.2 +++ b/endpoint/WebContent/describe.jsp	Fri May 02 17:39:27 2014 +0200
    26.3 @@ -1,11 +1,17 @@
    26.4 +<%@page import="java.net.URLEncoder"%>
    26.5  <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
    26.6 +<%@page import="org.springframework.web.context.support.WebApplicationContextUtils"%>
    26.7 +<%@page import="org.springframework.web.context.WebApplicationContext"%>
    26.8 +<%@page import="eu.earthobservatory.org.StrabonEndpoint.StrabonBeanWrapper"%>
    26.9 +<%@page import="eu.earthobservatory.org.StrabonEndpoint.StrabonBeanWrapperConfiguration"%>
   26.10 +<%@page import="java.util.List"%>
   26.11 +<%@page import="java.util.Iterator"%>
   26.12  <jsp:directive.page import="eu.earthobservatory.org.StrabonEndpoint.Common"/>
   26.13  <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
   26.14  <html>
   26.15  	<head>
   26.16  		<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
   26.17  		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
   26.18 -		<title>TELEIOS: Strabon Endpoint</title>
   26.19  		<link rel="stylesheet" href="style.css" type="text/css"/> 
   26.20  		<script type="text/javascript">
   26.21  			function toggleMe(a) {
   26.22 @@ -21,43 +27,176 @@
   26.23  				return true;
   26.24  			}
   26.25  		</script>
   26.26 +		
   26.27 +		<%String handle = "";
   26.28 +		if (request.getParameter("handle") != null) 
   26.29 +		{
   26.30 +			handle = request.getParameter("handle");
   26.31 +			
   26.32 +		} 
   26.33 +		else if (request.getAttribute("handle") != null) 
   26.34 +		{
   26.35 +			handle = (String) request.getAttribute("handle");
   26.36 +			
   26.37 +		}
   26.38 +		
   26.39 +		String selFormat = "RDF/XML";
   26.40 +		if (request.getParameter("format") != null) {
   26.41 +			selFormat = request.getParameter("format");
   26.42 +			
   26.43 +		} else if (request.getAttribute("format") != null) {
   26.44 +			selFormat = (String) request.getAttribute("format");
   26.45 +			
   26.46 +		}%>
   26.47 +		<!-- jQuery start  -->
   26.48 +		<link type="text/css" href="style-menu.css" rel="stylesheet" />
   26.49 +		<script type="text/javascript" src="js/jquery-1.8.0.min.js"></script>
   26.50 +		<script type="text/javascript" src="js/jquery-ui-1.8.23.custom.min.js"></script>
   26.51 +		<script type="text/javascript">
   26.52 +		$(function(){
   26.53 +				// Accordion
   26.54 +				$("#accordion").accordion({ 
   26.55 +					header: "h3",
   26.56 +					fillSpace: true,
   26.57 +					navigation: true,
   26.58 +					collapsible: true
   26.59 +				});
   26.60 +				//hover states on the static widgets
   26.61 +				$('#dialog_link, ul#icons li').hover(
   26.62 +					function() { $(this).addClass('ui-state-hover'); },
   26.63 +					function() { $(this).removeClass('ui-state-hover'); }
   26.64 +				);
   26.65 +		});
   26.66 +		</script>
   26.67 +		<style type="text/css">
   26.68 +		/*demo page css*/
   26.69 +		body{ font: 90% "Trebuchet MS", sans-serif; margin: 50px;}
   26.70 +		.container { height:410px; width:165px;}
   26.71 +		.demoHeaders { margin-top: 1em;}
   26.72 +		#dialog_link {padding: .4em 1em .4em 20px;text-decoration: none;position: relative;}
   26.73 +		#dialog_link span.ui-icon {margin: 0 5px 0 0;position: absolute;left: .2em;top: 50%;margin-top: -8px;}
   26.74 +		ul#icons {margin: 0; padding: 0;}
   26.75 +		ul#icons li {margin: 1px; position: relative; padding: 1px 0; cursor: pointer; float: left;  list-style: none;}
   26.76 +		ul#icons span.ui-icon {float: left; margin: 0 1px;}
   26.77 +	</style>
   26.78 +	
   26.79 +		<title>Strabon Endpoint</title>
   26.80 +	
   26.81  	</head>
   26.82  <body topmargin="0" leftmargin="0" link="#FFFFFF" vlink="#FFFFFF" alink="#FFFFFF">
   26.83  
   26.84  <!-- include TELEIOS header and description -->
   26.85 -<jsp:include page="teleios-header.html"/>
   26.86 +<jsp:include page="header.html"/>
   26.87  <!-- include TELEIOS header and description -->
   26.88  
   26.89  <FORM enctype="UTF-8" accept-charset="UTF-8" method="post" action="Describe">
   26.90  <INPUT type=hidden name="view" value="HTML"/>
   26.91  
   26.92 -<table border="0" width="100%"><tr> 
   26.93 -<td width="90" valign="top" class="style4"> 
   26.94 -<table border="0" cellspacing="0" cellpadding="0" width="165" id="navigation"> 
   26.95 -<tr><td width="90" class="style4"><a href="query.jsp" class="navText">Query</a></td></tr> 
   26.96 -<tr><td width="90" class="style4"><a href="store.jsp" class="navText" title="Store triples">Store</a></td></tr> 
   26.97 +<table border="0" width="100%">
   26.98 +<tr> 
   26.99 +	<td width="90" valign="top"> 
  26.100 +		<table border="0" cellspacing="0" cellpadding="0" width="165">  
  26.101 +		<tr><td id="twidth">
  26.102 +		<div class="container">
  26.103 +		<div id="accordion">
  26.104 +		<%
  26.105 +							StrabonBeanWrapper strabonWrapper;
  26.106 +							ServletContext context;
  26.107 +							context = getServletContext();
  26.108 +							WebApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(context);
  26.109 +							strabonWrapper=(StrabonBeanWrapper) applicationContext.getBean("strabonBean");
  26.110 +							Iterator <StrabonBeanWrapperConfiguration> entryListIterator = strabonWrapper.getEntries().iterator();
  26.111 +							boolean first = true;
  26.112 +							String hash = "";
  26.113 +							while(entryListIterator.hasNext())
  26.114 +							{
  26.115 +								StrabonBeanWrapperConfiguration entry = entryListIterator.next();
  26.116 +								
  26.117 +								if (entry.isHeader()) {
  26.118 +									if (!first) {
  26.119 +										%>
  26.120 +										</div></div>
  26.121 +										<%
  26.122 +									} else {
  26.123 +										first = false;
  26.124 +									}
  26.125 +									
  26.126 +									String label=entry.getLabel();
  26.127 +									String style = "", href = "";
  26.128 +									hash = new Integer(Math.abs(label.hashCode())).toString();
  26.129 +									href="href=\"#"+hash+"\"";									
  26.130 +									%>
  26.131 +									<div><h3><a <%=style%> <%=href%>><%=label%></a></h3><div>
  26.132 +									<%									
  26.133 +								} else if (entry.isBean()) {
  26.134 +									String label=entry.getLabel();
  26.135 +									String bean=entry.getBean();
  26.136 +									if(bean.equals("browse.jsp") || bean.equals("ChangeConnection"))
  26.137 +										continue;
  26.138 +									String style = "", href = "";
  26.139 +									hash = new Integer(Math.abs(label.hashCode()*bean.hashCode())).toString();
  26.140 +									href = "\"" +bean + "#"+ hash+"\"";
  26.141 +									style = "class=\"navText\"";
  26.142 +									%>
  26.143 +									<b>&middot;</b>&nbsp;<a class="linkText" href=<%=href%>><%=label%></a><br/>
  26.144 +									<%
  26.145 +								} else {
  26.146 +									String href="\""+URLEncoder.encode(entry.getBean(),"utf-8")+"?view=HTML&handle="+entry.getHandle()+"&query="+URLEncoder.encode(entry.getStatement(),"utf-8")+"&format="+URLEncoder.encode(entry.getFormat(),"utf-8")+(hash == "" ? "" : "#" + hash)+"\"";
  26.147 +									String title="\""+entry.getTitle()+"\"";
  26.148 +									String label=entry.getLabel();
  26.149 +									%>
  26.150 +									<b>&middot;</b>&nbsp;<a class="linkText" href=<%=href%> title=<%=title%>><%=label%></a><br/>
  26.151 +									<%
  26.152 +			
  26.153 +								}
  26.154 +							}
  26.155 +		%>
  26.156 +		</div>
  26.157 +		</div>
  26.158 +	</td>
  26.159 +</tr>
  26.160 +<!-- 
  26.161 +<tr><td width="90" class="style4"><a href="describe.jsp" class="navText">Describe</a></td></tr>
  26.162 +<tr><td width="90" class="style4"><a href="store.jsp" class="navText" title="Store triples">Store</a></td></tr>
  26.163 + --> 
  26.164  </table>
  26.165 -</td>
  26.166 +	</td>
  26.167  <td width="*" valign="top">
  26.168  <table cellspacing="5">
  26.169  <tr>
  26.170 -<td id="output">stSPARQL Query:</td>
  26.171 +<td id="output" style="width: 150px">stSPARQL Query:</td>
  26.172  <td id="output"><textarea name="query" title="pose your DESCRIBE query here" rows="15" cols="100">
  26.173  <%=request.getParameter("query") != null ? request.getParameter("query"):""%></textarea></td>
  26.174  </tr>
  26.175  <tr>
  26.176 -<td id="output"><center>Output Format:<br/>
  26.177 +<td id="output">Output Format:</td>
  26.178 +<td id="output">
  26.179  <SELECT name="format" title="select one of the following RDF graph format types">
  26.180  	<% for (String format : Common.registeredFormats) {%>
  26.181 -		<OPTION value="<%=format%>"><%=format%></OPTION>
  26.182 +		<OPTION value="<%=format%>"<%=format.equals(selFormat) ? "selected":""%>><%=format%></OPTION>
  26.183  	<%}%>
  26.184 -</SELECT></center></td>
  26.185 -<td colspan=2><br/>
  26.186 +</SELECT>
  26.187 +</td>
  26.188 +</tr>
  26.189 +<tr>
  26.190 +<td id="output">View Result:</td>
  26.191 +<td id="output">
  26.192 +	<SELECT name="handle" title="select how you would like to view the result">
  26.193 +		<OPTION value="plain"<%= ("plain".equals(handle)) ? "selected":""%>>Plain</OPTION>
  26.194 +		<OPTION value="download"<%= ("download".equals(handle)) ? "selected":""%>>Download</OPTION>		
  26.195 +	</SELECT>
  26.196 +</td>
  26.197 +</tr>
  26.198 +<tr>
  26.199 +<td colspan=2 id="output"><br/>
  26.200  <center>
  26.201 -	<input type="submit" title="execute DESCRIBE query" value="Describe" name="submit" style="width: 400px"/><br/>
  26.202 -</center><br/></td>
  26.203 +	<input type="submit" title="execute DESCRIBE query" value="Describe" name="submit" style="width: 350px"/>
  26.204 +</center><br/>
  26.205 +</td>
  26.206  </tr>
  26.207  
  26.208 +
  26.209 +
  26.210  <% if (request.getAttribute("error") != null) {%>
  26.211  	<!-- Error Message -->
  26.212  	<TR>
  26.213 @@ -67,13 +206,15 @@
  26.214  <%}%>
  26.215  
  26.216  
  26.217 -</table></td></tr></table><br/><br/>
  26.218 +</table></td></tr>
  26.219  
  26.220 +
  26.221 +</table>
  26.222 +</form>
  26.223  <% if (request.getAttribute("response") != null) {%>
  26.224  	<!-- Response -->
  26.225 -	<PRE><%=request.getAttribute("response") %></PRE>
  26.226 +	<div><%=request.getAttribute("response") %></div>
  26.227  	<!-- Response -->
  26.228  <%}%>
  26.229 -</form>
  26.230  </body>
  26.231  </html>
  26.232 \ No newline at end of file
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/endpoint/WebContent/header.html	Fri May 02 17:39:27 2014 +0200
    27.3 @@ -0,0 +1,37 @@
    27.4 +<TABLE width="100%" BORDER=0 CELLPADDING=0 CELLSPACING=0>
    27.5 +  
    27.6 +	<TR>
    27.7 +      <TD height="1"></TD>
    27.8 +	</TR>		
    27.9 +	<TR>
   27.10 +      <TD height="60"> 
   27.11 +        <table width="100%" border=0>
   27.12 +         <tr>
   27.13 +            <td width="1">&nbsp;</td>
   27.14 +            <td valign="top" width="50px"><a href="http://en.uoa.gr"><img border="0" src="images/uoa_logo.png" /></a></td>
   27.15 +            <td valign="middle" align="left">
   27.16 +            <span class="logo"><a href="query.jsp">&nbsp;stSPARQL Endpoint</a></span><br><span class="style4"></span></td>
   27.17 +          </tr>
   27.18 +        </table>
   27.19 +      </TD>
   27.20 +	</TR>
   27.21 +	<TR>
   27.22 +      <TD height="50" id="intro">
   27.23 +<p> On this page you can execute stSPARQL queries against the Strabon backend.
   27.24 +<!--  <a onclick="return toggleMe('par')">(More)</a>  -->
   27.25 +<!--
   27.26 +In this context NOA has been developing a real-time fire hotspot detection service for effectively monitoring 
   27.27 +a fire-front. The technique is based on the use of acquisitions originating from the SEVIRI  sensor, on top of MSG-1 and MSG-2 satellite platforms.
   27.28 +-->
   27.29 +<!-- Since 2007, NOA operates an MSG/SEVIRI acquisition station, and has been systematically
   27.30 +archiving raw satellite images on a 5 and 15 minutes basis, the respective temporal resolutions of MSG-1 and MSG-2.  -->
   27.31 +The acquired data are then annotated using the stRDF model and can be queried using the stSPARQL query language.
   27.32 + 
   27.33 +On the left sidebar, some example stSPARQL queries to aquire information on the dataset, are provided. 
   27.34 +<!--The NOA use case is described in more detail in the VLDB
   27.35 +demo paper <a href="http://www.earthobservatory.eu/publications/p2010_manoliskoubarakis_vldb2012-2.pdf">here</a>. 
   27.36 +-->
   27.37 +</p> 
   27.38 +      </TD>
   27.39 +	</TR>
   27.40 +</TABLE>
    28.1 Binary file endpoint/WebContent/images/red-circle.png has changed
    29.1 Binary file endpoint/WebContent/images/ui-bg_flat_75_aaaaaa_40x100.png has changed
    30.1 Binary file endpoint/WebContent/images/ui-bg_glass_100_f5f0e5_1x400.png has changed
    31.1 Binary file endpoint/WebContent/images/ui-bg_glass_25_cb842e_1x400.png has changed
    32.1 Binary file endpoint/WebContent/images/ui-bg_glass_70_ede4d4_1x400.png has changed
    33.1 Binary file endpoint/WebContent/images/ui-bg_highlight-hard_100_f4f0ec_1x100.png has changed
    34.1 Binary file endpoint/WebContent/images/ui-bg_highlight-hard_65_fee4bd_1x100.png has changed
    35.1 Binary file endpoint/WebContent/images/ui-bg_highlight-hard_75_f5f5b5_1x100.png has changed
    36.1 Binary file endpoint/WebContent/images/ui-bg_inset-soft_100_f4f0ec_1x100.png has changed
    37.1 Binary file endpoint/WebContent/images/ui-icons_c47a23_256x240.png has changed
    38.1 Binary file endpoint/WebContent/images/ui-icons_cb672b_256x240.png has changed
    39.1 Binary file endpoint/WebContent/images/ui-icons_f08000_256x240.png has changed
    40.1 Binary file endpoint/WebContent/images/ui-icons_f35f07_256x240.png has changed
    41.1 Binary file endpoint/WebContent/images/ui-icons_ff7519_256x240.png has changed
    42.1 Binary file endpoint/WebContent/images/ui-icons_ffffff_256x240.png has changed
    43.1 Binary file endpoint/WebContent/images/uoa_logo.png has changed
    44.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    44.2 +++ b/endpoint/WebContent/js/ProjectedOverlay.js	Fri May 02 17:39:27 2014 +0200
    44.3 @@ -0,0 +1,138 @@
    44.4 +// Create an overlay on the map from a projected image - Maps v3...
    44.5 +// Author. John D. Coryat 05/2009
    44.6 +// USNaviguide LLC - http://www.usnaviguide.com
    44.7 +// Thanks go to Mile Williams EInsert: http://econym.googlepages.com/einsert.js, Google's GOverlay Example and Bratliff's suggestion...
    44.8 +// Opacity code from TPhoto: http://gmaps.tommangan.us/addtphoto.html
    44.9 +// This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
   44.10 +//
   44.11 +// Parameters:
   44.12 +//    map: This Map
   44.13 +//    imageUrl: URL of the image (Mandatory)
   44.14 +//    bounds: Bounds object of image destination (Mandatory)
   44.15 +//    Options:
   44.16 +//    addZoom: Added Zoom factor as a parameter to the imageUrl (include complete parameter, including separater like '?zoom='
   44.17 +//    percentOpacity: Default 50, percent opacity to use when the image is loaded 0-100.
   44.18 +//    id: Default imageUrl, ID of the div
   44.19 +//
   44.20 +	
   44.21 +function ProjectedOverlay(map, imageUrl, bounds, opts)
   44.22 +{
   44.23 + google.maps.OverlayView.call(this);
   44.24 +
   44.25 + this.map_ = map;
   44.26 + this.url_ = imageUrl ;
   44.27 + this.bounds_ = bounds ;
   44.28 + this.addZ_ = opts.addZoom || '' ;				// Add the zoom to the image as a parameter
   44.29 + this.id_ = opts.id || this.url_ ;				// Added to allow for multiple images
   44.30 + this.percentOpacity_ = opts.percentOpacity || 50 ;
   44.31 +
   44.32 + this.setMap(map);
   44.33 +}
   44.34 +
   44.35 +ProjectedOverlay.prototype = new google.maps.OverlayView();
   44.36 +
   44.37 +ProjectedOverlay.prototype.createElement = function()
   44.38 +{
   44.39 + var panes = this.getPanes() ;
   44.40 + var div = this.div_ ;
   44.41 +
   44.42 + if (!div)
   44.43 + {
   44.44 +  div = this.div_ = document.createElement("div");
   44.45 +  div.style.position = "absolute" ;
   44.46 +  div.setAttribute('id',this.id_) ;
   44.47 +  this.div_ = div ;
   44.48 +  this.lastZoom_ = -1 ;
   44.49 +  if( this.percentOpacity_ )
   44.50 +  {
   44.51 +   this.setOpacity(this.percentOpacity_) ;
   44.52 +  }
   44.53 +  panes.overlayLayer.appendChild(div);
   44.54 + }
   44.55 +}
   44.56 +
   44.57 +// Remove the main DIV from the map pane
   44.58 +
   44.59 +ProjectedOverlay.prototype.remove = function()
   44.60 +{
   44.61 + if (this.div_) 
   44.62 + {
   44.63 +  this.div_.parentNode.removeChild(this.div_);
   44.64 +  this.div_ = null;
   44.65 + }
   44.66 +}
   44.67 +
   44.68 +// Redraw based on the current projection and zoom level...
   44.69 +
   44.70 +ProjectedOverlay.prototype.draw = function(firstTime)
   44.71 +{
   44.72 + // Creates the element if it doesn't exist already.
   44.73 +
   44.74 + this.createElement();
   44.75 +
   44.76 + if (!this.div_)
   44.77 + {
   44.78 +  return ;
   44.79 + }
   44.80 +
   44.81 + var c1 = this.get('projection').fromLatLngToDivPixel(this.bounds_.getSouthWest());
   44.82 + var c2 = this.get('projection').fromLatLngToDivPixel(this.bounds_.getNorthEast());
   44.83 +
   44.84 + if (!c1 || !c2) return;
   44.85 +
   44.86 + // Now position our DIV based on the DIV coordinates of our bounds
   44.87 +
   44.88 + this.div_.style.width = Math.abs(c2.x - c1.x) + "px";
   44.89 + this.div_.style.height = Math.abs(c2.y - c1.y) + "px";
   44.90 + this.div_.style.left = Math.min(c2.x, c1.x) + "px";
   44.91 + this.div_.style.top = Math.min(c2.y, c1.y) + "px";
   44.92 +
   44.93 + // Do the rest only if the zoom has changed...
   44.94 + 
   44.95 + if ( this.lastZoom_ == this.map_.getZoom() )
   44.96 + {
   44.97 +  return ;
   44.98 + }
   44.99 +
  44.100 + this.lastZoom_ = this.map_.getZoom() ;
  44.101 +
  44.102 + var url = this.url_ ;
  44.103 +
  44.104 + if ( this.addZ_ )
  44.105 + {
  44.106 +  url += this.addZ_ + this.map_.getZoom() ;
  44.107 + }
  44.108 +
  44.109 + this.div_.innerHTML = '<img src="' + url + '"  width=' + this.div_.style.width + ' height=' + this.div_.style.height + ' >' ;
  44.110 +}
  44.111 +
  44.112 +ProjectedOverlay.prototype.setOpacity=function(opacity)
  44.113 +{
  44.114 + if (opacity < 0)
  44.115 + {
  44.116 +  opacity = 0 ;
  44.117 + }
  44.118 + if(opacity > 100)
  44.119 + {
  44.120 +  opacity = 100 ;
  44.121 + }
  44.122 + var c = opacity/100 ;
  44.123 +
  44.124 + if (typeof(this.div_.style.filter) =='string')
  44.125 + {
  44.126 +  this.div_.style.filter = 'alpha(opacity:' + opacity + ')' ;
  44.127 + }
  44.128 + if (typeof(this.div_.style.KHTMLOpacity) == 'string' )
  44.129 + {
  44.130 +  this.div_.style.KHTMLOpacity = c ;
  44.131 + }
  44.132 + if (typeof(this.div_.style.MozOpacity) == 'string')
  44.133 + {
  44.134 +  this.div_.style.MozOpacity = c ;
  44.135 + }
  44.136 + if (typeof(this.div_.style.opacity) == 'string')
  44.137 + {
  44.138 +  this.div_.style.opacity = c ;
  44.139 + }
  44.140 +}
  44.141 +
    45.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    45.2 +++ b/endpoint/WebContent/js/ZipFile.complete.js	Fri May 02 17:39:27 2014 +0200
    45.3 @@ -0,0 +1,2172 @@
    45.4 +// ZipFile.complete.js
    45.5 +//
    45.6 +// 2/17/2012
    45.7 +//
    45.8 +// =======================================================
    45.9 +//
   45.10 +
   45.11 +// JSIO.core.js
   45.12 +// ------------------------------------------------------------------
   45.13 +//
   45.14 +// core methods for Javascript IO.
   45.15 +//
   45.16 +// =======================================================
   45.17 +//
   45.18 +// Copyleft (c) 2010, Dino Chiesa via MS-PL
   45.19 +// Copyleft (c) 2012, Brendan Byrd via GPL
   45.20 +//
   45.21 +// This work is licensed under the GPLv3.
   45.22 +
   45.23 +
   45.24 +(function(){
   45.25 +    if (typeof JSIO == "object"){
   45.26 +        var e1 = new Error("JSIO is already defined");
   45.27 +        e1.source = "JSIO.core.js";
   45.28 +        throw e1;
   45.29 +    }
   45.30 +
   45.31 +    JSIO = {};
   45.32 +
   45.33 +    JSIO.version = "2.0 2012Feb";
   45.34 +
   45.35 +    JSIO.throwError = function(msg, source, sub) {
   45.36 +        var error = new Error("Error: " + msg);
   45.37 +        error.source = (source || this._typename || 'JSIO') + (sub ? '.'+sub : '');
   45.38 +        throw error;
   45.39 +    }
   45.40 +
   45.41 +    // Format a number as hex.  Quantities over 7ffffff will be displayed properly.
   45.42 +    JSIO.decimalToHexString = function(number, digits) {
   45.43 +        if (number < 0) {
   45.44 +            number = 0xFFFFFFFF + number + 1;
   45.45 +        }
   45.46 +        var r1 = number.toString(16).toUpperCase();
   45.47 +        if (digits) {
   45.48 +            r1 = "00000000" + r1;
   45.49 +            r1 = r1.substring(r1.length - digits);
   45.50 +        }
   45.51 +        return r1;
   45.52 +    };
   45.53 +
   45.54 +    JSIO.FileType = {
   45.55 +        Text    : 0,
   45.56 +        Binary  : 1,
   45.57 +        XML     : 2,
   45.58 +        Unknown : 3
   45.59 +    };
   45.60 +
   45.61 +
   45.62 +    JSIO.guessFileType = function(name) {
   45.63 +       if (name == "makefile")  { return JSIO.FileType.Text; }
   45.64 +
   45.65 +        var lastDot = name.lastIndexOf(".");
   45.66 +        if (lastDot <= 0) { return JSIO.FileType.Unknown; }
   45.67 +
   45.68 +        var ext= name.substring(lastDot);
   45.69 +        if (ext == ".zip")   { return JSIO.FileType.Binary; }
   45.70 +        if (ext == ".xlsx")  { return JSIO.FileType.Binary; }
   45.71 +        if (ext == ".docx")  { return JSIO.FileType.Binary; }
   45.72 +        if (ext == ".dll")   { return JSIO.FileType.Binary; }
   45.73 +        if (ext == ".obj")   { return JSIO.FileType.Binary; }
   45.74 +        if (ext == ".pdb")   { return JSIO.FileType.Binary; }
   45.75 +        if (ext == ".exe")   { return JSIO.FileType.Binary; }
   45.76 +        if (ext == ".kmz")   { return JSIO.FileType.Binary; }
   45.77 +
   45.78 +        if (ext == ".xml")      { return JSIO.FileType.XML; }
   45.79 +        if (ext == ".xsl")      { return JSIO.FileType.XML; }
   45.80 +        if (ext == ".kml")      { return JSIO.FileType.XML; }
   45.81 +        if (ext == ".csproj")   { return JSIO.FileType.XML; }
   45.82 +        if (ext == ".vbproj")   { return JSIO.FileType.XML; }
   45.83 +        if (ext == ".shfbproj") { return JSIO.FileType.XML; }
   45.84 +        if (ext == ".resx")     { return JSIO.FileType.XML; }
   45.85 +        if (ext == ".xslt")     { return JSIO.FileType.XML; }
   45.86 +
   45.87 +        if (ext == ".sln")  { return JSIO.FileType.Text; }
   45.88 +        if (ext == ".htm")  { return JSIO.FileType.Text; }
   45.89 +        if (ext == ".html") { return JSIO.FileType.Text; }
   45.90 +        if (ext == ".js")   { return JSIO.FileType.Text; }
   45.91 +        if (ext == ".vb")   { return JSIO.FileType.Text; }
   45.92 +        if (ext == ".txt")  { return JSIO.FileType.Text; }
   45.93 +        if (ext == ".rels") { return JSIO.FileType.Text; }
   45.94 +        if (ext == ".css")  { return JSIO.FileType.Text; }
   45.95 +        if (ext == ".cs")   { return JSIO.FileType.Text; }
   45.96 +        if (ext == ".asp")  { return JSIO.FileType.Text; }
   45.97 +
   45.98 +        return JSIO.FileType.Unknown;
   45.99 +    };
  45.100 +
  45.101 +    JSIO.stringOfLength = function (charCode, length) {
  45.102 +        var s3 = "";
  45.103 +        for (var i = 0; i < length; i++) {
  45.104 +            s3 += String.fromCharCode(charCode);
  45.105 +        }
  45.106 +        return s3;
  45.107 +    };
  45.108 +
  45.109 +    JSIO.formatByteArray = function(b) {
  45.110 +        var s1 = "0000  ";
  45.111 +        var s2 = "";
  45.112 +        for (var i = 0; i < b.length; i++) {
  45.113 +            if (i !== 0 && i % 16 === 0) {
  45.114 +                s1 += "    " + s2 +"\n" + JSIO.decimalToHexString(i, 4) + "  ";
  45.115 +                s2 = "";
  45.116 +            }
  45.117 +            s1 += JSIO.decimalToHexString(b[i], 2) + " ";
  45.118 +            if (b[i] >=32 && b[i] <= 126) {
  45.119 +                s2 += String.fromCharCode(b[i]);
  45.120 +            } else {
  45.121 +                s2 += ".";
  45.122 +            }
  45.123 +        }
  45.124 +        if (s2.length > 0) {
  45.125 +            s1 += JSIO.stringOfLength(32, ((i%16>0)? ((16 - i%16) * 3) : 0) + 4) + s2;
  45.126 +        }
  45.127 +        return s1;
  45.128 +    };
  45.129 +
  45.130 +    JSIO.htmlEscape = function(str) {
  45.131 +        return str
  45.132 +            .replace(new RegExp( "&", "g" ), "&amp;")
  45.133 +            .replace(new RegExp( "<", "g" ), "&lt;")
  45.134 +            .replace(new RegExp( ">", "g" ), "&gt;")
  45.135 +            .replace(new RegExp( "\x13", "g" ), "<br/>")
  45.136 +            .replace(new RegExp( "\x10", "g" ), "<br/>");
  45.137 +    };
  45.138 +
  45.139 +    JSIO.massApply = function(func, funcThis, arr, needReturn) {
  45.140 +        var arrayLimit = 99999;  // Chrome has an apply/array limit of 99999; Firefox = 491519
  45.141 +        if (arr.length < arrayLimit) return func.apply(funcThis, arr);
  45.142 +        else {
  45.143 +            var newThis = funcThis;
  45.144 +            var offset = 0;
  45.145 +            var end    = 99999;
  45.146 +
  45.147 +            while (offset < arr.length) {
  45.148 +                var arrSlice;
  45.149 +                if      (arr.subarray) arrSlice = arr.subarray(offset, end);
  45.150 +                else if (arr.slice)    arrSlice = arr.slice(offset, end);
  45.151 +
  45.152 +                if (needReturn) newThis += func.apply(newThis,  arrSlice);
  45.153 +                else                       func.apply(funcThis, arrSlice);
  45.154 +
  45.155 +                offset += arrayLimit;
  45.156 +                end    += arrayLimit;
  45.157 +                end     = Math.min(arr.length, end);
  45.158 +            }
  45.159 +            return newThis;
  45.160 +        }
  45.161 +    }
  45.162 +
  45.163 +})();
  45.164 +
  45.165 +/// JSIO.core.js ends
  45.166 +
  45.167 +
  45.168 +// JSIO.BasicByteReaders.js
  45.169 +// ------------------------------------------------------------------
  45.170 +//
  45.171 +// Part of the JSIO library.  Adds a couple basic ByteReaders to JSIO.
  45.172 +// ByteReaders are forward-only byte-wise readers. They read one byte at
  45.173 +// a time from a source.
  45.174 +//
  45.175 +// =======================================================
  45.176 +//
  45.177 +// A ByteReader exposes an interface with these functions:
  45.178 +//
  45.179 +//    readByte()
  45.180 +//       must return null when EOF is reached.
  45.181 +//
  45.182 +//    readToEnd()
  45.183 +//       returns an array of all bytes read, to EOF
  45.184 +//
  45.185 +//    beginReadToEnd(callback)
  45.186 +//       async version of the above
  45.187 +//
  45.188 +//    readBytes(n)
  45.189 +//       returns an array of the next n bytes from the source
  45.190 +//
  45.191 +//    beginReadBytes(n, callback)
  45.192 +//       async version of the above
  45.193 +//
  45.194 +// =======================================================
  45.195 +//
  45.196 +// Copyleft (c) 2010, Dino Chiesa via MS-PL
  45.197 +// Copyleft (c) 2012, Brendan Byrd via GPL
  45.198 +//
  45.199 +// This work is licensed under the GPLv3.
  45.200 +
  45.201 +
  45.202 +(function(){
  45.203 +    var version = "2.0 2012Feb";
  45.204 +
  45.205 +    if (typeof JSIO !== "object") { JSIO = {}; }
  45.206 +    if ((typeof JSIO.version !== "string")) {
  45.207 +        JSIO.version = version;
  45.208 +    }
  45.209 +    else if ((JSIO.version.length < 3) ||
  45.210 +            (JSIO.version.substring(0,3) !== "2.0")) {
  45.211 +        JSIO.version += " " + version;
  45.212 +    }
  45.213 +
  45.214 +    // =======================================================
  45.215 +    // the base object, used as the prototype of all ByteReader objects.
  45.216 +    var _byteReaderBase = function () {
  45.217 +        this.position = 0;
  45.218 +        // position must be incremented in .readByte() for all derived classes
  45.219 +    };
  45.220 +
  45.221 +    _byteReaderBase.prototype._throwError = JSIO.throwError;
  45.222 +
  45.223 +    _byteReaderBase.prototype._limitCheck = function(len, startPos) {
  45.224 +        var LOE = {
  45.225 +            len: len,
  45.226 +            pos: startPos,
  45.227 +            end: startPos+len
  45.228 +        };
  45.229 +
  45.230 +        if (len === 0)              return {len:0, pos:0, end:0};
  45.231 +        if (len < 0)                this._throwError("Invalid read length");
  45.232 +        if (!this.length)           return {len:len, pos:this.position, end:len+this.position};
  45.233 +        if (!startPos >= 0)         LOE.pos = this.position;
  45.234 +        if (this.length <= LOE.pos) this._throwError("EOF reached");
  45.235 +
  45.236 +        LOE.end = LOE.pos+len;
  45.237 +        if (this.length < LOE.end)  LOE.end = LOE.pos+(LOE.len = this.length-this.position);
  45.238 +        return LOE;
  45.239 +    }
  45.240 +
  45.241 +    JSIO.SeekOrigin = {
  45.242 +        Begin     : 0,
  45.243 +        Current   : 1,
  45.244 +        End       : 2,
  45.245 +        SEEK_SET  : 0,
  45.246 +        SEEK_CUR  : 1,
  45.247 +        SEEK_END  : 2
  45.248 +    };
  45.249 +
  45.250 +    _byteReaderBase.prototype.seek = function(offset, origin) {
  45.251 +        switch (origin) {
  45.252 +            case JSIO.SeekOrigin.Begin:
  45.253 +                if (offset == this.position) return this.position;
  45.254 +                if (!this.length) {
  45.255 +                    if      (offset <  this.position) this._throwError('Uni-directional stream cannot seek backwards', null, 'seek');
  45.256 +                    else if (offset >  this.position) return this.read(offset - this.position);  // read will limit check
  45.257 +                }
  45.258 +                else {
  45.259 +                    if (this.length < offset) this._throwError('Cannot seek past reader length', null, 'seek');
  45.260 +                    this.position = offset;
  45.261 +                }
  45.262 +                break;
  45.263 +            case JSIO.SeekOrigin.Current:
  45.264 +                return this.seek(this.position + offset, JSIO.SeekOrigin.Begin);
  45.265 +                break;
  45.266 +            case JSIO.SeekOrigin.End:
  45.267 +                if (!this.length) this._throwError('Uni-directional stream has no known end length for seek', null, 'seek');
  45.268 +                return this.seek(this.length - 1 + offset, JSIO.SeekOrigin.Begin);
  45.269 +                break;
  45.270 +            default:
  45.271 +                this._throwError('Invalid seek method', null, 'seek');
  45.272 +                break;
  45.273 +        }
  45.274 +
  45.275 +        return this.position;
  45.276 +    };
  45.277 +
  45.278 +    _byteReaderBase.prototype.read = function(len, startPos) {
  45.279 +        var LOE = this._limitCheck(len, startPos);
  45.280 +        if (LOE.len === 0) return [];
  45.281 +        if (LOE.pos != this.position) this.seek(LOE.pos, JSIO.SeekOrigin.Begin);
  45.282 +
  45.283 +        var bytesRead = [];
  45.284 +
  45.285 +        // Faster methods with an array or stream
  45.286 +        if      (this.array && this.array.subarray) bytesRead = this.array.subarray(LOE.pos, LOE.end);
  45.287 +        else if (this.array && this.array.slice)    bytesRead = this.array.slice(LOE.pos, LOE.end);
  45.288 +        else if (this.stream)                       bytesRead = this.stream.read(LOE.len, LOE.pos);
  45.289 +        else if (this.length) {  // Random-access stream
  45.290 +            for(var i=LOE.pos; i<LOE.end; i++) { bytesRead.push(this.readByteAt(i)); }
  45.291 +        }
  45.292 +        else {                   // Uni-directional stream
  45.293 +            for(var i=LOE.pos; i<LOE.end; i++) {
  45.294 +                var b = this.readByte();
  45.295 +                if (b === null || b === undefined) break;
  45.296 +                bytesRead.push(b);
  45.297 +            }
  45.298 +        }
  45.299 +        this.position = LOE.end;
  45.300 +        return bytesRead;
  45.301 +    };
  45.302 +
  45.303 +    _byteReaderBase.prototype.beginRead = function(len, startPos, callback) {
  45.304 +        var LOE = this._limitCheck(len, startPos);
  45.305 +        if (LOE.len === 0) return setTimeout(function() { callback([]); }, 1);
  45.306 +        if (LOE.pos != this.position) this.seek(LOE.pos, JSIO.SeekOrigin.Begin);
  45.307 +
  45.308 +        var bytesRead = [];
  45.309 +        var thisReader = this;
  45.310 +        var leftToRead = LOE.len;
  45.311 +
  45.312 +        var readBatchAsync = function() {
  45.313 +            var c = 0;
  45.314 +            var pos = thisReader.position;
  45.315 +
  45.316 +            // read a 32k batch
  45.317 +            var l = (leftToRead >= 32768) ? 32768 : leftToRead;
  45.318 +            var newBytes = thisReader.read(l);
  45.319 +            JSIO.massApply(bytesRead.push, bytesRead, newBytes);
  45.320 +            c += l;
  45.321 +            leftToRead -= l;
  45.322 +            if (newBytes.length < l) leftToRead = 0;
  45.323 +
  45.324 +            if (leftToRead>0) setTimeout(readBatchAsync, 1);
  45.325 +            else              callback(bytesRead);
  45.326 +        };
  45.327 +
  45.328 +        // kickoff
  45.329 +        setTimeout(readBatchAsync, 1);  // always async, in ALL situations
  45.330 +        return null;
  45.331 +    };
  45.332 +
  45.333 +    _byteReaderBase.prototype.readToEnd = function() {
  45.334 +        if      (this.array && this.array.subarray) return this.array.subarray(this.position);
  45.335 +        else if (this.array && this.array.slice)    return this.array.slice(this.position);
  45.336 +        else if (this.length)                       return this.read(this.length - this.position);
  45.337 +        else                                        return this.read(9000 * 9000);  // over 9000
  45.338 +    };
  45.339 +
  45.340 +    _byteReaderBase.prototype.beginReadToEnd = function(callback) {
  45.341 +        if      (this.array && this.array.subarray) setTimeout(function() { callback( this.array.subarray(this.position) ); }, 1);
  45.342 +        else if (this.array && this.array.slice)    setTimeout(function() { callback(    this.array.slice(this.position) ); }, 1);
  45.343 +        else if (this.length)                       return this.beginRead(this.length - this.position, this.position, callback);
  45.344 +        else                                        return this.beginRead(9000 * 9000, this.position, callback);
  45.345 +    };
  45.346 +
  45.347 +    // Generic routines; one of these two MUST be overloaded (preferrably both)
  45.348 +    _byteReaderBase.prototype.readByte = function(){
  45.349 +        if (this.length && this.position >= this.length) return null;  // EOF
  45.350 +
  45.351 +        var byte;
  45.352 +        if      (this.array)  byte = this.array[this.position++];
  45.353 +        else if (this.length) byte = this.readByteAt(this.position++);
  45.354 +        else if (this.stream) byte = this.stream.read(1)[0];
  45.355 +        else                  byte = this.read(1)[0];
  45.356 +        return (byte === null || byte === undefined) ? null : byte;
  45.357 +    };
  45.358 +    _byteReaderBase.prototype.readByteAt = function(i) {
  45.359 +        var pos  = this.position;  // no position changes on this one
  45.360 +        if (i === null || i === undefined) i = this.position;
  45.361 +
  45.362 +        var byte;
  45.363 +        if      (this.array)  byte = this.array[i];
  45.364 +        else if (i === pos)   byte = this.readByte();
  45.365 +        else if (this.stream) byte = this.stream.read(1, i)[0];
  45.366 +        else                  byte = this.read(1, i)[0];
  45.367 +
  45.368 +        this.position = pos;
  45.369 +        return (byte === null || byte === undefined) ? null : byte;
  45.370 +    }
  45.371 +
  45.372 +    _byteReaderBase.prototype.readBytes = _byteReaderBase.prototype.read;
  45.373 +    _byteReaderBase.prototype.beginReadBytes = function(len, callback) { return this.beginRead(len, this.position, callback); };
  45.374 +
  45.375 +    _byteReaderBase.prototype.readNumber = function(len, startPos){
  45.376 +        var LOE = this._limitCheck(len, startPos);
  45.377 +        if (LOE.len === 0) LOE.len = 1;
  45.378 +        if (LOE.pos != this.position) this.seek(LOE.pos, JSIO.SeekOrigin.Begin);
  45.379 +
  45.380 +        var result = 0;
  45.381 +        var bytes  = this.read(LOE.len, LOE.pos);
  45.382 +        for (var i=bytes.length-1; i>=0; i--) {
  45.383 +            // IE only supports 32-bit integer shifting
  45.384 +            //result = result << 8 | bytes[i];
  45.385 +            result = result*256 + bytes[i];
  45.386 +        }
  45.387 +        return result;
  45.388 +    };
  45.389 +
  45.390 +    _byteReaderBase.prototype.readString = function(len, startPos){
  45.391 +        var LOE = this._limitCheck(len, startPos);
  45.392 +        if (LOE.len === 0) return '';
  45.393 +        if (LOE.pos != this.position) this.seek(LOE.pos, JSIO.SeekOrigin.Begin);
  45.394 +
  45.395 +        var result = '';
  45.396 +        var bytes  = this.read(LOE.len, LOE.pos);
  45.397 +        for(var i=0; i<bytes.length; i++){
  45.398 +            result += String.fromCharCode(bytes[i]);
  45.399 +        }
  45.400 +        return result;
  45.401 +    };
  45.402 +
  45.403 +    _byteReaderBase.prototype.readNullTerminatedString = function(startPos){
  45.404 +        var pos = startPos || this.position;
  45.405 +        if (this.length && this.length < pos) this._throwError('EOF reached', null, 'readNullTerminatedString');
  45.406 +        if (pos != this.position) this.seek(pos, JSIO.SeekOrigin.Begin);
  45.407 +
  45.408 +        var slarge = "";
  45.409 +        var s = "";
  45.410 +        var c = 0;
  45.411 +
  45.412 +        // Faster method with an array
  45.413 +        if (this.array && this.array.indexOf) {
  45.414 +            var len = pos - this.array.indexOf(0, pos);
  45.415 +            if (len > 0) return this.readString(len, pos);
  45.416 +        }
  45.417 +
  45.418 +        var ch;
  45.419 +        while(1) {
  45.420 +            ch = String.fromCharCode(this.readByteAt(pos+c));
  45.421 +            if (ch === null) break;
  45.422 +
  45.423 +            s += ch;
  45.424 +            c++;
  45.425 +            if(c >= 32768) {
  45.426 +                slarge += s;
  45.427 +                s = "";
  45.428 +                pos += c;
  45.429 +                this.position += c;
  45.430 +                c = 0;
  45.431 +            }
  45.432 +        };
  45.433 +        this.position = pos + c;
  45.434 +        return slarge + s;
  45.435 +    };
  45.436 +
  45.437 +    _byteReaderBase.prototype.beginReadNullTerminatedString = function(callback, startPos){
  45.438 +        var pos = startPos || this.position;
  45.439 +        if (this.length && this.length < pos) this._throwError('EOF reached', null, 'beginReadNullTerminatedString');
  45.440 +
  45.441 +        var slarge = "";
  45.442 +        var s = "";
  45.443 +        var thisBinStream = this;
  45.444 +
  45.445 +        var readBatchAsync = function() {
  45.446 +            var c = 0;
  45.447 +
  45.448 +            var ch;
  45.449 +            while(1) {
  45.450 +                ch = String.fromCharCode(this.readByteAt(pos+c));
  45.451 +                if (ch === null) break;
  45.452 +
  45.453 +                s += ch;
  45.454 +                c++;
  45.455 +                if(c >= 32768) {
  45.456 +                    slarge += s;
  45.457 +                    s = "";
  45.458 +                    pos += c;
  45.459 +                    this.position += c;
  45.460 +                    c = 0;
  45.461 +                }
  45.462 +            };
  45.463 +
  45.464 +            thisBinStream.position = pos + c;
  45.465 +            if (ch!==null) setTimeout(readBatchAsync, 1);
  45.466 +            else           callback(slarge+s);
  45.467 +        };
  45.468 +
  45.469 +        // Faster method with an array
  45.470 +        if (this.array && this.array.indexOf) {
  45.471 +            var len = pos - this.array.indexOf(0, pos);
  45.472 +            if (len > 0) readBatchASync = function() { callback(thisBinStream.readString(len, pos)); };
  45.473 +        }
  45.474 +
  45.475 +        // kickoff
  45.476 +        setTimeout(readBatchAsync, 1);  // always async, in ALL situations
  45.477 +        return null;
  45.478 +    };
  45.479 +
  45.480 +
  45.481 +
  45.482 +    JSIO._ByteReaderBase = _byteReaderBase;
  45.483 +    // =======================================================
  45.484 +
  45.485 +
  45.486 +
  45.487 +
  45.488 +    // =======================================================
  45.489 +    // reads from an array of bytes.
  45.490 +    // This basically wraps a readByte() fn onto array access.
  45.491 +    var _arrayReader = function(array) {
  45.492 +        if (! (this instanceof arguments.callee) ) this._throwError('You must use new to instantiate this class', 'JSIO.ArrayReader', 'ctor');
  45.493 +        this.position = 0;
  45.494 +        this.array = array;
  45.495 +        this.length = array.length;
  45.496 +        this._typename = "JSIO.ArrayReader";
  45.497 +        this._version = version;
  45.498 +        return this;
  45.499 +    };
  45.500 +
  45.501 +    _arrayReader.prototype = new JSIO._ByteReaderBase();
  45.502 +
  45.503 +    _arrayReader.prototype.readByte = function() {
  45.504 +        if (this.position >= this.array.length) return null;  // EOF
  45.505 +        return this.array[this.position++];
  45.506 +    };
  45.507 +    _arrayReader.prototype.readByteAt = function(i) {
  45.508 +        return this.array[i];
  45.509 +    };
  45.510 +
  45.511 +    // =======================================================
  45.512 +
  45.513 +
  45.514 +    // =======================================================
  45.515 +    // reads bytes at a time from a defined segment of a stream.
  45.516 +    var _streamSegmentReader = function(stream, offset, len) {
  45.517 +        if (! (this instanceof arguments.callee) ) this._throwError('You must use new to instantiate this class', 'JSIO.StreamSegmentReader', 'ctor');
  45.518 +        if (!stream)                               this._throwError('You must pass a non-null stream',            'JSIO.StreamSegmentReader', 'ctor');
  45.519 +
  45.520 +        if (!(offset >= 1)) offset = 0;
  45.521 +        if (!(len    >= 1)) len    = 0;
  45.522 +
  45.523 +        this.stream    = stream;
  45.524 +        this.array     = null;
  45.525 +        if (stream.array) {
  45.526 +            var end = len ? offset + len : null;
  45.527 +            if      (stream.array.subarray) this.array = stream.array.subarray(offset, end);
  45.528 +            else if (stream.array.slice)    this.array = stream.array.slice(offset, end);
  45.529 +        }
  45.530 +        this.length    = this.array ? this.array.length : (stream.length ? stream.length - offset : null);
  45.531 +        this.offset    = offset;
  45.532 +        this.limit     = len;
  45.533 +        this.position  = 0;
  45.534 +        this._typeName = 'JSIO.StreamSegmentReader';
  45.535 +        this._version  = version;
  45.536 +
  45.537 +        if (this.array) {
  45.538 +            this.readByte   = _arrayReader.prototype.readByte;
  45.539 +            this.readByteAt = _arrayReader.prototype.readByteAt;
  45.540 +        }
  45.541 +        return this;
  45.542 +    };
  45.543 +
  45.544 +    _streamSegmentReader.prototype = new JSIO._ByteReaderBase();
  45.545 +
  45.546 +    _streamSegmentReader.prototype.readByte = function() {
  45.547 +        if (this.limit && this.position >= this.limit) return null;  // EOF
  45.548 +        this.position++;
  45.549 +        return this.stream.readByteAt(this.offset + this.position - 1);
  45.550 +    };
  45.551 +    _streamSegmentReader.prototype.readByteAt = function(i) {
  45.552 +        if (this.limit && i >= this.limit) return null;  // EOF
  45.553 +        return this.stream.readByteAt(this.offset + i);
  45.554 +    };
  45.555 +
  45.556 +    // =======================================================
  45.557 +
  45.558 +    JSIO.ArrayReader         = _arrayReader;
  45.559 +    JSIO.StreamReader        = _streamSegmentReader;
  45.560 +    JSIO.StreamSegmentReader = _streamSegmentReader;
  45.561 +
  45.562 +})();
  45.563 +
  45.564 +
  45.565 +/// JSIO.BasicByteReaders.js ends
  45.566 +
  45.567 +// JSIO.BinaryUrlStream.js
  45.568 +// ------------------------------------------------------------------
  45.569 +//
  45.570 +// a class that acts as a stream wrapper around binary files obtained from URLs.
  45.571 +//
  45.572 +// =======================================================
  45.573 +//
  45.574 +// Copyleft (c) 2008, Andy G.P. Na <nagoon97@naver.com> via an MIT-style license
  45.575 +// Copyleft (c) 2012, Brendan Byrd via GPL
  45.576 +//
  45.577 +// This work is licensed under the GPLv3.
  45.578 +
  45.579 +(function(){
  45.580 +    var version  = "2.0 2012Feb";
  45.581 +    var typename = "JSIO.BinaryUrlStream";
  45.582 +
  45.583 +    if ((typeof JSIO !== "object") ||
  45.584 +        (typeof JSIO.version !== "string") ||
  45.585 +        (JSIO.version.length < 3) ||
  45.586 +        (JSIO.version.substring(0,3) !== "2.0"))
  45.587 +            JSIO.throwError('This extension requires JSIO.core.js v2.0', typename);
  45.588 +
  45.589 +    if (typeof JSIO._ByteReaderBase !== "function")
  45.590 +        JSIO.throwError('This extension requires JSIO.BasicByteReaders.js', typename);
  45.591 +
  45.592 +    if (/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent)) {
  45.593 +        var IEBinaryToArray_ByteStr_Script =
  45.594 +            "<!-- IEBinaryToArray_ByteStr -->\r\n"+
  45.595 +            "<script type='text/vbscript'>\r\n"+
  45.596 +            "Function IEBinaryToArray_ByteStr(Binary)\r\n"+
  45.597 +            "   IEBinaryToArray_ByteStr = CStr(Binary)\r\n"+
  45.598 +            "End Function\r\n"+
  45.599 +            "Function IEBinaryToArray_ByteAsc_Last(Binary)\r\n"+
  45.600 +            "   Dim lastIndex\r\n"+
  45.601 +            "   lastIndex = LenB(Binary)\r\n"+
  45.602 +            "   if lastIndex mod 2 Then\r\n"+
  45.603 +            "      IEBinaryToArray_ByteAsc_Last = AscB( MidB( Binary, lastIndex, 1 ) )\r\n"+
  45.604 +            "   Else\r\n"+
  45.605 +            "      IEBinaryToArray_ByteAsc_Last = -1\r\n"+
  45.606 +            "   End If\r\n"+
  45.607 +            "End Function\r\n"+
  45.608 +            "</script>\r\n";
  45.609 +
  45.610 +        // inject VBScript
  45.611 +        document.write(IEBinaryToArray_ByteStr_Script);
  45.612 +    }
  45.613 +
  45.614 +    JSIO.IEByteMapping = null;
  45.615 +
  45.616 +    var bus = function(url, callback) {
  45.617 +        if (! (this instanceof arguments.callee) ) this._throwError('You must use new to instantiate this class', 'JSIO.BinaryUrlStream', 'ctor');
  45.618 +
  45.619 +        this.callback   = callback;
  45.620 +        this.position   = 0;
  45.621 +        this.length     = null;
  45.622 +        this.readByte   = JSIO.ArrayReader.prototype.readByte;
  45.623 +        this.readByteAt = JSIO.ArrayReader.prototype.readByteAt;
  45.624 +        this.req        = null;
  45.625 +        this._typename  = typename;
  45.626 +        this._version   = version;
  45.627 +        this.status     = "-none-";
  45.628 +
  45.629 +        var _IeGetBinResource = function(fileURL){
  45.630 +            var binStream = this;
  45.631 +            // http://stackoverflow.com/questions/1919972/how-do-i-access-xhr-responsebody-for-binary-data-from-javascript-in-ie
  45.632 +
  45.633 +            // my helper to convert from responseBody to a byte array
  45.634 +            var convertResponseBodyToArray = function (binary) {
  45.635 +                var byteArray = new Array;
  45.636 +
  45.637 +                try {
  45.638 +                    // very fast; very little work involved
  45.639 +                    byteArray = new VBArray(binary).toArray();
  45.640 +                }
  45.641 +                catch(err) {
  45.642 +                    // use the BinaryToArray VBScript
  45.643 +                    if (!JSIO.IEByteMapping) {
  45.644 +                        JSIO.IEByteMapping = {};
  45.645 +                        for ( var i = 0; i < 256; i++ ) {
  45.646 +                            for ( var j = 0; j < 256; j++ ) {
  45.647 +                                JSIO.IEByteMapping[ String.fromCharCode( i + j * 256 ) ] = [ i, j ];
  45.648 +                            }
  45.649 +                        }
  45.650 +                    }
  45.651 +                    var rawBytes = IEBinaryToArray_ByteStr(binary);
  45.652 +                    var lastAsc  = IEBinaryToArray_ByteAsc_Last(binary);
  45.653 +
  45.654 +                    for ( var i = 0; i < rawBytes.length; i++ ) {
  45.655 +                        byteArray.push.apply(byteArray, JSIO.IEByteMapping[ rawBytes.substr(i,1) ]);
  45.656 +                    }
  45.657 +                    if (lastAsc >= 0) byteArray.push(lastAsc);
  45.658 +                }
  45.659 +
  45.660 +                return byteArray;
  45.661 +            };
  45.662 +
  45.663 +            this.req = (function() {
  45.664 +                if      (window.XMLHttpRequest) return new window.XMLHttpRequest();
  45.665 +                else if (window.ActiveXObject) {
  45.666 +                    // the many versions of IE's XML fetchers
  45.667 +                    var AXOs = [
  45.668 +                        'MSXML2.XMLHTTP.6.0',
  45.669 +                        'MSXML2.XMLHTTP.5.0',
  45.670 +                        'MSXML2.XMLHTTP.4.0',
  45.671 +                        'MSXML2.XMLHTTP.3.0',
  45.672 +                        'MSXML2.XMLHTTP',
  45.673 +                        'Microsoft.XMLHTTP',
  45.674 +                        'MSXML.XMLHTTP'
  45.675 +                    ];
  45.676 +                    for (var i = 0; i < AXOs.length; i++) {
  45.677 +                        try      { return new ActiveXObject(AXOs[i]); }
  45.678 +                        catch(e) { continue; }
  45.679 +                    }
  45.680 +                }
  45.681 +                return null;
  45.682 +            })();
  45.683 +            this.req.open("GET", fileURL, true);
  45.684 +            this.req.setRequestHeader("Accept-Charset", "x-user-defined");
  45.685 +            this.req.onreadystatechange = function(event){
  45.686 +                if (binStream.req.readyState == 4) {
  45.687 +                    binStream.status = "Status: " + binStream.req.status + ' ' + binStream.req.statusText;
  45.688 +                    if (binStream.req.status == 200) {
  45.689 +                        binStream.array  = convertResponseBodyToArray(binStream.req.responseBody);
  45.690 +                        binStream.length = binStream.array.length;
  45.691 +                        if (binStream.length < 0) this._throwError('Failed to load "'+ fileURL + '" after converting');
  45.692 +
  45.693 +                        if (typeof binStream.callback == "function") binStream.callback(binStream);
  45.694 +                    }
  45.695 +                    else {
  45.696 +                        binStream._throwError('Failed to load "'+ fileURL + '": HTTP ' + binStream.status);
  45.697 +                    }
  45.698 +                }
  45.699 +            };
  45.700 +            this.req.send();
  45.701 +        };
  45.702 +
  45.703 +        var _NormalGetBinResource = function(fileURL){
  45.704 +            var binStream= this;
  45.705 +            this.req = new XMLHttpRequest();
  45.706 +            this.req.open('GET', fileURL, true);
  45.707 +            this.req.onreadystatechange = function(aEvt) {
  45.708 +                if (binStream.req.readyState == 4) {
  45.709 +                    binStream.status = "Status: " + binStream.req.status + ' ' + binStream.req.statusText;
  45.710 +                    if(binStream.req.status == 200){
  45.711 +                        var fileContents = binStream.req.responseText;
  45.712 +                        binStream.length = fileContents.byteLength;
  45.713 +                        binStream.array  = fileContents.split('');
  45.714 +                        for ( var i = 0; i < binStream.array.length; i++ ) {
  45.715 +                            binStream.array[i] = binStream.array[i].charCodeAt(0) & 0xff;
  45.716 +                        }
  45.717 +
  45.718 +                        if (typeof binStream.callback == "function") binStream.callback(binStream);
  45.719 +                    }
  45.720 +                    else {
  45.721 +                        binStream._throwError('Failed to load "'+ fileURL + '": HTTP ' + binStream.status);
  45.722 +                    }
  45.723 +                }
  45.724 +            };
  45.725 +            //XHR binary charset opt by Marcus Granado 2006 [http://mgran.blogspot.com]
  45.726 +            this.req.overrideMimeType('text/plain; charset=x-user-defined');
  45.727 +            this.req.send(null);
  45.728 +        };
  45.729 +
  45.730 +        // http://stackoverflow.com/questions/327685/is-there-a-way-to-read-binary-data-into-javascript
  45.731 +        var _ArrayBufferGetBinResource = function(fileURL){
  45.732 +            var binStream= this;
  45.733 +            this.req = new XMLHttpRequest();
  45.734 +            this.req.open('GET', fileURL, true);
  45.735 +            this.req.onreadystatechange = function(aEvt) {
  45.736 +                if (binStream.req.readyState == 4) {
  45.737 +                    binStream.status = "Status: " + binStream.req.status + ' ' + binStream.req.statusText;
  45.738 +                    if(binStream.req.status == 200){
  45.739 +                        var fileContents = binStream.req.response;
  45.740 +                        binStream.length = fileContents.byteLength;
  45.741 +                        binStream.array = new Uint8Array(fileContents);
  45.742 +                        if (typeof binStream.callback == "function") binStream.callback(binStream);
  45.743 +                    }
  45.744 +                    else {
  45.745 +                        binStream._throwError('Failed to load "'+ fileURL + '": HTTP ' + binStream.status);
  45.746 +                    }
  45.747 +                }
  45.748 +            };
  45.749 +            this.req.responseType = 'arraybuffer';
  45.750 +            // http://stackoverflow.com/questions/11284728/how-do-i-access-8-bit-binary-data-from-javascript-in-opera
  45.751 +            this.req.overrideMimeType('application/octet-stream; charset=x-user-defined');
  45.752 +            this.req.send(null);
  45.753 +        };
  45.754 +
  45.755 +
  45.756 +        if      (typeof ArrayBuffer !== 'undefined')                                       _ArrayBufferGetBinResource.apply(this, [url]);
  45.757 +        else if (/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent)) _IeGetBinResource.apply(this, [url]);
  45.758 +        else                                                                               _NormalGetBinResource.apply(this, [url]);
  45.759 +    };
  45.760 +
  45.761 +    bus.prototype = new JSIO._ByteReaderBase();
  45.762 +
  45.763 +    bus.prototype.readByte = function(){
  45.764 +        var byte = this.readByteAt(this.position++);
  45.765 +        return (byte === null || byte === undefined) ? null : byte;
  45.766 +    };
  45.767 +
  45.768 +    JSIO.BinaryUrlStream = bus;
  45.769 +
  45.770 +})();
  45.771 +
  45.772 +/// JSIO.BinaryUrlStream.js ends
  45.773 +
  45.774 +// JSIO.TextDecoder.js
  45.775 +// ------------------------------------------------------------------
  45.776 +//
  45.777 +// Part of the JSIO library.  Adds text decoders, for UTF-8 and UTF-16,
  45.778 +// and plain text.
  45.779 +//
  45.780 +// =======================================================
  45.781 +//
  45.782 +// Derived in part from work by notmasteryet.
  45.783 +//   http://www.codeproject.com/KB/scripting/Javascript_binaryenc.aspx
  45.784 +
  45.785 +// Copyleft (c) 2008, notmasteryet via an MIT-style license
  45.786 +// Copyleft (c) 2010, Dino Chiesa via MS-PL
  45.787 +// Copyleft (c) 2012, Brendan Byrd via GPL
  45.788 +//
  45.789 +// This work is licensed under the GPLv3.
  45.790 +
  45.791 +(function(){
  45.792 +    var version = "2.0 2012Feb";
  45.793 +    var typename = "JSIO.TextDecoder";
  45.794 +
  45.795 +    if ((typeof JSIO !== "object") ||
  45.796 +        (typeof JSIO.version !== "string") ||
  45.797 +        (JSIO.version.length < 3) ||
  45.798 +        (JSIO.version.substring(0,3) !== "2.0"))
  45.799 +            JSIO.throwError('This extension requires JSIO.core.js v2.0', typename);
  45.800 +
  45.801 +    if (typeof JSIO._ByteReaderBase !== "function")
  45.802 +        JSIO.throwError('This extension requires JSIO.BasicByteReaders.js', typename);
  45.803 +
  45.804 +    var _ansi = function(reader) {
  45.805 +        if (! (this instanceof arguments.callee) ) this._throwError('You must use new to instantiate this class', 'JSIO.TextDecoder.ANSI', 'ctor');
  45.806 +        this.byteReader = reader;
  45.807 +        this.charWidth = 1;
  45.808 +        this._version = version;
  45.809 +        this._typename = typename + ".ANSI";
  45.810 +        return this;
  45.811 +    };
  45.812 +
  45.813 +    _ansi.prototype.readChar = function() {
  45.814 +        var code = this.byteReader.readByte();
  45.815 +        return (code < 0) ? null : String.fromCharCode(code);
  45.816 +    };
  45.817 +
  45.818 +    _ansi.prototype.parseChar = function(code) {
  45.819 +        return (code < 0) ? null : String.fromCharCode(code);
  45.820 +    };
  45.821 +
  45.822 +    var _utf16 = function(reader) {
  45.823 +        if (! (this instanceof arguments.callee) ) this._throwError('You must use new to instantiate this class', 'JSIO.TextDecoder.UTF16', 'ctor');
  45.824 +        this.byteReader = reader;
  45.825 +        this.charWidth = 2;
  45.826 +        this.bomState = 0;
  45.827 +        this._version = version;
  45.828 +        this._typename = typename + ".UTF16";
  45.829 +        return this;
  45.830 +    };
  45.831 +
  45.832 +    _utf16.prototype.readChar = function() {
  45.833 +        var b1 = this.byteReader.readByte();
  45.834 +        if (b1 < 0) return null;
  45.835 +        var b2 = this.byteReader.readByte();
  45.836 +        if (b2 < 0) this._throwError('Incomplete UTF16 character', null, 'readChar');
  45.837 +
  45.838 +        if ((this.bomState === 0) && ((b1 + b2) == 509)) {
  45.839 +            this.bomState = (b2 == 254) ? 1 : 2;
  45.840 +
  45.841 +            b1 = this.byteReader.readByte();
  45.842 +            if (b1 < 0) return null;
  45.843 +            b2 = this.byteReader.readByte();
  45.844 +            if (b2 < 0) this._throwError('Incomplete UTF16 character', null, 'readChar');
  45.845 +        }
  45.846 +        else {
  45.847 +            this.bomState = 1;
  45.848 +        }
  45.849 +        return this.parseChar(b1, b2);
  45.850 +    };
  45.851 +
  45.852 +    _utf16.prototype.parseChar = function(b1, b2) {
  45.853 +        return String.fromCharCode( this.bomState == 1 ? (b2 << 8 | b1) : (b1 << 8 | b2) );
  45.854 +    }
  45.855 +
  45.856 +    /* RFC 3629 */
  45.857 +    var _utf8 = function(reader) {
  45.858 +        if (! (this instanceof arguments.callee) ) this._throwError('You must use new to instantiate this class', 'JSIO.TextDecoder.UTF8', 'ctor');
  45.859 +        this.byteReader = reader;
  45.860 +        this.charWidth = null;
  45.861 +        this.waitBom = true;
  45.862 +        this.strict = false;
  45.863 +        this.pendingChar = null;
  45.864 +        this._version = version;
  45.865 +        this._typename = typename + ".UTF8";
  45.866 +        return this;
  45.867 +    };
  45.868 +
  45.869 +    _utf8.prototype.readChar = function() {
  45.870 +        var ch = null;
  45.871 +        do {
  45.872 +            if (this.pendingChar !== null) {
  45.873 +                ch = this.pendingChar;
  45.874 +                this.pendingChar = null;
  45.875 +            }
  45.876 +            else {
  45.877 +                var b1 = this.byteReader.readByte();
  45.878 +                if (b1 === null) return null;
  45.879 +
  45.880 +                if ((b1 & 0x80) === 0) ch = String.fromCharCode(b1);
  45.881 +                else {
  45.882 +                    var currentPrefix = 0xC0;
  45.883 +                    var ttlBytes = 0;
  45.884 +                    do {
  45.885 +                        var mask = currentPrefix >> 1 | 0x80;
  45.886 +                        if((b1 & mask) == currentPrefix) break;
  45.887 +                        currentPrefix = currentPrefix >> 1 | 0x80;
  45.888 +                    } while(++ttlBytes < 5);
  45.889 +
  45.890 +                    if (ttlBytes > 0) {
  45.891 +                        var code;
  45.892 +                        if (ttlBytes === 1) code = (b1 & 0x1F) << 6 | (this.byteReader.readByte() & 0x3F);
  45.893 +                        else {
  45.894 +                            code = code << 6*ttlBytes
  45.895 +                            var bytes = this.byteReader.read(ttlBytes);
  45.896 +                            for (var i = 0; i > ttlBytes; i++) {
  45.897 +                                var bi = bytes[i];
  45.898 +                                if ((bi & 0xC0) != 0x80) this._throwError('Invalid sequence character', null, 'readChar');
  45.899 +                                code = (code << 6) | (bi & 0x3F);
  45.900 +                            }
  45.901 +                        }
  45.902 +
  45.903 +                        if (code <= 0xFFFF) {
  45.904 +                            ch = (code == 0xFEFF && this.waitBom) ? null : String.fromCharCode(code);
  45.905 +                        }
  45.906 +                        else {
  45.907 +                            var v = code - 0x10000;
  45.908 +                            var w1 = 0xD800 | ((v >> 10) & 0x3FF);
  45.909 +                            var w2 = 0xDC00 | (v & 0x3FF);
  45.910 +                            this.pendingChar = String.fromCharCode(w2);
  45.911 +                            ch = String.fromCharCode(w1);
  45.912 +                        }
  45.913 +                    }
  45.914 +                    else {
  45.915 +                        // a byte higher than 0x80.
  45.916 +                        if (this.strict) this._throwError('Invalid character', null, 'readChar');
  45.917 +                        // fall back to "super ascii" (eg IBM-437)
  45.918 +                        else ch = String.fromCharCode(b1);
  45.919 +                    }
  45.920 +                }
  45.921 +            }
  45.922 +            this.waitBom = false;
  45.923 +        } while(ch === null);
  45.924 +        return ch;
  45.925 +    };
  45.926 +
  45.927 +    JSIO.TextDecoder = {
  45.928 +        Default : _ansi,
  45.929 +        ANSI    : _ansi,
  45.930 +        UTF16   : _utf16,
  45.931 +        UTF8    : _utf8
  45.932 +    };
  45.933 +
  45.934 +})();
  45.935 +
  45.936 +
  45.937 +/// JSIO.TextDecoder.js ends
  45.938 +
  45.939 +// JSIO.TextReader.js
  45.940 +// ------------------------------------------------------------------
  45.941 +//
  45.942 +// A reader class that decodes text as it reads.
  45.943 +//
  45.944 +// =======================================================
  45.945 +//
  45.946 +// Methods:
  45.947 +//    readChar()         = read 1 char
  45.948 +//    read(n)            = read n chars
  45.949 +//    readLine()         = read one line of data (to \n)
  45.950 +//    unreadChar(ch)     = unread one char
  45.951 +//    readToEnd()        = read all data in the reader;
  45.952 +//                         return a string.
  45.953 +//    beginReadToEnd(cb) = asynchronously read all data.
  45.954 +//
  45.955 +// =======================================================
  45.956 +//
  45.957 +// Derived in part from work by notmasteryet.
  45.958 +//   http://www.codeproject.com/KB/scripting/Javascript_binaryenc.aspx
  45.959 +//
  45.960 +// Copyleft (c) 2008, notmasteryet via an MIT-style license
  45.961 +// Copyleft (c) 2010, Dino Chiesa via MS-PL
  45.962 +// Copyleft (c) 2012, Brendan Byrd via GPL
  45.963 +//
  45.964 +// This work is licensed under the GPLv3.
  45.965 +
  45.966 +
  45.967 +(function(){
  45.968 +    var version = "2.0 2012Feb";
  45.969 +    var typename = "JSIO.TextReader";
  45.970 +
  45.971 +    if (typeof JSIO._ByteReaderBase !== "function")
  45.972 +        JSIO.throwError('This extension requires JSIO.BasicByteReaders.js', typename);
  45.973 +
  45.974 +    var tr =  function(textDecoder) {
  45.975 +        if (! (this instanceof arguments.callee) ) this._throwError('You must use new to instantiate this class', typename, 'ctor');
  45.976 +        this.decoder   = textDecoder;
  45.977 +        this._version  = version;
  45.978 +        this._typename = typename;
  45.979 +        this.unreads   = [];
  45.980 +    };
  45.981 +
  45.982 +    // read one char
  45.983 +    tr.prototype.readChar = function() {
  45.984 +        return (this.unreads.length > 0) ? this.unreads.pop() : this.decoder.readChar();
  45.985 +    };
  45.986 +
  45.987 +    // read a length of data
  45.988 +    tr.prototype.read = function(n) {
  45.989 +        // ANSI makes this easy
  45.990 +        if (this.decoder.charWidth === 1) return JSIO.massApply(String.fromCharCode, new String, this.decoder.byteReader.read(n), true);
  45.991 +
  45.992 +        var s = "";
  45.993 +        for (vari=0; i<n; i++) {
  45.994 +            var ch = this.readChar();
  45.995 +            if (ch !== null) s+= ch;
  45.996 +            else             break;
  45.997 +        }
  45.998 +        return s;
  45.999 +    };
 45.1000 +
 45.1001 +    tr.prototype.unreadChar = function(ch) {
 45.1002 +        this.unreads.push(ch);
 45.1003 +    };
 45.1004 +
 45.1005 +    tr.prototype.readToEnd = function() {
 45.1006 +        // ANSI makes this easy
 45.1007 +        if (this.decoder.charWidth === 1) return JSIO.massApply(String.fromCharCode, new String, this.decoder.byteReader.readToEnd(n), true);
 45.1008 +
 45.1009 +        var slarge = "";
 45.1010 +        var s = "";
 45.1011 +        var c = 0;
 45.1012 +        var ch = this.readChar();
 45.1013 +        while(ch !== null) {
 45.1014 +            s += ch;
 45.1015 +            c++;
 45.1016 +            if(c >= 32768) {
 45.1017 +                slarge += s;
 45.1018 +                s = "";
 45.1019 +                c = 0;
 45.1020 +            }
 45.1021 +            ch = this.readChar();
 45.1022 +        }
 45.1023 +        return slarge + s;
 45.1024 +    };
 45.1025 +
 45.1026 +    tr.prototype.beginReadToEnd = function(callback) {
 45.1027 +        // ANSI makes this easy
 45.1028 +        if (this.decoder.charWidth === 1) {
 45.1029 +            this.decoder.byteReader.beginReadToEnd(function (bytes) {
 45.1030 +                callback( JSIO.massApply(String.fromCharCode, new String, bytes, true) );
 45.1031 +            });
 45.1032 +            return null;
 45.1033 +        }
 45.1034 +
 45.1035 +        var slarge = "";
 45.1036 +        var s = "";
 45.1037 +        var txtrdr = this;
 45.1038 +
 45.1039 +        var readBatchAsync = function() {
 45.1040 +            var c = 0;
 45.1041 +            var ch = txtrdr.readChar();
 45.1042 +            while(ch !== null) {
 45.1043 +                s += ch;c++;
 45.1044 +                if(c >= 32768) {
 45.1045 +                    slarge += s;
 45.1046 +                    s = "";
 45.1047 +                    break;
 45.1048 +                }
 45.1049 +                ch = txtrdr.readChar();
 45.1050 +            }
 45.1051 +            if (ch!==null){
 45.1052 +                setTimeout(readBatchAsync, 1);
 45.1053 +            }
 45.1054 +            else {
 45.1055 +                callback(slarge+s);
 45.1056 +            }
 45.1057 +        };
 45.1058 +
 45.1059 +        // kickoff
 45.1060 +        setTimeout(readBatchAsync, 1);  // always async, in ALL situations
 45.1061 +        return null;
 45.1062 +    };
 45.1063 +
 45.1064 +    tr.prototype.readLine = function() {
 45.1065 +        var s = "";
 45.1066 +        var ch = this.readChar();
 45.1067 +        if (ch === null) return null;
 45.1068 +
 45.1069 +        while(ch != "\r" && ch != "\n") {
 45.1070 +            s += ch;
 45.1071 +            ch = this.readChar();
 45.1072 +            if (ch === null) return s;
 45.1073 +        }
 45.1074 +        if(ch == "\r") {
 45.1075 +            ch = this.readChar();
 45.1076 +            if(ch !== null && ch != "\n"){
 45.1077 +                this.unreadChar(ch);
 45.1078 +            }
 45.1079 +        }
 45.1080 +        return s;
 45.1081 +    };
 45.1082 +
 45.1083 +    JSIO.TextReader = tr;
 45.1084 +
 45.1085 +})();
 45.1086 +
 45.1087 +
 45.1088 +/// JSIO.TextReader.js ends
 45.1089 +
 45.1090 +// JSIO.Crc32.js
 45.1091 +//
 45.1092 +// Part of the JSIO library.  This adds an CRC32-calculating
 45.1093 +// ByteReader to JSIO.
 45.1094 +//
 45.1095 +// =======================================================
 45.1096 +//
 45.1097 +// A ByteReader exposes an interface with these functions:
 45.1098 +//
 45.1099 +//    readByte()
 45.1100 +//       must return null when EOF is reached.
 45.1101 +//
 45.1102 +//    readToEnd()
 45.1103 +//       returns an array of all bytes read, to EOF
 45.1104 +//
 45.1105 +//    beginReadToEnd(callback)
 45.1106 +//       async version of the above
 45.1107 +//
 45.1108 +//    readBytes(n)
 45.1109 +//       returns an array of all n bytes read from the source
 45.1110 +//
 45.1111 +//    beginReadBytes(n, callback)
 45.1112 +//       async version of the above
 45.1113 +//
 45.1114 +// =======================================================
 45.1115 +//
 45.1116 +// Copyleft (c) 2010, Dino Chiesa via MS-PL
 45.1117 +// Copyleft (c) 2012, Brendan Byrd via GPL
 45.1118 +//
 45.1119 +// This work is licensed under the GPLv3.
 45.1120 +
 45.1121 +(function(){
 45.1122 +    var version = "2.0 2012Feb";
 45.1123 +    var typename = "JSIO.Crc32";
 45.1124 +
 45.1125 +    if (typeof JSIO._ByteReaderBase !== "function")
 45.1126 +        JSIO.throwError('This extension requires JSIO.BasicByteReaders.js', typename);
 45.1127 +
 45.1128 +    JSIO.crc32Table = null;
 45.1129 +    JSIO.crc32Polynomial = 0xEDB88320;
 45.1130 +
 45.1131 +    var crc32TableCalc = function () {
 45.1132 +        // do this once only, for all instances
 45.1133 +        if (JSIO.crc32Table) return;
 45.1134 +        JSIO.crc32Table = new Array(256);
 45.1135 +        for (var i = 0; i < 256; i++) {
 45.1136 +            var c=i;
 45.1137 +            for (var k = 0; k < 8; k++) {
 45.1138 +                if ((c & 1) == 1) c = JSIO.crc32Polynomial ^ (c>>>1);
 45.1139 +                else              c >>>= 1;
 45.1140 +            }
 45.1141 +            JSIO.crc32Table[i] = c;
 45.1142 +        }
 45.1143 +    };
 45.1144 +
 45.1145 +    JSIO.computeCrc32 = function(str) {
 45.1146 +        crc32TableCalc(); // once
 45.1147 +        var c = 0xFFFFFFFF;
 45.1148 +        var sL = str.length;
 45.1149 +        if (typeof str == "object") {
 45.1150 +            for (var n1=0; n1<sL; n1++) {
 45.1151 +                c = JSIO.crc32Table[(c&0xff) ^ str[n1]] ^ (c>>>8);
 45.1152 +            }
 45.1153 +        } else {
 45.1154 +            for (var n2=0; n2<sL; n2++) {
 45.1155 +                c = JSIO.crc32Table[(c&0xff) ^ str.charCodeAt(n2)] ^ (c>>>8);
 45.1156 +            }
 45.1157 +        }
 45.1158 +        c ^= 0xFFFFFFFF;
 45.1159 +        if (c < 0) c += 0xFFFFFFFF+1;
 45.1160 +        return c;
 45.1161 +    };
 45.1162 +
 45.1163 +    // =======================================================
 45.1164 +    var _crc32 = function() {
 45.1165 +        if (! (this instanceof arguments.callee) ) this._throwError('You must use new to instantiate this class', typename, 'ctor');
 45.1166 +        crc32TableCalc(); // once
 45.1167 +        this._typename = typename;
 45.1168 +        this._version  = version;
 45.1169 +        this._runningCrc32 = 0xFFFFFFFF;
 45.1170 +    };
 45.1171 +
 45.1172 +    _crc32.prototype.slurpByte = function(b) {
 45.1173 +        var r = this._runningCrc32;
 45.1174 +        this._runningCrc32 = r>>>8 ^ JSIO.crc32Table[b ^ (r & 0x000000FF)];
 45.1175 +    };
 45.1176 +
 45.1177 +    _crc32.prototype.result = function() {
 45.1178 +        var c = this._runningCrc32 ^ 0xFFFFFFFF;
 45.1179 +        if (c < 0) c += 0xFFFFFFFF+1;
 45.1180 +        return c;
 45.1181 +    };
 45.1182 +    // =======================================================
 45.1183 +
 45.1184 +
 45.1185 +
 45.1186 +    var _crc32CalculatingReader = function(reader) {
 45.1187 +        if (! (this instanceof arguments.callee) ) this._throwError('You must use new to instantiate this class', 'JSIO.Crc32Reader', 'ctor');
 45.1188 +        this._byteReader = reader;
 45.1189 +        this._typename = "JSIO.Crc32Reader";
 45.1190 +        this._version = version;
 45.1191 +        this._crc32 = new JSIO.Crc32();
 45.1192 +    };
 45.1193 +
 45.1194 +    _crc32CalculatingReader.prototype = new JSIO._ByteReaderBase();
 45.1195 +
 45.1196 +    _crc32CalculatingReader.prototype.readByte = function() {
 45.1197 +        var b = this._byteReader.readByte();
 45.1198 +        if (b !== null) this._crc32.slurpByte(b);
 45.1199 +        this.position++;
 45.1200 +        return b;
 45.1201 +    };
 45.1202 +
 45.1203 +    _crc32CalculatingReader.prototype.read = function(len) {
 45.1204 +        if (len === 0) return [];
 45.1205 +        var bytes = this._byteReader.read(len);
 45.1206 +        len = bytes.length;
 45.1207 +
 45.1208 +        var tbl = JSIO.crc32Table;
 45.1209 +        var r = this._crc32._runningCrc32;
 45.1210 +        var t;
 45.1211 +        for (var i = 0; i < len; i++) {
 45.1212 +            t = tbl[ bytes[i] ^ (r & 0x000000FF) ];
 45.1213 +            r = (r >>> 8) ^ t;
 45.1214 +        }
 45.1215 +        this._crc32._runningCrc32 = r;
 45.1216 +
 45.1217 +        this.position += len;
 45.1218 +        return bytes;
 45.1219 +    }
 45.1220 +
 45.1221 +    _crc32CalculatingReader.prototype.crc32 = function() {
 45.1222 +        return this._crc32.result();
 45.1223 +    };
 45.1224 +
 45.1225 +    JSIO.Crc32 = _crc32;
 45.1226 +    JSIO.Crc32Reader = _crc32CalculatingReader;
 45.1227 +
 45.1228 +})();
 45.1229 +
 45.1230 +/// JSIO.CRC32.js ends
 45.1231 +// JSIO.InflatingReader.js
 45.1232 +// ------------------------------------------------------------------
 45.1233 +//
 45.1234 +// Part of the JSIO library.  This adds an Inflating ByteReader to
 45.1235 +// JSIO.
 45.1236 +//
 45.1237 +// =======================================================
 45.1238 +//
 45.1239 +// A ByteReader exposes an interface with these functions:
 45.1240 +//
 45.1241 +//    readByte()
 45.1242 +//       must return null when EOF is reached.
 45.1243 +//
 45.1244 +//    readToEnd()
 45.1245 +//       returns an array of all bytes read, to EOF
 45.1246 +//
 45.1247 +//    beginReadToEnd(callback)
 45.1248 +//       async version of the above
 45.1249 +//
 45.1250 +//    readBytes(n)
 45.1251 +//       returns an array of all n bytes read from the source
 45.1252 +//
 45.1253 +//    beginReadBytes(n, callback)
 45.1254 +//       async version of the above
 45.1255 +//
 45.1256 +// =======================================================
 45.1257 +//
 45.1258 +// Derived in part from work by notmasteryet.
 45.1259 +//   http://www.codeproject.com/KB/scripting/Javascript_binaryenc.aspx
 45.1260 +//
 45.1261 +// Copyleft (c) 2008, notmasteryet via an MIT-style license
 45.1262 +// Copyleft (c) 2010, Dino Chiesa via MS-PL
 45.1263 +// Copyleft (c) 2012, Brendan Byrd via GPL
 45.1264 +//
 45.1265 +// This work is licensed under the GPLv3.
 45.1266 +
 45.1267 +
 45.1268 +(function(){
 45.1269 +    var version = "2.0 2012Feb";
 45.1270 +    var typename = "JSIO.InflatingReader";
 45.1271 +
 45.1272 +    if (typeof JSIO._ByteReaderBase !== "function")
 45.1273 +        JSIO.throwError('This extension requires JSIO.BasicByteReaders.js', typename);
 45.1274 +
 45.1275 +    // =======================================================
 45.1276 +    //  _InternalBitReader is used internally in the InflatingReader class.
 45.1277 +    //
 45.1278 +
 45.1279 +    JSIO.bitShiftTable = null;
 45.1280 +
 45.1281 +    var bitShiftTableCalc = function () {
 45.1282 +        // do this once only, for all instances
 45.1283 +        if (JSIO.bitShiftTable) return;
 45.1284 +
 45.1285 +        var bits = 8;
 45.1286 +        JSIO.bitShiftTable = {
 45.1287 +            LSB: new Array(bits),
 45.1288 +            MSB: new Array(bits)
 45.1289 +        }
 45.1290 +        for (var bp = 0; bp < bits; bp++) {
 45.1291 +            var lim = bits - bp;
 45.1292 +            JSIO.bitShiftTable.LSB[bp] = new Array(lim);
 45.1293 +            JSIO.bitShiftTable.MSB[bp] = new Array(lim);
 45.1294 +
 45.1295 +            var maskLSB = 1 << bp;
 45.1296 +            var maskMSB = 1 << lim-1;
 45.1297 +            for (var len = 1; len <= lim; len++) {
 45.1298 +                JSIO.bitShiftTable.LSB[bp][len-1] = maskLSB;
 45.1299 +                JSIO.bitShiftTable.MSB[bp][len-1] = maskMSB;
 45.1300 +                maskLSB |= 1 << bp+len;
 45.1301 +                maskMSB |= 1 << lim-len-1;
 45.1302 +            }
 45.1303 +        }
 45.1304 +    };
 45.1305 +
 45.1306 +    var _InternalBitReader = function(reader) {
 45.1307 +        if (! (this instanceof arguments.callee) ) this._throwError('You must use new to instantiate this class', typename + '._InternalBitReader.ctor');
 45.1308 +        this.bitsLength = 0;
 45.1309 +        this.bits = 0;
 45.1310 +        this.byteReader = reader;
 45.1311 +        this._typeName = typename + "._InternalBitReader";
 45.1312 +        this._version = version;
 45.1313 +        bitShiftTableCalc();
 45.1314 +    };
 45.1315 +
 45.1316 +    _InternalBitReader.prototype._throwError = JSIO.throwError;
 45.1317 +
 45.1318 +    _InternalBitReader.prototype.readBit = function() {
 45.1319 +        if (this.bitsLength === 0) {
 45.1320 +            var nextByte = this.byteReader.readByte();
 45.1321 +            if (nextByte === null) this._throwError('Unexpected end of stream', null, 'readBit');
 45.1322 +            this.bits = nextByte;
 45.1323 +            this.bitsLength = 8;
 45.1324 +        }
 45.1325 +
 45.1326 +        var bit = (this.bits & 1 << 8-this.bitsLength) !== 0;
 45.1327 +        this.bitsLength--;
 45.1328 +        return bit;
 45.1329 +    };
 45.1330 +
 45.1331 +    _InternalBitReader.prototype.align = function() { this.bitsLength = 0; };
 45.1332 +
 45.1333 +    _InternalBitReader.prototype.readBits = function(len, type) {
 45.1334 +        var data = 0;
 45.1335 +        type = type || 'LSB';
 45.1336 +        var tbl = JSIO.bitShiftTable[type];
 45.1337 +        var dl = 0;
 45.1338 +        while (len > 0) {
 45.1339 +            if (this.bitsLength === 0) {
 45.1340 +                var nextByte = this.byteReader.readByte();
 45.1341 +                if (nextByte === null) this._throwError('Unexpected end of stream', null, 'read'+type);
 45.1342 +                this.bits = nextByte;
 45.1343 +                this.bitsLength = 8;
 45.1344 +            }
 45.1345 +
 45.1346 +            var maskLen = (this.bitsLength >= len) ? len : this.bitsLength;
 45.1347 +            var bitsPos = 8-this.bitsLength;
 45.1348 +            data |= (this.bits & tbl[bitsPos][maskLen-1]) >>> bitsPos << dl;
 45.1349 +
 45.1350 +            dl += maskLen;
 45.1351 +            len -= maskLen;
 45.1352 +            this.bitsLength -= maskLen;
 45.1353 +        };
 45.1354 +        return data;
 45.1355 +    };
 45.1356 +
 45.1357 +    _InternalBitReader.prototype.readLSB = function(len) { return this.readBits(len, 'LSB'); }
 45.1358 +    _InternalBitReader.prototype.readMSB = function(len) { return this.readBits(len, 'MSB'); }
 45.1359 +
 45.1360 +    //
 45.1361 +    // =======================================================
 45.1362 +
 45.1363 +
 45.1364 +    /* inflating ByteReader - RFC 1951 */
 45.1365 +    var _inflatingReader = function(reader) {
 45.1366 +        if (! (this instanceof arguments.callee) ) this._throwError('You must use new to instantiate this class', typename, 'ctor');
 45.1367 +        this._byteReader = reader;
 45.1368 +        this._bitReader = new _InternalBitReader(reader);
 45.1369 +        this._buffer = [];
 45.1370 +        this._bufferPosition = 0;
 45.1371 +        this._state = 0;
 45.1372 +        this._blockFinal = false;
 45.1373 +        this._typeName = typename;
 45.1374 +        this._version = version;
 45.1375 +        return this;
 45.1376 +    };
 45.1377 +
 45.1378 +
 45.1379 +    // shared fns and variables
 45.1380 +
 45.1381 +    var staticCodes = null;
 45.1382 +    var staticDistances = null;
 45.1383 +
 45.1384 +    var clenMap = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15];
 45.1385 +
 45.1386 +    var buildCodes = function(lengths){
 45.1387 +        var i=0;
 45.1388 +        var codes = new Array(lengths.length);
 45.1389 +        var maxBits = lengths[0];
 45.1390 +        for (i=1; i<lengths.length; i++) {
 45.1391 +            if (maxBits < lengths[i]) maxBits = lengths[i];
 45.1392 +        }
 45.1393 +
 45.1394 +        var bitLengthsCount = new Array(maxBits + 1);
 45.1395 +        for (i=0; i<=maxBits; i++) bitLengthsCount[i]=0;
 45.1396 +
 45.1397 +        for (i=0; i<lengths.length; i++) {
 45.1398 +            ++bitLengthsCount[lengths[i]];
 45.1399 +        }
 45.1400 +
 45.1401 +        var nextCode = new Array(maxBits + 1);
 45.1402 +        var code = 0;
 45.1403 +        bitLengthsCount[0] = 0;
 45.1404 +        for (var bits=1; bits<=maxBits; bits++) {
 45.1405 +            code = (code + bitLengthsCount[bits - 1]) << 1;
 45.1406 +            nextCode[bits] = code;
 45.1407 +        }
 45.1408 +
 45.1409 +        for (i=0; i<codes.length; i++) {
 45.1410 +            var len = lengths[i];
 45.1411 +            if (len !== 0) {
 45.1412 +                codes[i] = nextCode[len];
 45.1413 +                nextCode[len]++;
 45.1414 +            }
 45.1415 +        }
 45.1416 +        return codes;
 45.1417 +    };
 45.1418 +
 45.1419 +    var buildTree = function(codes, lengths){
 45.1420 +        var nonEmptyCodes = [];
 45.1421 +        for(var i=0; i<codes.length; ++i) {
 45.1422 +            if(lengths[i] > 0) {
 45.1423 +                var code = {};
 45.1424 +                code.bits = codes[i];
 45.1425 +                code.length = lengths[i];
 45.1426 +                code.index = i;
 45.1427 +                nonEmptyCodes.push(code);
 45.1428 +            }
 45.1429 +        }
 45.1430 +        return buildTreeBranch(nonEmptyCodes, 0, 0);
 45.1431 +    };
 45.1432 +
 45.1433 +
 45.1434 +    var buildTreeBranch = function(codes, prefix, prefixLength){
 45.1435 +        if (codes.length === 0) return null;
 45.1436 +
 45.1437 +        var zeros = [];
 45.1438 +        var ones = [];
 45.1439 +        var branch = {};
 45.1440 +        branch.isLeaf = false;
 45.1441 +        for(var i=0; i<codes.length; ++i) {
 45.1442 +            if (codes[i].length == prefixLength && codes[i].bits == prefix) {
 45.1443 +                branch.isLeaf = true;
 45.1444 +                branch.index = codes[i].index;
 45.1445 +                break;
 45.1446 +            }
 45.1447 +            else {
 45.1448 +                var nextBit = ((codes[i].bits >> (codes[i].length - prefixLength - 1)) & 1) > 0;
 45.1449 +                if (nextBit)  ones.push(codes[i]);
 45.1450 +                else         zeros.push(codes[i]);
 45.1451 +            }
 45.1452 +        }
 45.1453 +        if(!branch.isLeaf) {
 45.1454 +            branch.zero = buildTreeBranch(zeros, (prefix << 1), prefixLength + 1);
 45.1455 +            branch.one = buildTreeBranch(ones, (prefix << 1) | 1, prefixLength + 1);
 45.1456 +        }
 45.1457 +        return branch;
 45.1458 +    };
 45.1459 +
 45.1460 +
 45.1461 +    var encodedLengthStart = [3,4,5,6,7,8,9,10,
 45.1462 +                              11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,
 45.1463 +                              115,131,163,195,227,258];
 45.1464 +
 45.1465 +    var encodedLengthAdditionalBits = [0,0,0,0,0,0,0,0,
 45.1466 +                                       1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0];
 45.1467 +
 45.1468 +    var encodedDistanceStart = [1,2,3,4, 5,7,9, 13,17,25, 33,49,65,
 45.1469 +                                97,129,193,257,385,513,769,1025,1537,2049,
 45.1470 +                                3073,4097,6145,8193,12289,16385,24577];
 45.1471 +
 45.1472 +    var encodedDistanceAdditionalBits = [0,0,0,0,1,1,2,2,3,3,4,4,
 45.1473 +                                         5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13];
 45.1474 +
 45.1475 +
 45.1476 +    var readDynamicTrees = function(bitReader){
 45.1477 +        var hlit  = bitReader.readLSB(5) + 257;
 45.1478 +        var hdist = bitReader.readLSB(5) + 1;
 45.1479 +        var hclen = bitReader.readLSB(4) + 4;
 45.1480 +        var clen  = new Array(19);
 45.1481 +        var i;
 45.1482 +        for (i=0; i<clen.length; i++) { clen[i]          = 0; }
 45.1483 +        for (i=0; i<hclen;       i++) { clen[clenMap[i]] = bitReader.readLSB(3); }
 45.1484 +
 45.1485 +        var clenCodes = buildCodes(clen);
 45.1486 +        var clenTree  = buildTree(clenCodes, clen);
 45.1487 +
 45.1488 +        var lengthsSequence = [];
 45.1489 +        while(lengthsSequence.length < hlit + hdist) {
 45.1490 +            var p = clenTree;
 45.1491 +            while(!p.isLeaf) { p = bitReader.readBit() ? p.one : p.zero; }
 45.1492 +
 45.1493 +            var code = p.index;
 45.1494 +            if      (code <= 15) lengthsSequence.push(code);
 45.1495 +            else if (code == 16) {
 45.1496 +                // TODO: replace with faster repeat algorythm
 45.1497 +                var repeat = bitReader.readLSB(2) + 3;
 45.1498 +                for(var q=0; q<repeat; ++q){
 45.1499 +                    lengthsSequence.push(lengthsSequence[lengthsSequence.length - 1]);
 45.1500 +                }
 45.1501 +            }
 45.1502 +            else if (code == 17) {
 45.1503 +                var repeat1 = bitReader.readLSB(3) + 3;
 45.1504 +                for(var q1=0; q1<repeat1; ++q1) {
 45.1505 +                    lengthsSequence.push(0);
 45.1506 +                }
 45.1507 +            }
 45.1508 +            else if (code == 18) {
 45.1509 +                var repeat2 = bitReader.readLSB(7) + 11;
 45.1510 +                for(var q2=0; q2<repeat2; ++q2){
 45.1511 +                    lengthsSequence.push(0);
 45.1512 +                }
 45.1513 +            }
 45.1514 +        }
 45.1515 +
 45.1516 +        var codesLengths     = lengthsSequence.slice(0, hlit);
 45.1517 +        var codes            = buildCodes(codesLengths);
 45.1518 +        var distancesLengths = lengthsSequence.slice(hlit, hlit + hdist);
 45.1519 +        var distances        = buildCodes(distancesLengths);
 45.1520 +
 45.1521 +        return {
 45.1522 +            codesTree     : buildTree(codes,     codesLengths),
 45.1523 +            distancesTree : buildTree(distances, distancesLengths)
 45.1524 +        };
 45.1525 +    };
 45.1526 +
 45.1527 +
 45.1528 +    _inflatingReader.prototype = new JSIO._ByteReaderBase();
 45.1529 +
 45.1530 +
 45.1531 +    // internal instance fns
 45.1532 +    _inflatingReader.prototype._decodeItem = function() {
 45.1533 +        if (this._state == 2) return null;  // end-of-blocks
 45.1534 +
 45.1535 +        var item;
 45.1536 +        if(this._state === 0) {
 45.1537 +            this._blockFinal = this._bitReader.readBit();
 45.1538 +            var blockType = this._bitReader.readLSB(2);
 45.1539 +            switch(blockType) {
 45.1540 +            case 0:
 45.1541 +                this._bitReader.align();
 45.1542 +                var len  = this._bitReader.readLSB(16);  // low-byte first, as opposed to readNumber's HBF
 45.1543 +                var nlen = this._bitReader.readLSB(16);
 45.1544 +                if ((len & ~nlen) != len) this._throwError('Invalid block type 0 length', null, '_decodeItem');
 45.1545 +
 45.1546 +                item = {};
 45.1547 +                item.itemType = 0;
 45.1548 +                item.array = this._bitReader.byteReader.read(len);
 45.1549 +                if (item.array.length < len) this._throwError('Incomplete block', null, '_decodeItem');
 45.1550 +                if (this._blockFinal) this._state = 2;
 45.1551 +                return item;
 45.1552 +            case 1:
 45.1553 +                this._codesTree = staticCodes;
 45.1554 +                this._distancesTree = staticDistances;
 45.1555 +                this._state = 1;
 45.1556 +                break;
 45.1557 +            case 2:
 45.1558 +                var dTrees = readDynamicTrees(this._bitReader);
 45.1559 +                this._codesTree = dTrees.codesTree;
 45.1560 +                this._distancesTree = dTrees.distancesTree;
 45.1561 +                this._state = 1;
 45.1562 +                break;
 45.1563 +            default:
 45.1564 +                this._throwError('Invalid block type ('+ blockType +')', null, '_decodeItem');
 45.1565 +            }
 45.1566 +        }
 45.1567 +
 45.1568 +        item = {};
 45.1569 +
 45.1570 +        var p = this._codesTree;
 45.1571 +        while (!p.isLeaf) { p = this._bitReader.readBit() ? p.one : p.zero; }
 45.1572 +        if(p.index < 256) {
 45.1573 +            item.itemType = 2;
 45.1574 +            item.symbol = p.index;
 45.1575 +        } else if(p.index > 256) {
 45.1576 +            var lengthCode = p.index;
 45.1577 +            if(lengthCode > 285) this._throwError('Invalid length code', null, '_decodeItem');
 45.1578 +
 45.1579 +            var length = encodedLengthStart[lengthCode - 257];
 45.1580 +            if(encodedLengthAdditionalBits[lengthCode - 257] > 0) {
 45.1581 +                length += this._bitReader.readLSB(encodedLengthAdditionalBits[lengthCode - 257]);
 45.1582 +            }
 45.1583 +
 45.1584 +            p = this._distancesTree;
 45.1585 +            while (!p.isLeaf) { p = this._bitReader.readBit() ? p.one : p.zero; }
 45.1586 +
 45.1587 +            var distanceCode = p.index;
 45.1588 +            var distance = encodedDistanceStart[distanceCode];
 45.1589 +            if (encodedDistanceAdditionalBits[distanceCode] > 0)
 45.1590 +                distance += this._bitReader.readLSB(encodedDistanceAdditionalBits[distanceCode]);
 45.1591 +
 45.1592 +            item.itemType = 3;
 45.1593 +            item.distance = distance;
 45.1594 +            item.length = length;
 45.1595 +        } else {
 45.1596 +            item.itemType = 1;
 45.1597 +            this._state = this._blockFinal ? 2 : 0;  // EOB
 45.1598 +        }
 45.1599 +        return item;
 45.1600 +    };
 45.1601 +
 45.1602 +
 45.1603 +
 45.1604 +    // public instance functions
 45.1605 +
 45.1606 +    _inflatingReader.prototype.readByte = function() {
 45.1607 +        var byte = this.read(1)[0];
 45.1608 +        return (byte === null || byte === undefined) ? null : byte;
 45.1609 +    };
 45.1610 +
 45.1611 +    _inflatingReader.prototype.read = function(len) {
 45.1612 +        var b = this._buffer;  // (since we use this so much...)
 45.1613 +
 45.1614 +        // Keep reading until we get to the right length
 45.1615 +        while (this._bufferPosition+len > b.length) {
 45.1616 +            var item = this._decodeItem();
 45.1617 +            if (item === null) {  // EOF
 45.1618 +                len = b.length - this._bufferPosition;
 45.1619 +                break;
 45.1620 +            }
 45.1621 +            switch(item.itemType) {
 45.1622 +                case 0:
 45.1623 +                    JSIO.massApply(b.push, b, item.array);
 45.1624 +                    break;
 45.1625 +                case 2:
 45.1626 +                    b.push(item.symbol);
 45.1627 +                    break;
 45.1628 +                case 3:
 45.1629 +                    var j = b.length - item.distance;
 45.1630 +                    if (item.distance >= item.length)
 45.1631 +                        JSIO.massApply(b.push, b, b.slice(j, j+item.length));
 45.1632 +                    // sometimes DEFLATE tries some trickery with "look-ahead" compression
 45.1633 +                    else {
 45.1634 +                        // this is basically just a repetition of the same string, plus some possible cutoff
 45.1635 +                        var count = parseInt(item.length / item.distance);
 45.1636 +                        var repArr = b.slice(j);
 45.1637 +                        // http://stackoverflow.com/questions/202605/repeat-string-javascript/5450113#5450113
 45.1638 +                        while (count > 0) {
 45.1639 +                            if (count   & 1) JSIO.massApply(     b.push,      b, repArr);
 45.1640 +                            if (count >>= 1) JSIO.massApply(repArr.push, repArr, repArr);
 45.1641 +                        }
 45.1642 +                        // add any remaining cutoff
 45.1643 +                        var r;
 45.1644 +                        if (r = item.length % item.distance)
 45.1645 +                            JSIO.massApply(b.push, b, b.slice(j, j+r));
 45.1646 +                    }
 45.1647 +                    break;
 45.1648 +            }
 45.1649 +        }
 45.1650 +        var bytes = b.slice(this._bufferPosition, this._bufferPosition+len);
 45.1651 +        this._bufferPosition += len;
 45.1652 +        this.position        += len;
 45.1653 +
 45.1654 +        if (this._bufferPosition > 0xC000) {
 45.1655 +            var shift = b.length - 0x8000;
 45.1656 +            if (shift > this._bufferPosition) shift = this._bufferPosition;
 45.1657 +            b.splice(0, shift);
 45.1658 +            this._bufferPosition -= shift;
 45.1659 +        }
 45.1660 +
 45.1661 +        return bytes;
 45.1662 +    };
 45.1663 +
 45.1664 +    // initialization routine - once per type
 45.1665 +    (function(){
 45.1666 +
 45.1667 +        var codes = new Array(288);
 45.1668 +        var codesLengths = new Array(288);
 45.1669 +        var i=0;
 45.1670 +        for ( i = 0;   i <= 143; i++) {
 45.1671 +            codes[i] = 0x0030 + i;
 45.1672 +            codesLengths[i] = 8;
 45.1673 +        }
 45.1674 +        for ( i = 144; i <= 255; i++) {
 45.1675 +            codes[i] = 0x0190 + i - 144;
 45.1676 +            codesLengths[i] = 9;
 45.1677 +        }
 45.1678 +        for ( i = 256; i <= 279; i++) {
 45.1679 +            codes[i] = 0x0000 + i - 256;
 45.1680 +            codesLengths[i] = 7;
 45.1681 +        }
 45.1682 +        for ( i = 280; i <= 287; i++) {
 45.1683 +            codes[i] = 0x00C0 + i - 280;
 45.1684 +            codesLengths[i] = 8;
 45.1685 +        }
 45.1686 +        staticCodes = buildTree(codes, codesLengths);
 45.1687 +
 45.1688 +        var distances = new Array(32);
 45.1689 +        var distancesLengths = new Array(32);
 45.1690 +        for ( i = 0; i <= 31; i++) {
 45.1691 +            distances[i] = i;
 45.1692 +            distancesLengths[i] = 5;
 45.1693 +        }
 45.1694 +        staticDistances = buildTree(distances, distancesLengths);
 45.1695 +    })();
 45.1696 +
 45.1697 +
 45.1698 +    JSIO.InflatingReader = _inflatingReader;
 45.1699 +
 45.1700 +})();
 45.1701 +
 45.1702 +
 45.1703 +/// JSIO.InflatingReader.js ends
 45.1704 +
 45.1705 +// Zipfile.js
 45.1706 +// ------------------------------------------------------------------
 45.1707 +//
 45.1708 +// A class that reads Zip files.
 45.1709 +// Depends on the JSIO library functions.
 45.1710 +//
 45.1711 +// =======================================================
 45.1712 +//
 45.1713 +// Copyleft (c) 2010, Dino Chiesa via MS-PL
 45.1714 +// Copyleft (c) 2012, Brendan Byrd via GPL
 45.1715 +//
 45.1716 +// This work is licensed under the GPLv3.
 45.1717 +
 45.1718 +(function(){
 45.1719 +    var version = "2.0 2012Feb";
 45.1720 +    var typename = "Zipfile";
 45.1721 +
 45.1722 +    if (typeof JSIO.BinaryUrlStream !== "function") JSIO.throwError('This extension requires JSIO.BinaryUrlStream.js v2.0', typename);
 45.1723 +    if (typeof JSIO.TextDecoder     !== "object")   JSIO.throwError('This extension requires JSIO.TextDecoder.js v2.0',     typename);
 45.1724 +    if (typeof JSIO.TextReader      !== "function") JSIO.throwError('This extension requires JSIO.TextReader.js v2.0',      typename);
 45.1725 +    if (typeof JSIO.Crc32           !== "function") JSIO.throwError('This extension requires JSIO.Crc32.js v2.0',           typename);
 45.1726 +    if (typeof JSIO.InflatingReader !== "function") JSIO.throwError('This extension requires JSIO.InflatingReader.js v2.0', typename);
 45.1727 +
 45.1728 +    // =======================================================
 45.1729 +    function ZipEntry(zip) {
 45.1730 +        this.zipfile = zip;
 45.1731 +        this._typename = "ZipEntry";
 45.1732 +        this._version = version;
 45.1733 +        this._crcCalculator = null;
 45.1734 +    }
 45.1735 +
 45.1736 +    ZipEntry.prototype._throwError = JSIO.throwError;
 45.1737 +
 45.1738 +    // return byte array or string
 45.1739 +    ZipEntry.prototype.extract = function(callback, asString) {
 45.1740 +        this.contentType = JSIO.guessFileType(this.name);
 45.1741 +        asString = asString || ( this.contentType == JSIO.FileType.Text ||
 45.1742 +                                 this.contentType == JSIO.FileType.XML);
 45.1743 +        var thisEntry = this;
 45.1744 +
 45.1745 +        if (this.compressionMethod !== 0 && this.compressionMethod != 8)
 45.1746 +            this._throwError('Unsupported compression method: ' + this.compressionMethod, null, 'extract');
 45.1747 +
 45.1748 +        var reader = (asString) ? this.openTextReader(thisEntry.utf8 ? JSIO.TextDecoder.UTF8 : JSIO.TextDecoder.ANSI) : this.openBinaryReader();
 45.1749 +
 45.1750 +        // diagnostic purpose only; tag the reader with the entry name
 45.1751 +        reader.zipEntryName = thisEntry.name;
 45.1752 +
 45.1753 +        if (typeof callback != "function") {
 45.1754 +            // synchronous
 45.1755 +            var result = reader.readToEnd();
 45.1756 +            this.verifyCrc32();
 45.1757 +            return result;
 45.1758 +        }
 45.1759 +
 45.1760 +        // asynchronous
 45.1761 +        reader.beginReadToEnd(function(result){
 45.1762 +            try {
 45.1763 +                thisEntry.verifyCrc32();
 45.1764 +                callback(thisEntry, result);
 45.1765 +            }
 45.1766 +            catch (exc1) {
 45.1767 +                callback(thisEntry, exc1);
 45.1768 +            }
 45.1769 +        });
 45.1770 +        return null;
 45.1771 +    };
 45.1772 +
 45.1773 +
 45.1774 +    // open a ByteReader on the entry, which will read binary
 45.1775 +    // content from the compressed stream.
 45.1776 +    ZipEntry.prototype.openBinaryReader = function() {
 45.1777 +        var reader =
 45.1778 +                new JSIO.StreamSegmentReader(this.zipfile.binaryStream,
 45.1779 +                                             this.offset + this.lengthOfHeader,
 45.1780 +                                             this.compressedSize);
 45.1781 +        if (this.compressionMethod === 0) {
 45.1782 +            this._crcCalculator = new JSIO.Crc32Reader(reader);
 45.1783 +        }
 45.1784 +        else {
 45.1785 +            var inflator = new JSIO.InflatingReader(reader);
 45.1786 +            this._crcCalculator = new JSIO.Crc32Reader(inflator);
 45.1787 +        }
 45.1788 +        // Whether compressed or not, the source ByteReader in each case
 45.1789 +        // is wrapped in a second ByteReader object that calculates CRC
 45.1790 +        // as it reads.  That way, after all reading is complete, the
 45.1791 +        // caller can check the calcuated CRC against the expected CRC.
 45.1792 +        return this._crcCalculator;
 45.1793 +    };
 45.1794 +
 45.1795 +    // open a TextReader on the entry, to read text from the
 45.1796 +    // compressed stream.
 45.1797 +    ZipEntry.prototype.openTextReader = function(decoderKind) {
 45.1798 +        var reader = this.openBinaryReader();
 45.1799 +        decoderKind = decoderKind || JSIO.TextDecoder.UTF8;
 45.1800 +        var d = new decoderKind(reader);
 45.1801 +        var textReader = new JSIO.TextReader(d);
 45.1802 +        d._parent = textReader;  // store a reference, for diagnostic purposes only
 45.1803 +        return textReader;
 45.1804 +    };
 45.1805 +
 45.1806 +    // verify the CRC on the entry.
 45.1807 +    // call this after all bytes have been read.
 45.1808 +    ZipEntry.prototype.verifyCrc32 = function() {
 45.1809 +        var computedCrc = this._crcCalculator.crc32();
 45.1810 +        var rc = false;  // CRC FAIL
 45.1811 +        if (this.crc32 != computedCrc) {
 45.1812 +            var msg = "WARNING: CRC check failed: " +
 45.1813 +                "entry(" + this.name + ") " +
 45.1814 +                "computed(" + JSIO.decimalToHexString(computedCrc,8) + ") " +
 45.1815 +                "expected(" + JSIO.decimalToHexString(this.crc32,8) + ") ";
 45.1816 +            this.zipfile.status.push(msg);
 45.1817 +        } else {
 45.1818 +            rc = true;  // OK
 45.1819 +            if (this.zipfile.verbose>2) {
 45.1820 +                this.zipfile.status.push("INFO: CRC check ok: 0x" +
 45.1821 +                                         JSIO.decimalToHexString(this.crc32,8));
 45.1822 +            }
 45.1823 +        }
 45.1824 +        return rc;
 45.1825 +    };
 45.1826 +
 45.1827 +
 45.1828 +    // ctor
 45.1829 +    ZipFile = function(fileUrl, callback, verbosity) {
 45.1830 +        if (! (this instanceof arguments.callee) ) JSIO.throwError('You must use new to instantiate this class', typename, 'ctor');
 45.1831 +
 45.1832 +        this.verbose     = verbosity || 0;
 45.1833 +        this.entries     = [];
 45.1834 +        this.entryNames  = [];
 45.1835 +        this.status      = [];
 45.1836 +        this._version    = version;
 45.1837 +        this._typename   = "ZipFile";
 45.1838 +        this._throwError = JSIO.throwError;
 45.1839 +
 45.1840 +        var thisZipFile = this;
 45.1841 +
 45.1842 +        // Could use a back-tracking reader for the central directory, but
 45.1843 +        // there's no point, since all the zip data is held in memory anyway.
 45.1844 +
 45.1845 +        /* function ReadCentralDirectory(){
 45.1846 +            var posn = thisZipFile.binaryStream.length - 64;
 45.1847 +            var maxSeekback = Math.Max(s.Length - 0x4000, 10);
 45.1848 +            var success = false;
 45.1849 +            var nTries = 0;
 45.1850 +            do
 45.1851 +            {
 45.1852 +                thisZipFile.binaryStream.Seek(posn, SeekOrigin.Begin);
 45.1853 +                var bytesRead = thisZipFile.binaryStream.findSignature(thisZipFile.Signatures.EndOfCentralDirectory);
 45.1854 +                if (bytesRead != -1)
 45.1855 +                    success = true;
 45.1856 +                else
 45.1857 +                {
 45.1858 +                    nTries++;
 45.1859 +                    // increasingly larger
 45.1860 +                    posn -= (32 * (nTries + 1) * nTries);
 45.1861 +                    if (posn < 0) posn = 0;  // BOF
 45.1862 +                }
 45.1863 +            }
 45.1864 +            while (!success && posn > maxSeekback);
 45.1865 +            if (!success) {
 45.1866 +                thisZipFile.status.push("cannot find End of Central Directory");
 45.1867 +                return;
 45.1868 +            }
 45.1869 +        } */
 45.1870 +
 45.1871 +
 45.1872 +        function DateFromPackedFormat(packed) {
 45.1873 +            if (packed == 0xFFFF || packed === 0) return new Date(1995, 0, 1, 0,0,0,0);
 45.1874 +
 45.1875 +            var packedTime = packed & 0x0000ffff;
 45.1876 +            var packedDate = ((packed & 0xffff0000) >> 16);
 45.1877 +
 45.1878 +            var year = 1980 + ((packedDate & 0xFE00) >> 9);
 45.1879 +            var month = ((packedDate & 0x01E0) >> 5) -1;
 45.1880 +            var day = packedDate & 0x001F;
 45.1881 +
 45.1882 +            var hour = (packedTime & 0xF800) >> 11;
 45.1883 +            var minute = (packedTime & 0x07E0) >> 5;
 45.1884 +            var second = (packedTime & 0x001F) * 2;
 45.1885 +
 45.1886 +            // Validation and error checking.
 45.1887 +            // This is not foolproof but will catch most errors.
 45.1888 +
 45.1889 +            // I can't believe how many different ways applications
 45.1890 +            // can mess up a simple date format.
 45.1891 +
 45.1892 +            if (second >= 60) { minute++; second = 0; }
 45.1893 +            if (minute >= 60) { hour++;   minute = 0; }
 45.1894 +            if (hour   >= 24) { day++;    hour   = 0; }
 45.1895 +            var success = false;
 45.1896 +            var d;
 45.1897 +            try {
 45.1898 +                d = new Date(year, month, day, hour, minute, second, 0);
 45.1899 +                success= true;
 45.1900 +            }
 45.1901 +            catch (exc1) {
 45.1902 +                if (year == 1980 && (month === 0 || day === 0)) {
 45.1903 +                    try {
 45.1904 +                        d = new Date(1980, 0, 1, hour, minute, second, 0);
 45.1905 +                        success= true;
 45.1906 +                    }
 45.1907 +                    catch (exc2) {
 45.1908 +                        try {
 45.1909 +                            d = new Date(1980, 0, 1, 0, 0, 0, 0);
 45.1910 +                            success= true;
 45.1911 +                        }
 45.1912 +                        catch (exc3) { }  // how could this fail??
 45.1913 +                    }
 45.1914 +                }
 45.1915 +                else {
 45.1916 +                    try {
 45.1917 +                        if (year   < 1980) year   = 1980;
 45.1918 +                        if (year   > 2030) year   = 2030;
 45.1919 +                        if (month  < 1)    month  = 1;
 45.1920 +                        if (month  > 12)   month  = 12;
 45.1921 +                        if (day    < 1)    day    = 1;
 45.1922 +                        if (day    > 31)   day    = 31;
 45.1923 +                        if (minute < 0)    minute = 0;
 45.1924 +                        if (minute > 59)   minute = 59;
 45.1925 +                        if (second < 0)    second = 0;
 45.1926 +                        if (second > 59)   second = 59;
 45.1927 +                        d = new Date(year, month-1, day, hour, minute, second, 0);
 45.1928 +                        success= true;
 45.1929 +                    }
 45.1930 +                    catch (exc4){}
 45.1931 +                }
 45.1932 +            }
 45.1933 +            if (!success) this._throwError('Bad date/time value in this ZIP file', null, 'DateFromPackedFormat');
 45.1934 +            return d;
 45.1935 +        }
 45.1936 +
 45.1937 +
 45.1938 +        function ReadZipEntries () {
 45.1939 +            // read only once
 45.1940 +            if (thisZipFile.entryNames.length === 0){
 45.1941 +                var e;
 45.1942 +                while ((e = ReadZipEntry()) !== null) {
 45.1943 +                    thisZipFile.entries.push(e);
 45.1944 +                    thisZipFile.entryNames.push(e.name);
 45.1945 +                }
 45.1946 +            }
 45.1947 +        }
 45.1948 +
 45.1949 +
 45.1950 +        function ReadZipEntry () {
 45.1951 +            var offset = thisZipFile.binaryStream.position;
 45.1952 +            var sig = thisZipFile.binaryStream.readNumber(4);
 45.1953 +            if (sig == ZipFile.Signatures.DirEntry) {
 45.1954 +                // after all entries, comes the central directory
 45.1955 +                if (thisZipFile.verbose > 0) {
 45.1956 +                    thisZipFile.status.push("INFO: at offset 0x" +
 45.1957 +                                     JSIO.decimalToHexString(offset) +
 45.1958 +                                     ", found start of Zip Directory.");
 45.1959 +                }
 45.1960 +                // all done reading
 45.1961 +                return null;
 45.1962 +            }
 45.1963 +            if (sig != ZipFile.Signatures.Entry) {
 45.1964 +                thisZipFile.status.push("WARNING: at offset 0x" +
 45.1965 +                                 JSIO.decimalToHexString(offset) +
 45.1966 +                                 ", found unexpected signature: 0x" +
 45.1967 +                                 JSIO.decimalToHexString(sig));
 45.1968 +                return null;
 45.1969 +            }
 45.1970 +
 45.1971 +            var entry = new ZipEntry(thisZipFile);
 45.1972 +            entry.offset            = offset;
 45.1973 +            entry.versionNeeded     = thisZipFile.binaryStream.readNumber(2);
 45.1974 +            entry.bitField          = thisZipFile.binaryStream.readNumber(2);
 45.1975 +            entry.compressionMethod = thisZipFile.binaryStream.readNumber(2);
 45.1976 +            var timeBlob            = thisZipFile.binaryStream.readNumber(4);
 45.1977 +            entry.lastModified      = DateFromPackedFormat(timeBlob);
 45.1978 +            entry.crc32             = thisZipFile.binaryStream.readNumber(4);
 45.1979 +            entry.compressedSize    = thisZipFile.binaryStream.readNumber(4);
 45.1980 +            entry.uncompressedSize  = thisZipFile.binaryStream.readNumber(4);
 45.1981 +
 45.1982 +            if ((entry.bitField & 0x01) == 0x01){
 45.1983 +                thisZipFile.status.push("This zipfile uses Encryption, which is not supported by ZipFile.js.");
 45.1984 +                return null;
 45.1985 +            }
 45.1986 +
 45.1987 +            entry.utf8 = ((entry.bitField & 0x0800) == 0x0800);
 45.1988 +
 45.1989 +            if ((entry.bitField & 0x0008) == 0x0008){
 45.1990 +                thisZipFile.status.push("This zipfile uses a bit 3 trailing data descriptor, which is not supported by ZipFile.js.");
 45.1991 +                return null;
 45.1992 +            }
 45.1993 +
 45.1994 +            if (entry.compressedSize == 0xFFFFFFFF ||
 45.1995 +                entry.uncompressedSize == 0xFFFFFFFF) {
 45.1996 +                thisZipFile.status.push("This zipfile uses ZIP64, which is not supported by ZipFile.js");
 45.1997 +                return null;
 45.1998 +            }
 45.1999 +
 45.2000 +            var filenameLength   = thisZipFile.binaryStream.readNumber(2);
 45.2001 +            var extraFieldLength = thisZipFile.binaryStream.readNumber(2);
 45.2002 +
 45.2003 +            thisZipFile.status.push("INFO: filename length= " + filenameLength);
 45.2004 +
 45.2005 +            // we've read 30 bytes of metadata so far
 45.2006 +            var bytesRead = 30 + filenameLength + extraFieldLength;
 45.2007 +
 45.2008 +            if (entry.utf8) {
 45.2009 +                thisZipFile.status.push("INFO: before filename, position= 0x" +
 45.2010 +                                        JSIO.decimalToHexString( thisZipFile.binaryStream.position ));
 45.2011 +                var binReader =
 45.2012 +                    new JSIO.StreamSegmentReader(thisZipFile.binaryStream,
 45.2013 +                                                 thisZipFile.binaryStream.position,
 45.2014 +                                                 filenameLength);
 45.2015 +                var utf8Decoder = new JSIO.TextDecoder.UTF8(binReader);
 45.2016 +                var textReader  = new JSIO.TextReader(utf8Decoder);
 45.2017 +                entry.name = textReader.readToEnd();
 45.2018 +
 45.2019 +                // advance the filepointer:
 45.2020 +                thisZipFile.binaryStream.seek(filenameLength,
 45.2021 +                                              JSIO.SeekOrigin.Current,
 45.2022 +                                              thisZipFile);
 45.2023 +
 45.2024 +                thisZipFile.status.push("INFO: after filename, position= 0x" +
 45.2025 +                                        JSIO.decimalToHexString( thisZipFile.binaryStream.position ));
 45.2026 +            }
 45.2027 +            else {
 45.2028 +                entry.name = thisZipFile.binaryStream.readString(filenameLength);
 45.2029 +            }
 45.2030 +
 45.2031 +            // There are a bunch of things in the "extra" header, thisZipFile we
 45.2032 +            // could parse, like timestamps and other things.  This class
 45.2033 +            // only identifies and separates them.
 45.2034 +
 45.2035 +            // More info here: http://www.pkware.com/documents/casestudies/APPNOTE.TXT
 45.2036 +
 45.2037 +            var extraPos = 0;
 45.2038 +            entry.extra = [];
 45.2039 +            while (extraPos < extraFieldLength) {
 45.2040 +                var extraBlock = {
 45.2041 +                    type: thisZipFile.binaryStream.readNumber(2),
 45.2042 +                    size: thisZipFile.binaryStream.readNumber(2)
 45.2043 +                };
 45.2044 +                extraBlock.typeDescription = ZipFile.ExtraFieldTypes[extraBlock.type];
 45.2045 +                extraBlock.data = thisZipFile.binaryStream.read(extraBlock.size);
 45.2046 +                entry.extra.push(extraBlock);
 45.2047 +                extraPos += 4 + extraBlock.size;
 45.2048 +            }
 45.2049 +
 45.2050 +            if (thisZipFile.verbose > 1) {
 45.2051 +                thisZipFile.status.push("INFO: at offset 0x" +
 45.2052 +                             JSIO.decimalToHexString(entry.offset) +
 45.2053 +                             ", found entry '" + entry.name + "' fnl(" +
 45.2054 +                             filenameLength + ") efl(" +
 45.2055 +                             extraFieldLength +")");
 45.2056 +            }
 45.2057 +
 45.2058 +            if (extraFieldLength > 0) {
 45.2059 +                if (thisZipFile.verbose > 0) {
 45.2060 +                    thisZipFile.status.push("INFO: entry " + entry.name + " has " +
 45.2061 +                                     extraFieldLength + " bytes of " +
 45.2062 +                                     "extra metadata (ID'd but ignored)");
 45.2063 +                }
 45.2064 +            }
 45.2065 +
 45.2066 +            entry.lengthOfHeader = bytesRead;
 45.2067 +            entry.totalEntrySize = entry.lengthOfHeader + entry.compressedSize;
 45.2068 +
 45.2069 +            // seek past the data without reading it. We will read on Extract()
 45.2070 +            if (thisZipFile.verbose > 1) {
 45.2071 +                thisZipFile.status.push("INFO: seek 0x" +
 45.2072 +                                 JSIO.decimalToHexString(entry.compressedSize) +
 45.2073 +                                 " (" + entry.compressedSize + ") bytes");
 45.2074 +            }
 45.2075 +
 45.2076 +            thisZipFile.binaryStream.seek(entry.compressedSize,
 45.2077 +                              JSIO.SeekOrigin.Current,
 45.2078 +                              thisZipFile);
 45.2079 +
 45.2080 +            return entry;
 45.2081 +        }
 45.2082 +
 45.2083 +
 45.2084 +        var parseZipFile = function(bfr){
 45.2085 +            try {
 45.2086 +                if (bfr.req.status == 200) {
 45.2087 +                    var sig = thisZipFile.binaryStream.readNumber(4);
 45.2088 +                    if (sig != ZipFile.Signatures.Entry){
 45.2089 +                        thisZipFile.status.push("WARNING: this file does not appear to be a zip file");
 45.2090 +                    } else {
 45.2091 +                        thisZipFile.binaryStream.seek(0, JSIO.SeekOrigin.Begin);
 45.2092 +                        ReadZipEntries();
 45.2093 +                        if (thisZipFile.verbose > 0) {
 45.2094 +                            thisZipFile.status.push("INFO: read " + thisZipFile.entries.length + " entries");
 45.2095 +                        }
 45.2096 +                    }
 45.2097 +                }
 45.2098 +                else {
 45.2099 +                    thisZipFile.status.push("ERROR: the URL could not be read (" +
 45.2100 +                                     bfr.req.status + " " + bfr.req.statusText + ")");
 45.2101 +                }
 45.2102 +                callback(thisZipFile);
 45.2103 +            }
 45.2104 +            catch (exc1)
 45.2105 +            {
 45.2106 +                thisZipFile.status.push("Exception: " + exc1.message);
 45.2107 +                callback(thisZipFile);
 45.2108 +            }
 45.2109 +        };
 45.2110 +
 45.2111 +        this.binaryStream = new JSIO.BinaryUrlStream(fileUrl, parseZipFile);
 45.2112 +
 45.2113 +        return this;
 45.2114 +    };
 45.2115 +
 45.2116 +
 45.2117 +    ZipFile.Signatures = {
 45.2118 +        Entry                 : 0x04034b50,
 45.2119 +        EndOfCentralDirectory : 0x06054b50,
 45.2120 +        DirEntry              : 0x02014b50
 45.2121 +    };
 45.2122 +
 45.2123 +    ZipFile.Version = version;
 45.2124 +
 45.2125 +    ZipFile.EncryptionAlgorithm = {
 45.2126 +        None      : 0,
 45.2127 +        PkzipWeak : 1,
 45.2128 +        WinZipAes : 2
 45.2129 +    };
 45.2130 +
 45.2131 +    ZipFile.ExtraFieldTypes = {};
 45.2132 +    ZipFile.ExtraFieldTypes[0x0001] = 'Zip64 Extended Info';
 45.2133 +    ZipFile.ExtraFieldTypes[0x0007] = 'AV Info';
 45.2134 +    ZipFile.ExtraFieldTypes[0x0008] = 'Extended Language Encoding Data (PFS)';
 45.2135 +    ZipFile.ExtraFieldTypes[0x0009] = 'OS/2';
 45.2136 +    ZipFile.ExtraFieldTypes[0x000a] = 'NTFS ';
 45.2137 +    ZipFile.ExtraFieldTypes[0x000c] = 'OpenVMS';
 45.2138 +    ZipFile.ExtraFieldTypes[0x000d] = 'UNIX';
 45.2139 +    ZipFile.ExtraFieldTypes[0x000e] = 'File Stream and Fork Descriptors';
 45.2140 +    ZipFile.ExtraFieldTypes[0x000f] = 'Patch Descriptor';
 45.2141 +    ZipFile.ExtraFieldTypes[0x0014] = 'PKCS#7 Store for X.509 Certificates';
 45.2142 +    ZipFile.ExtraFieldTypes[0x0015] = 'X.509 Certificate ID and Signature (Individual File)';
 45.2143 +    ZipFile.ExtraFieldTypes[0x0016] = 'X.509 Certificate ID (Central Directory)';
 45.2144 +    ZipFile.ExtraFieldTypes[0x0017] = 'Strong Encryption Header';
 45.2145 +    ZipFile.ExtraFieldTypes[0x0018] = 'Record Management Controls';
 45.2146 +    ZipFile.ExtraFieldTypes[0x0019] = 'PKCS#7 Encryption Recipient Certificate List';
 45.2147 +    ZipFile.ExtraFieldTypes[0x0065] = 'IBM S/390 (Z390), AS/400 (I400) attributes (uncompressed)';
 45.2148 +    ZipFile.ExtraFieldTypes[0x0066] = 'IBM S/390 (Z390), AS/400 (I400) attributes (compressed)';
 45.2149 +    ZipFile.ExtraFieldTypes[0x4690] = 'POSZIP 4690 (reserved) ';
 45.2150 +    ZipFile.ExtraFieldTypes[0x07c8] = 'Macintosh';
 45.2151 +    ZipFile.ExtraFieldTypes[0x2605] = 'ZipIt Macintosh';
 45.2152 +    ZipFile.ExtraFieldTypes[0x2705] = 'ZipIt Macintosh 1.3.5+';
 45.2153 +    ZipFile.ExtraFieldTypes[0x2805] = 'ZipIt Macintosh 1.3.5+';
 45.2154 +    ZipFile.ExtraFieldTypes[0x334d] = 'Info-ZIP Macintosh';
 45.2155 +    ZipFile.ExtraFieldTypes[0x4341] = 'Acorn/SparkFS ';
 45.2156 +    ZipFile.ExtraFieldTypes[0x4453] = 'Windows NT security descriptor (binary ACL)';
 45.2157 +    ZipFile.ExtraFieldTypes[0x4704] = 'VM/CMS';
 45.2158 +    ZipFile.ExtraFieldTypes[0x470f] = 'MVS';
 45.2159 +    ZipFile.ExtraFieldTypes[0x4b46] = 'FWKCS MD5';
 45.2160 +    ZipFile.ExtraFieldTypes[0x4c41] = 'OS/2 access control list (text ACL)';
 45.2161 +    ZipFile.ExtraFieldTypes[0x4d49] = 'Info-ZIP OpenVMS';
 45.2162 +    ZipFile.ExtraFieldTypes[0x4f4c] = 'Xceed original location extra field';
 45.2163 +    ZipFile.ExtraFieldTypes[0x5356] = 'AOS/VS (ACL)';
 45.2164 +    ZipFile.ExtraFieldTypes[0x5455] = 'extended timestamp';
 45.2165 +    ZipFile.ExtraFieldTypes[0x554e] = 'Xceed unicode extra field';
 45.2166 +    ZipFile.ExtraFieldTypes[0x5855] = 'Info-ZIP UNIX (original, also OS/2, NT, etc)';
 45.2167 +    ZipFile.ExtraFieldTypes[0x6375] = 'Info-ZIP Unicode Comment Extra Field';
 45.2168 +    ZipFile.ExtraFieldTypes[0x6542] = 'BeOS/BeBox';
 45.2169 +    ZipFile.ExtraFieldTypes[0x7075] = 'Info-ZIP Unicode Path Extra Field';
 45.2170 +    ZipFile.ExtraFieldTypes[0x756e] = 'ASi UNIX';
 45.2171 +    ZipFile.ExtraFieldTypes[0x7855] = 'Info-ZIP UNIX (new)';
 45.2172 +    ZipFile.ExtraFieldTypes[0xa220] = 'Microsoft Open Packaging Growth Hint';
 45.2173 +    ZipFile.ExtraFieldTypes[0xfd4a] = 'SMS/QDOS';
 45.2174 +
 45.2175 +})();
    46.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    46.2 +++ b/endpoint/WebContent/js/geoxml3-kmz.js	Fri May 02 17:39:27 2014 +0200
    46.3 @@ -0,0 +1,1899 @@
    46.4 +/**
    46.5 + * @fileOverview Renders KML on the Google Maps JavaScript API Version 3
    46.6 + * @name GeoXML3
    46.7 + * @author Sterling Udell, Larry Ross, Brendan Byrd
    46.8 + * @see http://code.google.com/p/geoxml3/
    46.9 + *
   46.10 + * geoxml3.js
   46.11 + *
   46.12 + * Renders KML on the Google Maps JavaScript API Version 3
   46.13 + * http://code.google.com/p/geoxml3/
   46.14 + *
   46.15 + * Copyright 2010 Sterling Udell, Larry Ross
   46.16 + *
   46.17 + * Licensed under the Apache License, Version 2.0 (the "License");
   46.18 + * you may not use this file except in compliance with the License.
   46.19 + * You may obtain a copy of the License at
   46.20 + *
   46.21 + *    http://www.apache.org/licenses/LICENSE-2.0
   46.22 + *
   46.23 + * Unless required by applicable law or agreed to in writing, software
   46.24 + * distributed under the License is distributed on an "AS IS" BASIS,
   46.25 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   46.26 + * See the License for the specific language governing permissions and
   46.27 + * limitations under the License.
   46.28 + *
   46.29 + */
   46.30 +
   46.31 +if (!String.prototype.trim) {
   46.32 +/**
   46.33 + * Remove leading and trailing whitespace.
   46.34 + *
   46.35 + * @augments String
   46.36 + * @return {String}
   46.37 + */
   46.38 +  String.prototype.trim = function () {
   46.39 +    return this.replace(/^\s+|\s+$/g, '');
   46.40 +  };
   46.41 +}
   46.42 +
   46.43 +/**
   46.44 + * @namespace The GeoXML3 namespace.
   46.45 + */
   46.46 +geoXML3 = window.geoXML3 || {instances: []};
   46.47 +
   46.48 +/**
   46.49 + * Constructor for the root KML parser object.
   46.50 + *
   46.51 + * <p>All top-level objects and functions are declared under a namespace of geoXML3.
   46.52 + * The core object is geoXML3.parser; typically, you'll instantiate a one parser
   46.53 + * per map.</p>
   46.54 + *
   46.55 + * @class Main XML parser.
   46.56 + * @param {geoXML3.parserOptions} options
   46.57 + */
   46.58 +geoXML3.parser = function (options) {
   46.59 +  // Private variables
   46.60 +  var parserOptions = new geoXML3.parserOptions(options);
   46.61 +  var docs        = [];  // Individual KML documents
   46.62 +  var docsByUrl   = {};  // Same docs as an hash by cleanURL
   46.63 +  var kmzMetaData = {};  // Extra files from KMZ data
   46.64 +  var styles      = {};  // Global list of styles
   46.65 +  var lastPlacemark;
   46.66 +  var parserName;
   46.67 +  if (!parserOptions.infoWindow && parserOptions.singleInfoWindow)
   46.68 +    parserOptions.infoWindow = new google.maps.InfoWindow();
   46.69 +
   46.70 +  var parseKmlString = function (kmlString, docSet) {
   46.71 +    // Internal values for the set of documents as a whole
   46.72 +    var internals = {
   46.73 +      parser: this,
   46.74 +      docSet: docSet || [],
   46.75 +      remaining: 1,
   46.76 +      parseOnly: !(parserOptions.afterParse || parserOptions.processStyles)
   46.77 +    };
   46.78 +    thisDoc = new Object();
   46.79 +    thisDoc.internals = internals;
   46.80 +    internals.docSet.push(thisDoc);
   46.81 +    render(geoXML3.xmlParse(kmlString),thisDoc);
   46.82 +  }
   46.83 +
   46.84 +  var parse = function (urls, docSet) {
   46.85 +    // Process one or more KML documents
   46.86 +    if (!parserName) {
   46.87 +      parserName = 'geoXML3.instances[' + (geoXML3.instances.push(this) - 1) + ']';
   46.88 +    }
   46.89 +
   46.90 +    if (typeof urls === 'string') {
   46.91 +      // Single KML document
   46.92 +      urls = [urls];
   46.93 +    }
   46.94 +
   46.95 +    // Internal values for the set of documents as a whole
   46.96 +    var internals = {
   46.97 +      parser: this,
   46.98 +      docSet: docSet || [],
   46.99 +      remaining: urls.length,
  46.100 +      parseOnly: !(parserOptions.afterParse || parserOptions.processStyles)
  46.101 +    };
  46.102 +    var thisDoc, j;
  46.103 +    for (var i = 0; i < urls.length; i++) {
  46.104 +      var baseUrl = cleanURL(defileURL(location.pathname), urls[i]);
  46.105 +      if (docsByUrl[baseUrl]) {
  46.106 +        // Reloading an existing document
  46.107 +        thisDoc = docsByUrl[baseUrl];
  46.108 +        thisDoc.reload = true;
  46.109 +      }
  46.110 +      else {
  46.111 +        thisDoc = new Object();
  46.112 +        thisDoc.baseUrl = baseUrl;
  46.113 +        internals.docSet.push(thisDoc);
  46.114 +      }
  46.115 +      thisDoc.url       = urls[i];
  46.116 +      thisDoc.internals = internals;
  46.117 +      fetchDoc(thisDoc.url, thisDoc);
  46.118 +    }
  46.119 +  };
  46.120 +
  46.121 +  function fetchDoc(url, doc, resFunc) {
  46.122 +    resFunc = resFunc || function (responseXML) { render(responseXML, doc); };
  46.123 +
  46.124 +    if (typeof ZipFile === 'function' && typeof JSIO === 'object' && typeof JSIO.guessFileType === 'function') {  // KMZ support requires these modules loaded
  46.125 +      contentType = JSIO.guessFileType(doc.baseUrl);
  46.126 +      if (contentType == JSIO.FileType.Binary || contentType == JSIO.FileType.Unknown) {
  46.127 +         doc.isCompressed = true;
  46.128 +         doc.baseDir = doc.baseUrl + '/';
  46.129 +         geoXML3.fetchZIP(url, resFunc, doc.internals.parser);
  46.130 +         return;
  46.131 +      }
  46.132 +    }
  46.133 +    doc.isCompressed = false;
  46.134 +    doc.baseDir = defileURL(doc.baseUrl);
  46.135 +    geoXML3.fetchXML(url, resFunc);
  46.136 +  }
  46.137 +
  46.138 +  var hideDocument = function (doc) {
  46.139 +    if (!doc) doc = docs[0];
  46.140 +    // Hide the map objects associated with a document
  46.141 +    var i;
  46.142 +    if (!!doc.markers) {
  46.143 +      for (i = 0; i < doc.markers.length; i++) {
  46.144 +        if(!!doc.markers[i].infoWindow) doc.markers[i].infoWindow.close();
  46.145 +        doc.markers[i].setVisible(false);
  46.146 +      }
  46.147 +    }
  46.148 +    if (!!doc.ggroundoverlays) {
  46.149 +      for (i = 0; i < doc.ggroundoverlays.length; i++) {
  46.150 +        doc.ggroundoverlays[i].setOpacity(0);
  46.151 +      }
  46.152 +    }
  46.153 +    if (!!doc.gpolylines) {
  46.154 +      for (i=0;i<doc.gpolylines.length;i++) {
  46.155 +        if(!!doc.gpolylines[i].infoWindow) doc.gpolylines[i].infoWindow.close();
  46.156 +        doc.gpolylines[i].setMap(null);
  46.157 +      }
  46.158 +    }
  46.159 +    if (!!doc.gpolygons) {
  46.160 +      for (i=0;i<doc.gpolygons.length;i++) {
  46.161 +        if(!!doc.gpolygons[i].infoWindow) doc.gpolygons[i].infoWindow.close();
  46.162 +        doc.gpolygons[i].setMap(null);
  46.163 +      }
  46.164 +    }
  46.165 +  };
  46.166 +
  46.167 +  var showDocument = function (doc) {
  46.168 +    if (!doc) doc = docs[0];
  46.169 +    // Show the map objects associated with a document
  46.170 +    var i;
  46.171 +    if (!!doc.markers) {
  46.172 +      for (i = 0; i < doc.markers.length; i++) {
  46.173 +        doc.markers[i].setVisible(true);
  46.174 +      }
  46.175 +    }
  46.176 +    if (!!doc.ggroundoverlays) {
  46.177 +      for (i = 0; i < doc.ggroundoverlays.length; i++) {
  46.178 +        doc.ggroundoverlays[i].setOpacity(doc.ggroundoverlays[i].percentOpacity_);
  46.179 +      }
  46.180 +    }
  46.181 +    if (!!doc.gpolylines) {
  46.182 +      for (i=0;i<doc.gpolylines.length;i++) {
  46.183 +        doc.gpolylines[i].setMap(parserOptions.map);
  46.184 +      }
  46.185 +    }
  46.186 +    if (!!doc.gpolygons) {
  46.187 +      for (i=0;i<doc.gpolygons.length;i++) {
  46.188 +        doc.gpolygons[i].setMap(parserOptions.map);
  46.189 +      }
  46.190 +    }
  46.191 +  };
  46.192 +
  46.193 +  var defaultStyle = {
  46.194 +    balloon: {
  46.195 +      bgColor:   'ffffffff',
  46.196 +      textColor: 'ff000000',
  46.197 +      text: "<h3>$[name]</h3>\n<div>$[description]</div>\n<div>$[geDirections]</div>",
  46.198 +      displayMode: 'default'
  46.199 +    },
  46.200 +    icon: {
  46.201 +      scale: 1.0,
  46.202 +      dim: {
  46.203 +        x: 0,
  46.204 +        y: 0,
  46.205 +        w: -1,
  46.206 +        h: -1
  46.207 +      },
  46.208 +      hotSpot: {
  46.209 +        x: 0.5,
  46.210 +        y: 0.5,
  46.211 +        xunits: 'fraction',
  46.212 +        yunits: 'fraction'
  46.213 +      }
  46.214 +    },
  46.215 +    line: {
  46.216 +      color: '770000ff', // red (KML default)
  46.217 +      colorMode: 'normal',
  46.218 +      width: 1.0
  46.219 +    },
  46.220 +    poly: {
  46.221 +      color: '770000ff', // red (KML default)
  46.222 +      colorMode: 'normal',
  46.223 +      fill: true,
  46.224 +      outline: true
  46.225 +    }
  46.226 +  };
  46.227 +
  46.228 +  var kmlNS = 'http://www.opengis.net/kml/2.2';
  46.229 +  var gxNS  = 'http://www.google.com/kml/ext/2.2';
  46.230 +  var nodeValue              = geoXML3.nodeValue;
  46.231 +  var getBooleanValue        = geoXML3.getBooleanValue;
  46.232 +  var getElementsByTagNameNS = geoXML3.getElementsByTagNameNS;
  46.233 +  var getElementsByTagName   = geoXML3.getElementsByTagName;
  46.234 +
  46.235 +function processStyleUrl(node) {
  46.236 +  var styleUrlStr = nodeValue(getElementsByTagName(node, 'styleUrl')[0]);
  46.237 +  if (!!styleUrlStr && styleUrlStr.indexOf('#') != -1) 
  46.238 +    var styleUrl = styleUrlStr.split('#');
  46.239 +  else var styleUrl = ["",""];
  46.240 +  return styleUrl;
  46.241 +}
  46.242 +
  46.243 +  function processStyle(thisNode, baseUrl, styleID, baseDir) {
  46.244 +    var style = (baseUrl === '{inline}') ? clone(defaultStyle) : (styles[baseUrl][styleID] = styles[baseUrl][styleID] || clone(defaultStyle));
  46.245 +
  46.246 +    var styleNodes = getElementsByTagName(thisNode, 'BalloonStyle');
  46.247 +    if (!!styleNodes && styleNodes.length > 0) {
  46.248 +      style.balloon.bgColor     = nodeValue(getElementsByTagName(styleNodes[0], 'bgColor')[0],     style.balloon.bgColor);
  46.249 +      style.balloon.textColor   = nodeValue(getElementsByTagName(styleNodes[0], 'textColor')[0],   style.balloon.textColor);
  46.250 +      style.balloon.text        = nodeValue(getElementsByTagName(styleNodes[0], 'text')[0],        style.balloon.text);
  46.251 +      style.balloon.displayMode = nodeValue(getElementsByTagName(styleNodes[0], 'displayMode')[0], style.balloon.displayMode);
  46.252 +    }
  46.253 +
  46.254 +    // style.list = (unsupported; doesn't make sense in Google Maps)
  46.255 +
  46.256 +    var styleNodes = getElementsByTagName(thisNode, 'IconStyle');
  46.257 +    if (!!styleNodes && styleNodes.length > 0) {
  46.258 +      var icon = style.icon;
  46.259 +
  46.260 +      icon.scale = parseFloat(nodeValue(getElementsByTagName(styleNodes[0], 'scale')[0], icon.scale));
  46.261 +      // style.icon.heading   = (unsupported; not supported in API)
  46.262 +      // style.icon.color     = (unsupported; not supported in API)
  46.263 +      // style.icon.colorMode = (unsupported; not supported in API)
  46.264 +
  46.265 +      styleNodes = getElementsByTagName(thisNode, 'Icon');
  46.266 +      if (!!styleNodes && styleNodes.length > 0) {
  46.267 +        icon.href = nodeValue(getElementsByTagName(styleNodes[0], 'href')[0]);
  46.268 +        icon.url  = cleanURL(baseDir, icon.href);
  46.269 +        // Detect images buried in KMZ files (and use a base64 encoded URL)
  46.270 +        if (kmzMetaData[icon.url]) icon.url = kmzMetaData[icon.url].dataUrl;
  46.271 +
  46.272 +        // Support for icon palettes and exact size dimensions
  46.273 +        icon.dim = {
  46.274 +          x: parseInt(nodeValue(getElementsByTagNameNS(styleNodes[0], gxNS, 'x')[0], icon.dim.x)),
  46.275 +          y: parseInt(nodeValue(getElementsByTagNameNS(styleNodes[0], gxNS, 'y')[0], icon.dim.y)),
  46.276 +          w: parseInt(nodeValue(getElementsByTagNameNS(styleNodes[0], gxNS, 'w')[0], icon.dim.w)),
  46.277 +          h: parseInt(nodeValue(getElementsByTagNameNS(styleNodes[0], gxNS, 'h')[0], icon.dim.h))
  46.278 +        };
  46.279 +
  46.280 +        styleNodes = getElementsByTagName(styleNodes[0], 'hotSpot')[0];
  46.281 +        if (!!styleNodes && styleNodes.length > 0) {
  46.282 +          icon.hotSpot = {
  46.283 +            x:      styleNodes[0].getAttribute('x'),
  46.284 +            y:      styleNodes[0].getAttribute('y'),
  46.285 +            xunits: styleNodes[0].getAttribute('xunits'),
  46.286 +            yunits: styleNodes[0].getAttribute('yunits')
  46.287 +          };
  46.288 +        }
  46.289 +
  46.290 +        // certain occasions where we need the pixel size of the image (like the default settings...)
  46.291 +        // (NOTE: Scale is applied to entire image, not just the section of the icon palette.  So,
  46.292 +        //  if we need scaling, we'll need the img dimensions no matter what.)
  46.293 +        if ( (icon.dim.w < 0 || icon.dim.h < 0) && (icon.xunits != 'pixels' || icon.yunits == 'fraction') || icon.scale != 1.0) {
  46.294 +          // (hopefully, this will load by the time we need it...)
  46.295 +          icon.img = new Image();
  46.296 +          icon.img.onload = function() {
  46.297 +            if (icon.dim.w < 0 || icon.dim.h < 0) {
  46.298 +              icon.dim.w = this.width;
  46.299 +              icon.dim.h = this.height;
  46.300 +            }
  46.301 +          };
  46.302 +          icon.img.src = icon.url;
  46.303 +
  46.304 +          // sometimes the file is already cached and it never calls onLoad
  46.305 +          if (icon.img.width > 0) {
  46.306 +            icon.dim.w = icon.img.width;
  46.307 +            icon.dim.h = icon.img.height;
  46.308 +          }
  46.309 +        }
  46.310 +      }
  46.311 +    }
  46.312 +
  46.313 +    // style.label = (unsupported; may be possible but not with API)
  46.314 +
  46.315 +    styleNodes = getElementsByTagName(thisNode, 'LineStyle');
  46.316 +    if (!!styleNodes && styleNodes.length > 0) {
  46.317 +      style.line.color     = nodeValue(getElementsByTagName(styleNodes[0], 'color')[0],     style.line.color);
  46.318 +      style.line.colorMode = nodeValue(getElementsByTagName(styleNodes[0], 'colorMode')[0], style.line.colorMode);
  46.319 +      style.line.width     = nodeValue(getElementsByTagName(styleNodes[0], 'width')[0],     style.line.width);
  46.320 +      // style.line.outerColor      = (unsupported; not supported in API)
  46.321 +      // style.line.outerWidth      = (unsupported; not supported in API)
  46.322 +      // style.line.physicalWidth   = (unsupported; unneccesary in Google Maps)
  46.323 +      // style.line.labelVisibility = (unsupported; possible to implement)
  46.324 +    }
  46.325 +
  46.326 +    styleNodes = getElementsByTagName(thisNode, 'PolyStyle');
  46.327 +    if (!!styleNodes && styleNodes.length > 0) {
  46.328 +      style.poly.color     = nodeValue(      getElementsByTagName(styleNodes[0], 'color')[0],     style.poly.color);
  46.329 +      style.poly.colorMode = nodeValue(      getElementsByTagName(styleNodes[0], 'colorMode')[0], style.poly.colorMode);
  46.330 +      style.poly.outline   = getBooleanValue(getElementsByTagName(styleNodes[0], 'outline')[0],   style.poly.outline);
  46.331 +      style.poly.fill      = getBooleanValue(getElementsByTagName(styleNodes[0], 'fill')[0],      style.poly.fill);
  46.332 +    }
  46.333 +    return style;
  46.334 +  }
  46.335 +
  46.336 +  // from http://stackoverflow.com/questions/122102/what-is-the-most-efficient-way-to-clone-a-javascript-object
  46.337 +  // http://keithdevens.com/weblog/archive/2007/Jun/07/javascript.clone
  46.338 +  function clone(obj){
  46.339 +    if(obj == null || typeof(obj) != 'object') return obj;
  46.340 +    if (obj.cloneNode) return obj.cloneNode(true);
  46.341 +    var temp = new obj.constructor();
  46.342 +    for(var key in obj) temp[key] = clone(obj[key]);
  46.343 +    return temp;
  46.344 +  }
  46.345 +
  46.346 +  function processStyleMap(thisNode, baseUrl, styleID, baseDir) {
  46.347 +    var pairs = getElementsByTagName(thisNode, 'Pair');
  46.348 +    var map = new Object();
  46.349 +
  46.350 +    // add each key to the map
  46.351 +    for (var pr=0;pr<pairs.length;pr++) {
  46.352 +      var pairKey      = nodeValue(getElementsByTagName(pairs[pr], 'key')[0]);
  46.353 +      var pairStyle    = nodeValue(getElementsByTagName(pairs[pr], 'Style')[0]);
  46.354 +      var pairStyleUrl = processStyleUrl(pairs[pr]);
  46.355 +      var pairStyleBaseUrl = pairStyleUrl[0] ? cleanURL(baseDir, pairStyleUrl[0]) : baseUrl;
  46.356 +      var pairStyleID      = pairStyleUrl[1];
  46.357 +
  46.358 +      if (!!pairStyle) {
  46.359 +        map[pairKey] = processStyle(pairStyle, pairStyleBaseUrl, pairStyleID);
  46.360 +      } else if (!!pairStyleID && !!styles[pairStyleBaseUrl][pairStyleID]) {
  46.361 +        map[pairKey] = clone(styles[pairStyleBaseUrl][pairStyleID]);
  46.362 +      }
  46.363 +    }
  46.364 +    if (!!map["normal"]) {
  46.365 +      styles[baseUrl][styleID] = clone(map["normal"]);
  46.366 +    } else {
  46.367 +      styles[baseUrl][styleID] = clone(defaultStyle);
  46.368 +    }
  46.369 +    if (!!map["highlight"]) {
  46.370 +      processStyleID(map["highlight"]);
  46.371 +    }
  46.372 +    styles[baseUrl][styleID].map = clone(map);
  46.373 +  }
  46.374 +
  46.375 +  function processPlacemarkCoords(node, tag) {
  46.376 +    var parent = getElementsByTagName(node, tag);
  46.377 +    var coordListA = [];
  46.378 +    for (var i=0; i<parent.length; i++) {
  46.379 +      var coordNodes = getElementsByTagName(parent[i], 'coordinates');
  46.380 +      if (!coordNodes) {
  46.381 +        if (coordListA.length > 0) {
  46.382 +          break;
  46.383 +        } else {
  46.384 +          return [{coordinates: []}];
  46.385 +        }
  46.386 +      }
  46.387 +
  46.388 +      for (var j=0; j<coordNodes.length;j++) {
  46.389 +        var coords = nodeValue(coordNodes[j]).trim();
  46.390 +        coords = coords.replace(/,\s+/g, ',');
  46.391 +        var path = coords.split(/\s+/g);
  46.392 +        var pathLength = path.length;
  46.393 +        var coordList = [];
  46.394 +        for (var k = 0; k < pathLength; k++) {
  46.395 +          coords = path[k].split(',');
  46.396 +          if (!isNaN(coords[0]) && !isNaN(coords[1])) {
  46.397 +            coordList.push({
  46.398 +              lat: parseFloat(coords[1]),
  46.399 +              lng: parseFloat(coords[0]),
  46.400 +              alt: parseFloat(coords[2])
  46.401 +            });
  46.402 +          }
  46.403 +        }
  46.404 +        coordListA.push({coordinates: coordList});
  46.405 +      }
  46.406 +    }
  46.407 +    return coordListA;
  46.408 +  }
  46.409 +
  46.410 +  var render = function (responseXML, doc) {
  46.411 +    // Callback for retrieving a KML document: parse the KML and display it on the map
  46.412 +    if (!responseXML) {
  46.413 +      // Error retrieving the data
  46.414 +      geoXML3.log('Unable to retrieve ' + doc.url);
  46.415 +      if (parserOptions.failedParse) parserOptions.failedParse(doc);
  46.416 +      doc.failed = true;
  46.417 +      return;
  46.418 +    } else if (responseXML.parseError && responseXML.parseError.errorCode != 0) {
  46.419 +      // IE parse error
  46.420 +      var err = responseXML.parseError;
  46.421 +      var msg = 'Parse error in line ' + err.line + ', col ' + err.linePos + ' (error code: ' + err.errorCode + ")\n" +
  46.422 +        "\nError Reason: " + err.reason +
  46.423 +        'Error Line: ' + err.srcText;
  46.424 +
  46.425 +      geoXML3.log('Unable to retrieve ' + doc.url + ': ' + msg);
  46.426 +      if (parserOptions.failedParse) parserOptions.failedParse(doc);
  46.427 +      doc.failed = true;
  46.428 +      return;
  46.429 +    } else if (responseXML.documentElement && responseXML.documentElement.nodeName == 'parsererror') {
  46.430 +      // Firefox parse error
  46.431 +      geoXML3.log('Unable to retrieve ' + doc.url + ': ' + responseXML.documentElement.childNodes[0].nodeValue);
  46.432 +      if (parserOptions.failedParse) parserOptions.failedParse(doc);
  46.433 +      doc.failed = true;
  46.434 +      return;
  46.435 +    } else if (!doc) {
  46.436 +      throw 'geoXML3 internal error: render called with null document';
  46.437 +    } else { //no errors
  46.438 +      var i;
  46.439 +      doc.placemarks      = [];
  46.440 +      doc.groundoverlays  = [];
  46.441 +      doc.ggroundoverlays = [];
  46.442 +      doc.networkLinks    = [];
  46.443 +      doc.gpolygons       = [];
  46.444 +      doc.gpolylines      = [];
  46.445 +
  46.446 +      // Check for dependent KML files
  46.447 +      var nodes = getElementsByTagName(responseXML, 'styleUrl');
  46.448 +      var docSet = doc.internals.docSet;
  46.449 +
  46.450 +      for (var i = 0; i < nodes.length; i++) {
  46.451 +        var url = nodeValue(nodes[i]).split('#')[0];
  46.452 +        if (!url)                 continue;  // #id (inside doc)
  46.453 +        var rUrl = cleanURL( doc.baseDir, url );
  46.454 +        if (rUrl === doc.baseUrl) continue;  // self
  46.455 +        if (docsByUrl[rUrl])      continue;  // already loaded
  46.456 +
  46.457 +        var thisDoc;
  46.458 +        var j = docSet.indexOfObjWithItem('baseUrl', rUrl);
  46.459 +        if (j != -1) {
  46.460 +          // Already listed to be loaded, but probably in the wrong order.
  46.461 +          // Load it right away to immediately resolve dependency.
  46.462 +          thisDoc = docSet[j];
  46.463 +          if (thisDoc.failed) continue;  // failed to load last time; don't retry it again
  46.464 +        }
  46.465 +        else {
  46.466 +          // Not listed at all; add it in
  46.467 +          thisDoc           = new Object();
  46.468 +          thisDoc.url       = rUrl;  // url can't be trusted inside KMZ files, since it may .. outside of the archive
  46.469 +          thisDoc.baseUrl   = rUrl;
  46.470 +          thisDoc.internals = doc.internals;
  46.471 +
  46.472 +          doc.internals.docSet.push(thisDoc);
  46.473 +          doc.internals.remaining++;
  46.474 +        }
  46.475 +
  46.476 +        // render dependent KML first then re-run renderer
  46.477 +        fetchDoc(rUrl, thisDoc, function (thisResXML) {
  46.478 +          render(thisResXML, thisDoc);
  46.479 +          render(responseXML, doc);
  46.480 +        });
  46.481 +
  46.482 +        // to prevent cross-dependency issues, just load the one
  46.483 +        // file first and re-check the rest later
  46.484 +        return;
  46.485 +      }
  46.486 +
  46.487 +      // Parse styles
  46.488 +      doc.styles = styles[doc.baseUrl] = styles[doc.baseUrl] || {};
  46.489 +      var styleID, styleNodes;
  46.490 +      nodes = getElementsByTagName(responseXML, 'Style');
  46.491 +      nodeCount = nodes.length;
  46.492 +      for (i = 0; i < nodeCount; i++) {
  46.493 +        thisNode = nodes[i];
  46.494 +        var styleID = thisNode.getAttribute('id');
  46.495 +        if (!!styleID) processStyle(thisNode, doc.baseUrl, styleID, doc.baseDir);
  46.496 +      }
  46.497 +      // Parse StyleMap nodes
  46.498 +      nodes = getElementsByTagName(responseXML, 'StyleMap');
  46.499 +      for (i = 0; i < nodes.length; i++) {
  46.500 +        thisNode = nodes[i];
  46.501 +        var styleID = thisNode.getAttribute('id');
  46.502 +        if (!!styleID) processStyleMap(thisNode, doc.baseUrl, styleID, doc.baseDir);
  46.503 +      }
  46.504 +
  46.505 +      if (!!parserOptions.processStyles || !parserOptions.createMarker) {
  46.506 +        // Convert parsed styles into GMaps equivalents
  46.507 +        processStyles(doc);
  46.508 +      }
  46.509 +
  46.510 +      // Parse placemarks
  46.511 +      if (!!doc.reload && !!doc.markers) {
  46.512 +        for (i = 0; i < doc.markers.length; i++) {
  46.513 +          doc.markers[i].active = false;
  46.514 +        }
  46.515 +      }
  46.516 +      var placemark, node, coords, path, marker, poly;
  46.517 +      var placemark, coords, path, pathLength, marker, polygonNodes, coordList;
  46.518 +      var placemarkNodes = getElementsByTagName(responseXML, 'Placemark');
  46.519 +      for (pm = 0; pm < placemarkNodes.length; pm++) {
  46.520 +        // Init the placemark object
  46.521 +        node = placemarkNodes[pm];
  46.522 +        var styleUrl = processStyleUrl(node);
  46.523 +        placemark = {
  46.524 +          name:         nodeValue(getElementsByTagName(node, 'name')[0]),
  46.525 +          description:  nodeValue(getElementsByTagName(node, 'description')[0]),
  46.526 +          styleUrl:     styleUrl.join('#'),
  46.527 +          styleBaseUrl: styleUrl[0] ? cleanURL(doc.baseDir, styleUrl[0]) : doc.baseUrl,
  46.528 +          styleID:      styleUrl[1],
  46.529 +          visibility:        getBooleanValue(getElementsByTagName(node, 'visibility')[0], true),
  46.530 +          balloonVisibility: getBooleanValue(getElementsByTagNameNS(node, gxNS, 'balloonVisibility')[0], !parserOptions.suppressInfoWindows)
  46.531 +        };
  46.532 +        placemark.style = (styles[placemark.styleBaseUrl] && styles[placemark.styleBaseUrl][placemark.styleID]) || clone(defaultStyle);
  46.533 +        // inline style overrides shared style
  46.534 +        var inlineStyles = getElementsByTagName(node, 'Style');
  46.535 +        if (inlineStyles && (inlineStyles.length > 0)) {
  46.536 +          var style = processStyle(node, '{inline}', '{inline}');
  46.537 +          processStyleID(style);
  46.538 +          if (style) placemark.style = style;
  46.539 +        }
  46.540 +
  46.541 +        if (/^https?:\/\//.test(placemark.description)) {
  46.542 +          placemark.description = ['<a href="', placemark.description, '">', placemark.description, '</a>'].join('');
  46.543 +        }
  46.544 +
  46.545 +        // record list of variables for substitution
  46.546 +        placemark.vars = {
  46.547 +          display: {
  46.548 +            name:         'Name',
  46.549 +            description:  'Description',
  46.550 +            address:      'Street Address',
  46.551 +            id:           'ID',
  46.552 +            Snippet:      'Snippet',
  46.553 +            geDirections: 'Directions'
  46.554 +          },
  46.555 +          val: {
  46.556 +            name:        placemark.name || '',
  46.557 +            description: placemark.description || '',
  46.558 +            address:     nodeValue(getElementsByTagName(node, 'address')[0], ''),
  46.559 +            id:          node.getAttribute('id') || '',
  46.560 +            Snippet:     nodeValue(getElementsByTagName(node, 'Snippet')[0], '')
  46.561 +          },
  46.562 +          directions: [
  46.563 +            'f=d',
  46.564 +            'source=GeoXML3'
  46.565 +          ]
  46.566 +        };
  46.567 +
  46.568 +        // add extended data to variables
  46.569 +        var extDataNodes = getElementsByTagName(node, 'ExtendedData');
  46.570 +        if (!!extDataNodes && extDataNodes.length > 0) {
  46.571 +          var dataNodes = getElementsByTagName(extDataNodes[0], 'Data');
  46.572 +          for (var d = 0; d < dataNodes.length; d++) {
  46.573 +            var dn    = dataNodes[d];
  46.574 +            var name  = dn.getAttribute('name');
  46.575 +            if (!name) continue;
  46.576 +            var dName = nodeValue(getElementsByTagName(dn, 'displayName')[0], name);
  46.577 +            var val   = nodeValue(getElementsByTagName(dn, 'value')[0]);
  46.578 +
  46.579 +            placemark.vars.val[name]     = val;
  46.580 +            placemark.vars.display[name] = dName;
  46.581 +          }
  46.582 +        }
  46.583 +
  46.584 +        // process MultiGeometry
  46.585 +        var GeometryNodes = getElementsByTagName(node, 'coordinates');
  46.586 +        var Geometry = null;
  46.587 +        if (!!GeometryNodes && (GeometryNodes.length > 0)) {
  46.588 +          for (var gn=0;gn<GeometryNodes.length;gn++) {
  46.589 +            if (GeometryNodes[gn].parentNode &&
  46.590 +                GeometryNodes[gn].parentNode.nodeName) {
  46.591 +              var GeometryPN = GeometryNodes[gn].parentNode;
  46.592 +              Geometry = GeometryPN.nodeName;
  46.593 +
  46.594 +              // Extract the coordinates
  46.595 +              // What sort of placemark?
  46.596 +              switch(Geometry) {
  46.597 +                case "Point":
  46.598 +                  placemark.Point = processPlacemarkCoords(node, "Point")[0];
  46.599 +                  placemark.latlng = new google.maps.LatLng(placemark.Point.coordinates[0].lat, placemark.Point.coordinates[0].lng);
  46.600 +                  pathLength = 1;
  46.601 +                  break;
  46.602 +                case "LinearRing":
  46.603 +                  // Polygon/line
  46.604 +                  polygonNodes = getElementsByTagName(node, 'Polygon');
  46.605 +                  // Polygon
  46.606 +                  if (!placemark.Polygon)
  46.607 +                    placemark.Polygon = [{
  46.608 +                      outerBoundaryIs: {coordinates: []},
  46.609 +                      innerBoundaryIs: [{coordinates: []}]
  46.610 +                    }];
  46.611 +                  for (var pg=0;pg<polygonNodes.length;pg++) {
  46.612 +                     placemark.Polygon[pg] = {
  46.613 +                       outerBoundaryIs: {coordinates: []},
  46.614 +                       innerBoundaryIs: [{coordinates: []}]
  46.615 +                     }
  46.616 +                     placemark.Polygon[pg].outerBoundaryIs = processPlacemarkCoords(polygonNodes[pg], "outerBoundaryIs");
  46.617 +                     placemark.Polygon[pg].innerBoundaryIs = processPlacemarkCoords(polygonNodes[pg], "innerBoundaryIs");
  46.618 +                  }
  46.619 +                  coordList = placemark.Polygon[0].outerBoundaryIs;
  46.620 +                  break;
  46.621 +
  46.622 +                case "LineString":
  46.623 +                  pathLength = 0;
  46.624 +                  placemark.LineString = processPlacemarkCoords(node,"LineString");
  46.625 +                  break;
  46.626 +
  46.627 +                default:
  46.628 +                  break;
  46.629 +              }
  46.630 +            }
  46.631 +          }
  46.632 +        }
  46.633 +
  46.634 +        // call the custom placemark parse function if it is defined
  46.635 +        if (!!parserOptions.pmParseFn) parserOptions.pmParseFn(node, placemark);
  46.636 +        doc.placemarks.push(placemark);
  46.637 +
  46.638 +        // single marker
  46.639 +        if (placemark.Point) {
  46.640 +          if (!!google.maps) {
  46.641 +            doc.bounds = doc.bounds || new google.maps.LatLngBounds();
  46.642 +            doc.bounds.extend(placemark.latlng);
  46.643 +          }
  46.644 +
  46.645 +          // Potential user-defined marker handler
  46.646 +          var pointCreateFunc = parserOptions.createMarker || createMarker;
  46.647 +          var found = false;
  46.648 +          if (!parserOptions.createMarker) {
  46.649 +            // Check to see if this marker was created on a previous load of this document
  46.650 +            if (!!doc) {
  46.651 +              doc.markers = doc.markers || [];
  46.652 +              if (doc.reload) {
  46.653 +                for (var j = 0; j < doc.markers.length; j++) {
  46.654 +                  if (doc.markers[j].getPosition().equals(placemark.latlng)) {
  46.655 +                    found = doc.markers[j].active = true;
  46.656 +                    break;
  46.657 +                  }
  46.658 +                }
  46.659 +              }
  46.660 +            }
  46.661 +          }
  46.662 +          if (!found) {
  46.663 +            // Call the marker creator
  46.664 +            var marker = pointCreateFunc(placemark, doc);
  46.665 +            if (marker) marker.active = placemark.visibility;
  46.666 +          }
  46.667 +        }
  46.668 +        // polygon/line
  46.669 +        var poly, line;
  46.670 +        if (!!doc) {
  46.671 +          if (placemark.Polygon)    doc.gpolygons  = doc.gpolygons  || [];
  46.672 +          if (placemark.LineString) doc.gpolylines = doc.gpolylines || [];
  46.673 +        }
  46.674 +
  46.675 +        var polyCreateFunc = parserOptions.createPolygon    || createPolygon;
  46.676 +        var lineCreateFunc = parserOptions.createLineString || createPolyline;
  46.677 +        if (placemark.Polygon) {
  46.678 +          poly = polyCreateFunc(placemark,doc);
  46.679 +          if (poly) poly.active = placemark.visibility;
  46.680 +        }
  46.681 +        if (placemark.LineString) {
  46.682 +          line = lineCreateFunc(placemark,doc);
  46.683 +          if (line) line.active = placemark.visibility;
  46.684 +        }
  46.685 +        if (!!google.maps) {
  46.686 +          doc.bounds = doc.bounds || new google.maps.LatLngBounds();
  46.687 +          if (poly) doc.bounds.union(poly.bounds);
  46.688 +          if (line) doc.bounds.union(line.bounds);
  46.689 +        }
  46.690 +
  46.691 +      } // placemark loop
  46.692 +
  46.693 +      if (!!doc.reload && !!doc.markers) {
  46.694 +        for (i = doc.markers.length - 1; i >= 0 ; i--) {
  46.695 +          if (!doc.markers[i].active) {
  46.696 +            if (!!doc.markers[i].infoWindow) {
  46.697 +              doc.markers[i].infoWindow.close();
  46.698 +            }
  46.699 +            doc.markers[i].setMap(null);
  46.700 +            doc.markers.splice(i, 1);
  46.701 +          }
  46.702 +        }
  46.703 +      }
  46.704 +
  46.705 +      // Parse ground overlays
  46.706 +      if (!!doc.reload && !!doc.groundoverlays) {
  46.707 +        for (i = 0; i < doc.groundoverlays.length; i++) {
  46.708 +          doc.groundoverlays[i].active = false;
  46.709 +        }
  46.710 +      }
  46.711 +
  46.712 +      if (!!doc) {
  46.713 +        doc.groundoverlays = doc.groundoverlays || [];
  46.714 +      }
  46.715 +      // doc.groundoverlays =[];
  46.716 +      var groundOverlay, color, transparency, overlay;
  46.717 +      var groundNodes = getElementsByTagName(responseXML, 'GroundOverlay');
  46.718 +      for (i = 0; i < groundNodes.length; i++) {
  46.719 +        node = groundNodes[i];
  46.720 +
  46.721 +        // Detect images buried in KMZ files (and use a base64 encoded URL)
  46.722 +        var gnUrl = cleanURL( doc.baseDir, nodeValue(getElementsByTagName(node, 'href')[0]) );
  46.723 +        if (kmzMetaData[gnUrl]) gnUrl = kmzMetaData[gnUrl].dataUrl;
  46.724 +
  46.725 +        // Init the ground overlay object
  46.726 +        groundOverlay = {
  46.727 +          name:        nodeValue(getElementsByTagName(node, 'name')[0]),
  46.728 +          description: nodeValue(getElementsByTagName(node, 'description')[0]),
  46.729 +          icon: { href: gnUrl },
  46.730 +          latLonBox: {
  46.731 +            north: parseFloat(nodeValue(getElementsByTagName(node, 'north')[0])),
  46.732 +            east:  parseFloat(nodeValue(getElementsByTagName(node, 'east')[0])),
  46.733 +            south: parseFloat(nodeValue(getElementsByTagName(node, 'south')[0])),
  46.734 +            west:  parseFloat(nodeValue(getElementsByTagName(node, 'west')[0]))
  46.735 +          }
  46.736 +        };
  46.737 +        if (!!google.maps) {
  46.738 +          doc.bounds = doc.bounds || new google.maps.LatLngBounds();
  46.739 +          doc.bounds.union(new google.maps.LatLngBounds(
  46.740 +            new google.maps.LatLng(groundOverlay.latLonBox.south, groundOverlay.latLonBox.west),
  46.741 +            new google.maps.LatLng(groundOverlay.latLonBox.north, groundOverlay.latLonBox.east)
  46.742 +          ));
  46.743 +        }
  46.744 +
  46.745 +        // Opacity is encoded in the color node
  46.746 +        var colorNode = getElementsByTagName(node, 'color');
  46.747 +        if (colorNode && colorNode.length > 0) {
  46.748 +          groundOverlay.opacity = geoXML3.getOpacity(nodeValue(colorNode[0]));
  46.749 +        } else {
  46.750 +          groundOverlay.opacity = 1.0;  // KML default
  46.751 +        }
  46.752 +
  46.753 +        doc.groundoverlays.push(groundOverlay);
  46.754 +        if (!!parserOptions.createOverlay) {
  46.755 +          // User-defined overlay handler
  46.756 +          parserOptions.createOverlay(groundOverlay, doc);
  46.757 +        } else {
  46.758 +          // Check to see if this overlay was created on a previous load of this document
  46.759 +          var found = false;
  46.760 +          if (!!doc) {
  46.761 +            doc.groundoverlays = doc.groundoverlays || [];
  46.762 +            if (doc.reload) {
  46.763 +              overlayBounds = new google.maps.LatLngBounds(
  46.764 +                new google.maps.LatLng(groundOverlay.latLonBox.south, groundOverlay.latLonBox.west),
  46.765 +                new google.maps.LatLng(groundOverlay.latLonBox.north, groundOverlay.latLonBox.east)
  46.766 +              );
  46.767 +              var overlays = doc.groundoverlays;
  46.768 +              for (i = overlays.length; i--;) {
  46.769 +                if ((overlays[i].bounds().equals(overlayBounds)) &&
  46.770 +                    (overlays.url_ === groundOverlay.icon.href)) {
  46.771 +                  found = overlays[i].active = true;
  46.772 +                  break;
  46.773 +                }
  46.774 +              }
  46.775 +            }
  46.776 +          }
  46.777 +
  46.778 +          if (!found) {
  46.779 +            // Call the built-in overlay creator
  46.780 +            overlay = createOverlay(groundOverlay, doc);
  46.781 +            overlay.active = true;
  46.782 +          }
  46.783 +        }
  46.784 +        if (!!doc.reload && !!doc.groundoverlays && !!doc.groundoverlays.length) {
  46.785 +          var overlays = doc.groundoverlays;
  46.786 +          for (i = overlays.length; i--;) {
  46.787 +            if (!overlays[i].active) {
  46.788 +              overlays[i].remove();
  46.789 +              overlays.splice(i, 1);
  46.790 +            }
  46.791 +          }
  46.792 +          doc.groundoverlays = overlays;
  46.793 +        }
  46.794 +      }
  46.795 +
  46.796 +      // Parse network links
  46.797 +      var networkLink;
  46.798 +      var docPath = document.location.pathname.split('/');
  46.799 +      docPath = docPath.splice(0, docPath.length - 1).join('/');
  46.800 +      var linkNodes = getElementsByTagName(responseXML, 'NetworkLink');
  46.801 +      for (i = 0; i < linkNodes.length; i++) {
  46.802 +        node = linkNodes[i];
  46.803 +
  46.804 +        // Init the network link object
  46.805 +        networkLink = {
  46.806 +          name: nodeValue(getElementsByTagName(node, 'name')[0]),
  46.807 +          link: {
  46.808 +            href:        nodeValue(getElementsByTagName(node, 'href')[0]),
  46.809 +            refreshMode: nodeValue(getElementsByTagName(node, 'refreshMode')[0])
  46.810 +          }
  46.811 +        };
  46.812 +
  46.813 +        // Establish the specific refresh mode
  46.814 +        if (!networkLink.link.refreshMode) {
  46.815 +          networkLink.link.refreshMode = 'onChange';
  46.816 +        }
  46.817 +        if (networkLink.link.refreshMode === 'onInterval') {
  46.818 +          networkLink.link.refreshInterval = parseFloat(nodeValue(getElementsByTagName(node, 'refreshInterval')[0]));
  46.819 +          if (isNaN(networkLink.link.refreshInterval)) {
  46.820 +            networkLink.link.refreshInterval = 0;
  46.821 +          }
  46.822 +        } else if (networkLink.link.refreshMode === 'onChange') {
  46.823 +          networkLink.link.viewRefreshMode = nodeValue(getElementsByTagName(node, 'viewRefreshMode')[0]);
  46.824 +          if (!networkLink.link.viewRefreshMode) {
  46.825 +            networkLink.link.viewRefreshMode = 'never';
  46.826 +          }
  46.827 +          if (networkLink.link.viewRefreshMode === 'onStop') {
  46.828 +            networkLink.link.viewRefreshTime = nodeValue(getElementsByTagName(node, 'refreshMode')[0]);
  46.829 +            networkLink.link.viewFormat =      nodeValue(getElementsByTagName(node, 'refreshMode')[0]);
  46.830 +            if (!networkLink.link.viewFormat) {
  46.831 +              networkLink.link.viewFormat = 'BBOX=[bboxWest],[bboxSouth],[bboxEast],[bboxNorth]';
  46.832 +            }
  46.833 +          }
  46.834 +        }
  46.835 +
  46.836 +        if (!/^[\/|http]/.test(networkLink.link.href)) {
  46.837 +          // Fully-qualify the HREF
  46.838 +          networkLink.link.href = docPath + '/' + networkLink.link.href;
  46.839 +        }
  46.840 +
  46.841 +        // Apply the link
  46.842 +        if ((networkLink.link.refreshMode === 'onInterval') &&
  46.843 +            (networkLink.link.refreshInterval > 0)) {
  46.844 +          // Reload at regular intervals
  46.845 +          setInterval(parserName + '.parse("' + networkLink.link.href + '")',
  46.846 +                      1000 * networkLink.link.refreshInterval);
  46.847 +        } else if (networkLink.link.refreshMode === 'onChange') {
  46.848 +          if (networkLink.link.viewRefreshMode === 'never') {
  46.849 +            // Load the link just once
  46.850 +            doc.internals.parser.parse(networkLink.link.href, doc.internals.docSet);
  46.851 +          } else if (networkLink.link.viewRefreshMode === 'onStop') {
  46.852 +            // Reload when the map view changes
  46.853 +
  46.854 +          }
  46.855 +        }
  46.856 +      }
  46.857 +    }
  46.858 +
  46.859 +    if (!!doc.bounds) {
  46.860 +      doc.internals.bounds = doc.internals.bounds || new google.maps.LatLngBounds();
  46.861 +      doc.internals.bounds.union(doc.bounds);
  46.862 +    }
  46.863 +    if (!!doc.markers || !!doc.groundoverlays || !!doc.gpolylines || !!doc.gpolygons) {
  46.864 +      doc.internals.parseOnly = false;
  46.865 +    }
  46.866 +
  46.867 +    if (!doc.internals.parseOnly) {
  46.868 +      // geoXML3 is not being used only as a real-time parser, so keep the processed documents around
  46.869 +      if (!docsByUrl[doc.baseUrl]) {
  46.870 +        docs.push(doc);
  46.871 +        docsByUrl[doc.baseUrl] = doc;
  46.872 +      }
  46.873 +      else {
  46.874 +        // internal replacement, which keeps the same memory ref loc in docs and docsByUrl
  46.875 +        for (var i in docsByUrl[doc.baseUrl]) {
  46.876 +          docsByUrl[doc.baseUrl][i] = doc[i];
  46.877 +        }
  46.878 +      }
  46.879 +    }
  46.880 +
  46.881 +    doc.internals.remaining--;
  46.882 +    if (doc.internals.remaining === 0) {
  46.883 +      // We're done processing this set of KML documents
  46.884 +      // Options that get invoked after parsing completes
  46.885 +      if (parserOptions.zoom && !!doc.internals.bounds &&
  46.886 +	  !doc.internals.bounds.isEmpty() && !!parserOptions.map) {
  46.887 +        parserOptions.map.fitBounds(doc.internals.bounds);
  46.888 +      }
  46.889 +      if (parserOptions.afterParse) {
  46.890 +        parserOptions.afterParse(doc.internals.docSet);
  46.891 +      }
  46.892 +    }
  46.893 +  };
  46.894 +
  46.895 +  var kmlColor = function (kmlIn, colorMode) {
  46.896 +    var kmlColor = {};
  46.897 +    kmlIn = kmlIn || 'ffffffff';  // white (KML 2.2 default)
  46.898 +
  46.899 +    var aa = kmlIn.substr(0,2);
  46.900 +    var bb = kmlIn.substr(2,2);
  46.901 +    var gg = kmlIn.substr(4,2);
  46.902 +    var rr = kmlIn.substr(6,2);
  46.903 +
  46.904 +    kmlColor.opacity = parseInt(aa, 16) / 256;
  46.905 +    kmlColor.color   = (colorMode === 'random') ? randomColor(rr, gg, bb) : '#' + rr + gg + bb;
  46.906 +    return kmlColor;
  46.907 +  };
  46.908 +
  46.909 +  // Implemented per KML 2.2 <ColorStyle> specs
  46.910 +  var randomColor = function(rr, gg, bb) {
  46.911 +    var col = { rr: rr, gg: gg, bb: bb };
  46.912 +    for (var k in col) {
  46.913 +      var v = col[k];
  46.914 +      if (v == null) v = 'ff';
  46.915 +
  46.916 +      // RGB values are limiters for random numbers (ie: 7f would be a random value between 0 and 7f)
  46.917 +      v = Math.round(Math.random() * parseInt(rr, 16)).toString(16);
  46.918 +      if (v.length === 1) v = '0' + v;
  46.919 +      col[k] = v;
  46.920 +    }
  46.921 +
  46.922 +    return '#' + col.rr + col.gg + col.bb;
  46.923 +  };
  46.924 +
  46.925 +  var processStyleID = function (style) {
  46.926 +    var icon = style.icon;
  46.927 +    if (!icon.href) return;
  46.928 +
  46.929 +    if (icon.img && !icon.img.complete && (icon.dim.w < 0) && (icon.dim.h < 0) ) {
  46.930 +      // we're still waiting on the image loading (probably because we've been blocking since the declaration)
  46.931 +      // so, let's queue this function on the onload stack
  46.932 +      icon.markerBacklog = [];
  46.933 +      icon.img.onload = function() {
  46.934 +        if (icon.dim.w < 0 || icon.dim.h < 0) {
  46.935 +          icon.dim.w = this.width;
  46.936 +          icon.dim.h = this.height;
  46.937 +        }
  46.938 +        processStyleID(style);
  46.939 +
  46.940 +        // we will undoubtedly get some createMarker queuing, so set this up in advance
  46.941 +        for (var i = 0; i < icon.markerBacklog.length; i++) {
  46.942 +          var p = icon.markerBacklog[i][0];
  46.943 +          var d = icon.markerBacklog[i][1];
  46.944 +          createMarker(p, d);
  46.945 +          if (p.marker) p.marker.active = true;
  46.946 +        }
  46.947 +        delete icon.markerBacklog;
  46.948 +      };
  46.949 +      return;
  46.950 +    }
  46.951 +    else if (icon.dim.w < 0 || icon.dim.h < 0) {
  46.952 +      if (icon.img && icon.img.complete) {
  46.953 +        // sometimes the file is already cached and it never calls onLoad
  46.954 +        icon.dim.w = icon.img.width;
  46.955 +        icon.dim.h = icon.img.height;
  46.956 +      }
  46.957 +      else {
  46.958 +        // settle for a default of 32x32
  46.959 +        icon.dim.whGuess = true;
  46.960 +        icon.dim.w = 32;
  46.961 +        icon.dim.h = 32;
  46.962 +      }
  46.963 +    }
  46.964 +
  46.965 +    // pre-scaled variables
  46.966 +    var rnd = Math.round;
  46.967 +    var scaled = {
  46.968 +      x:  icon.dim.x     * icon.scale,
  46.969 +      y:  icon.dim.y     * icon.scale,
  46.970 +      w:  icon.dim.w     * icon.scale,
  46.971 +      h:  icon.dim.h     * icon.scale,
  46.972 +      aX: icon.hotSpot.x * icon.scale,
  46.973 +      aY: icon.hotSpot.y * icon.scale,
  46.974 +      iW: (icon.img ? icon.img.width  : icon.dim.w) * icon.scale,
  46.975 +      iH: (icon.img ? icon.img.height : icon.dim.h) * icon.scale
  46.976 +    };
  46.977 +
  46.978 +    // Figure out the anchor spot
  46.979 +    var aX, aY;
  46.980 +    switch (icon.hotSpot.xunits) {
  46.981 +      case 'fraction':    aX = rnd(scaled.aX * icon.dim.w); break;
  46.982 +      case 'insetPixels': aX = rnd(icon.dim.w * icon.scale - scaled.aX); break;
  46.983 +      default:            aX = rnd(scaled.aX); break;  // already pixels
  46.984 +    }
  46.985 +    aY = rnd( ((icon.hotSpot.yunits === 'fraction') ? icon.dim.h : 1) * scaled.aY );  // insetPixels Y = pixels Y
  46.986 +    var iconAnchor = new google.maps.Point(aX, aY);
  46.987 +
  46.988 +    // Sizes
  46.989 +    // (NOTE: Scale is applied to entire image, not just the section of the icon palette.)
  46.990 +    var iconSize   = icon.dim.whGuess  ? null : new google.maps.Size(rnd(scaled.w),  rnd(scaled.h));
  46.991 +    var iconScale  = icon.scale == 1.0 ? null :
  46.992 +                     icon.dim.whGuess  ?        new google.maps.Size(rnd(scaled.w),  rnd(scaled.h))
  46.993 +                                              : new google.maps.Size(rnd(scaled.iW), rnd(scaled.iH));
  46.994 +    var iconOrigin = new google.maps.Point(rnd(scaled.x), rnd(scaled.y));
  46.995 +
  46.996 +    // Detect images buried in KMZ files (and use a base64 encoded URL)
  46.997 +    if (kmzMetaData[icon.url]) icon.url = kmzMetaData[icon.url].dataUrl;
  46.998 +
  46.999 +    // Init the style object with the KML icon
 46.1000 +    icon.marker = new google.maps.MarkerImage(
 46.1001 +      icon.url,    // url
 46.1002 +      iconSize,    // size
 46.1003 +      iconOrigin,  // origin
 46.1004 +      iconAnchor,  // anchor
 46.1005 +      iconScale    // scaledSize
 46.1006 +    );
 46.1007 +
 46.1008 +    // Look for a predictable shadow
 46.1009 +    var stdRegEx = /\/(red|blue|green|yellow|lightblue|purple|pink|orange)(-dot)?\.png/;
 46.1010 +    var shadowSize = new google.maps.Size(59, 32);
 46.1011 +    var shadowPoint = new google.maps.Point(16, 32);
 46.1012 +    if (stdRegEx.test(icon.href)) {
 46.1013 +      // A standard GMap-style marker icon
 46.1014 +      icon.shadow = new google.maps.MarkerImage(
 46.1015 +        'http://maps.google.com/mapfiles/ms/micons/msmarker.shadow.png', // url
 46.1016 +        shadowSize,                                                      // size
 46.1017 +        null,                                                            // origin
 46.1018 +        shadowPoint,                                                     // anchor
 46.1019 +        shadowSize                                                       // scaledSize
 46.1020 +      );
 46.1021 +    } else if (icon.href.indexOf('-pushpin.png') > -1) {
 46.1022 +      // Pushpin marker icon
 46.1023 +      icon.shadow = new google.maps.MarkerImage(
 46.1024 +        'http://maps.google.com/mapfiles/ms/micons/pushpin_shadow.png',  // url
 46.1025 +        shadowSize,                                                      // size
 46.1026 +        null,                                                            // origin
 46.1027 +        shadowPoint,                                                     // anchor
 46.1028 +        shadowSize                                                       // scaledSize
 46.1029 +      );
 46.1030 +    } /* else {
 46.1031 +      // Other MyMaps KML standard icon
 46.1032 +      icon.shadow = new google.maps.MarkerImage(
 46.1033 +        icon.href.replace('.png', '.shadow.png'),                        // url
 46.1034 +        shadowSize,                                                      // size
 46.1035 +        null,                                                            // origin
 46.1036 +        anchorPoint,                                                     // anchor
 46.1037 +        shadowSize                                                       // scaledSize
 46.1038 +      );
 46.1039 +    } */
 46.1040 +  }
 46.1041 +
 46.1042 +  var processStyles = function (doc) {
 46.1043 +    for (var styleID in doc.styles) {
 46.1044 +      processStyleID(doc.styles[styleID]);
 46.1045 +    }
 46.1046 +  };
 46.1047 +
 46.1048 +  var createMarker = function (placemark, doc) {
 46.1049 +    // create a Marker to the map from a placemark KML object
 46.1050 +    var icon = placemark.style.icon;
 46.1051 +
 46.1052 +    if ( !icon.marker && icon.img ) {
 46.1053 +      // yay, single point of failure is holding up multiple markers...
 46.1054 +      icon.markerBacklog = icon.markerBacklog || [];
 46.1055 +      icon.markerBacklog.push([placemark, doc]);
 46.1056 +      return;
 46.1057 +    }
 46.1058 +
 46.1059 +    // Load basic marker properties
 46.1060 +    var markerOptions = geoXML3.combineOptions(parserOptions.markerOptions, {
 46.1061 +      map:      parserOptions.map,
 46.1062 +      position: new google.maps.LatLng(placemark.Point.coordinates[0].lat, placemark.Point.coordinates[0].lng),
 46.1063 +      title:    placemark.name,
 46.1064 +      zIndex:   Math.round(placemark.Point.coordinates[0].lat * -100000)<<5,
 46.1065 +      icon:     icon.marker,
 46.1066 +      shadow:   icon.shadow,
 46.1067 +      flat:     !icon.shadow,
 46.1068 +      visible:  placemark.visibility
 46.1069 +    });
 46.1070 +
 46.1071 +    // Create the marker on the map
 46.1072 +    var marker = new google.maps.Marker(markerOptions);
 46.1073 +    if (!!doc) doc.markers.push(marker);
 46.1074 +
 46.1075 +    // Set up and create the infowindow if it is not suppressed
 46.1076 +    createInfoWindow(placemark, doc, marker);
 46.1077 +    placemark.marker = marker;
 46.1078 +    return marker;
 46.1079 +  };
 46.1080 +
 46.1081 +  var createOverlay = function (groundOverlay, doc) {
 46.1082 +    // Add a ProjectedOverlay to the map from a groundOverlay KML object
 46.1083 +
 46.1084 +    if (!window.ProjectedOverlay) {
 46.1085 +      throw 'geoXML3 error: ProjectedOverlay not found while rendering GroundOverlay from KML';
 46.1086 +    }
 46.1087 +
 46.1088 +    var bounds = new google.maps.LatLngBounds(
 46.1089 +        new google.maps.LatLng(groundOverlay.latLonBox.south, groundOverlay.latLonBox.west),
 46.1090 +        new google.maps.LatLng(groundOverlay.latLonBox.north, groundOverlay.latLonBox.east)
 46.1091 +    );
 46.1092 +    var overlayOptions = geoXML3.combineOptions(parserOptions.overlayOptions, {percentOpacity: groundOverlay.opacity*100});
 46.1093 +    var overlay = new ProjectedOverlay(parserOptions.map, groundOverlay.icon.href, bounds, overlayOptions);
 46.1094 +
 46.1095 +    if (!!doc) {
 46.1096 +      doc.ggroundoverlays = doc.ggroundoverlays || [];
 46.1097 +      doc.ggroundoverlays.push(overlay);
 46.1098 +    }
 46.1099 +
 46.1100 +    return overlay;
 46.1101 +  };
 46.1102 +
 46.1103 +  // Create Polyline
 46.1104 +  var createPolyline = function(placemark, doc) {
 46.1105 +    var path = [];
 46.1106 +    for (var j=0; j<placemark.LineString.length; j++) {
 46.1107 +      var coords = placemark.LineString[j].coordinates;
 46.1108 +      var bounds = new google.maps.LatLngBounds();
 46.1109 +      for (var i=0;i<coords.length;i++) {
 46.1110 +        var pt = new google.maps.LatLng(coords[i].lat, coords[i].lng);
 46.1111 +        path.push(pt);
 46.1112 +        bounds.extend(pt);
 46.1113 +      }
 46.1114 +    }
 46.1115 +    // point to open the infowindow if triggered
 46.1116 +    var point = path[Math.floor(path.length/2)];
 46.1117 +    // Load basic polyline properties
 46.1118 +    var kmlStrokeColor = kmlColor(placemark.style.line.color, placemark.style.line.colorMode);
 46.1119 +    var polyOptions = geoXML3.combineOptions(parserOptions.polylineOptions, {
 46.1120 +      map:           parserOptions.map,
 46.1121 +      path:          path,
 46.1122 +      strokeColor:   kmlStrokeColor.color,
 46.1123 +      strokeWeight:  placemark.style.line.width,
 46.1124 +      strokeOpacity: kmlStrokeColor.opacity,
 46.1125 +      title:         placemark.name,
 46.1126 +      visible:       placemark.visibility
 46.1127 +    });
 46.1128 +    var p = new google.maps.Polyline(polyOptions);
 46.1129 +    p.bounds = bounds;
 46.1130 +
 46.1131 +    // setup and create the infoWindow if it is not suppressed
 46.1132 +    createInfoWindow(placemark, doc, p);
 46.1133 +    if (!!doc) doc.gpolylines.push(p);
 46.1134 +    placemark.polyline = p;
 46.1135 +    return p;
 46.1136 +  }
 46.1137 +
 46.1138 +  // Create Polygon
 46.1139 +  var createPolygon = function(placemark, doc) {
 46.1140 +    var bounds = new google.maps.LatLngBounds();
 46.1141 +    var pathsLength = 0;
 46.1142 +    var paths = [];
 46.1143 +    for (var polygonPart=0;polygonPart<placemark.Polygon.length;polygonPart++) {
 46.1144 +      for (var j=0; j<placemark.Polygon[polygonPart].outerBoundaryIs.length; j++) {
 46.1145 +        var coords = placemark.Polygon[polygonPart].outerBoundaryIs[j].coordinates;
 46.1146 +        var path = [];
 46.1147 +        for (var i=0;i<coords.length;i++) {
 46.1148 +          var pt = new google.maps.LatLng(coords[i].lat, coords[i].lng);
 46.1149 +          path.push(pt);
 46.1150 +          bounds.extend(pt);
 46.1151 +        }
 46.1152 +        paths.push(path);
 46.1153 +        pathsLength += path.length;
 46.1154 +      }
 46.1155 +      for (var j=0; j<placemark.Polygon[polygonPart].innerBoundaryIs.length; j++) {
 46.1156 +        var coords = placemark.Polygon[polygonPart].innerBoundaryIs[j].coordinates;
 46.1157 +        var path = [];
 46.1158 +        for (var i=0;i<coords.length;i++) {
 46.1159 +          var pt = new google.maps.LatLng(coords[i].lat, coords[i].lng);
 46.1160 +          path.push(pt);
 46.1161 +          bounds.extend(pt);
 46.1162 +        }
 46.1163 +        paths.push(path);
 46.1164 +        pathsLength += path.length;
 46.1165 +      }
 46.1166 +    }
 46.1167 +
 46.1168 +    // Load basic polygon properties
 46.1169 +    var kmlStrokeColor = kmlColor(placemark.style.line.color, placemark.style.line.colorMode);
 46.1170 +    var kmlFillColor = kmlColor(placemark.style.poly.color, placemark.style.poly.colorMode);
 46.1171 +    if (!placemark.style.poly.fill) kmlFillColor.opacity = 0.0;
 46.1172 +    var strokeWeight = placemark.style.line.width;
 46.1173 +    if (!placemark.style.poly.outline) {
 46.1174 +      strokeWeight = 0;
 46.1175 +      kmlStrokeColor.opacity = 0.0;
 46.1176 +    }
 46.1177 +    var polyOptions = geoXML3.combineOptions(parserOptions.polygonOptions, {
 46.1178 +      map:           parserOptions.map,
 46.1179 +      paths:         paths,
 46.1180 +      title:         placemark.name,
 46.1181 +      strokeColor:   kmlStrokeColor.color,
 46.1182 +      strokeWeight:  strokeWeight,
 46.1183 +      strokeOpacity: kmlStrokeColor.opacity,
 46.1184 +      fillColor:     kmlFillColor.color,
 46.1185 +      fillOpacity:   kmlFillColor.opacity,
 46.1186 +      visible:       placemark.visibility
 46.1187 +    });
 46.1188 +    var p = new google.maps.Polygon(polyOptions);
 46.1189 +    
 46.1190 +    
 46.1191 +    google.maps.event.addListener(p,"mouseover",function(){
 46.1192 +    	 this.setOptions({fillColor: "#FFFFFF"});
 46.1193 +    	}); 
 46.1194 +
 46.1195 +    	google.maps.event.addListener(p,"mouseout",function(){
 46.1196 +    	 this.setOptions({fillColor: kmlFillColor.color});
 46.1197 +    	});
 46.1198 +    
 46.1199 +    p.bounds = bounds;
 46.1200 +
 46.1201 +    createInfoWindow(placemark, doc, p);
 46.1202 +    if (!!doc) doc.gpolygons.push(p);
 46.1203 +    placemark.polygon = p;
 46.1204 +    return p;
 46.1205 +  }
 46.1206 +
 46.1207 +  var createInfoWindow = function(placemark, doc, gObj) {
 46.1208 +    var bStyle = placemark.style.balloon;
 46.1209 +    var vars = placemark.vars;
 46.1210 +
 46.1211 +    if (!placemark.balloonVisibility || bStyle.displayMode === 'hide') return;
 46.1212 +
 46.1213 +    // define geDirections
 46.1214 +    if (placemark.latlng) {
 46.1215 +      vars.directions.push('sll=' + placemark.latlng.toUrlValue());
 46.1216 +
 46.1217 +      var url = 'http://maps.google.com/maps?' + vars.directions.join('&');
 46.1218 +      var address = encodeURIComponent( vars.val.address || placemark.latlng.toUrlValue() ).replace(/\%20/g, '+');
 46.1219 +
 46.1220 +      vars.val.geDirections = '<a href="' + url + '&daddr=' + address + '" target=_blank>To Here</a> - <a href="' + url + '&saddr=' + address + '" target=_blank>From Here</a>';
 46.1221 +    }
 46.1222 +    else vars.val.geDirections = '';
 46.1223 +
 46.1224 +    // add in the variables
 46.1225 +    var iwText = bStyle.text.replace(/\$\[(\w+(\/displayName)?)\]/g, function(txt, n, dn) { return dn ? vars.display[n] : vars.val[n]; });
 46.1226 +    var classTxt = 'geoxml3_infowindow geoxml3_style_' + placemark.styleID;
 46.1227 +
 46.1228 +    // color styles
 46.1229 +    var styleArr = [];
 46.1230 +    if (bStyle.bgColor   != 'ffffffff') styleArr.push('background: ' + kmlColor(bStyle.bgColor  ).color + ';');
 46.1231 +    if (bStyle.textColor != 'ff000000') styleArr.push('color: '      + kmlColor(bStyle.textColor).color + ';');
 46.1232 +    var styleProp = styleArr.length ? ' style="' + styleArr.join(' ') + '"' : '';
 46.1233 +
 46.1234 +    var infoWindowOptions = geoXML3.combineOptions(parserOptions.infoWindowOptions, {
 46.1235 +      content: '<div class="' + classTxt + '"' + styleProp + '>' + iwText + '</div>',
 46.1236 +      pixelOffset: new google.maps.Size(0, 2)
 46.1237 +    });
 46.1238 +
 46.1239 +    gObj.infoWindow = parserOptions.infoWindow || new google.maps.InfoWindow(infoWindowOptions);
 46.1240 +    gObj.infoWindowOptions = infoWindowOptions;
 46.1241 +
 46.1242 +    // Info Window-opening event handler
 46.1243 +    google.maps.event.addListener(gObj, 'click', function(e) {
 46.1244 +      var iW = this.infoWindow;
 46.1245 +      iW.close();
 46.1246 +      iW.setOptions(this.infoWindowOptions);
 46.1247 +
 46.1248 +      if      (e && e.latLng) iW.setPosition(e.latLng);
 46.1249 +      else if (this.bounds)   iW.setPosition(this.bounds.getCenter());
 46.1250 +
 46.1251 +      iW.setContent("<div id='geoxml3_infowindow'>"+iW.getContent()+"</div>");
 46.1252 +      google.maps.event.addListenerOnce(iW, "domready", function() {
 46.1253 +        var node = document.getElementById('geoxml3_infowindow');
 46.1254 +        var imgArray = node.getElementsByTagName('img');
 46.1255 +        for (var i = 0; i < imgArray.length; i++) 
 46.1256 +        {
 46.1257 +          var imgUrlIE = imgArray[i].getAttribute("src");
 46.1258 +          var imgUrl  = cleanURL(doc.baseDir, imgUrlIE);
 46.1259 +
 46.1260 +          if (kmzMetaData[imgUrl]) {
 46.1261 +             imgArray[i].src = kmzMetaData[imgUrl].dataUrl;
 46.1262 +          } else if (kmzMetaData[imgUrlIE]) {
 46.1263 +             imgArray[i].src = kmzMetaData[imgUrlIE].dataUrl;
 46.1264 +          }
 46.1265 +        }
 46.1266 +      });
 46.1267 +      iW.open(this.map, this.bounds ? null : this);
 46.1268 +    });
 46.1269 +
 46.1270 +  }
 46.1271 +
 46.1272 +  return {
 46.1273 +    // Expose some properties and methods
 46.1274 +
 46.1275 +    options:     parserOptions,
 46.1276 +    docs:        docs,
 46.1277 +    docsByUrl:   docsByUrl,
 46.1278 +    kmzMetaData: kmzMetaData,
 46.1279 +
 46.1280 +    parse:          parse,
 46.1281 +    parseKmlString: parseKmlString,
 46.1282 +    hideDocument:   hideDocument,
 46.1283 +    showDocument:   showDocument,
 46.1284 +    processStyles:  processStyles,
 46.1285 +    createMarker:   createMarker,
 46.1286 +    createOverlay:  createOverlay,
 46.1287 +    createPolyline: createPolyline,
 46.1288 +    createPolygon:  createPolygon
 46.1289 +  };
 46.1290 +};
 46.1291 +// End of KML Parser
 46.1292 +
 46.1293 +// Helper objects and functions
 46.1294 +geoXML3.getOpacity = function (kmlColor) {
 46.1295 +  // Extract opacity encoded in a KML color value. Returns a number between 0 and 1.
 46.1296 +  if (!!kmlColor &&
 46.1297 +      (kmlColor !== '') &&
 46.1298 +      (kmlColor.length == 8)) {
 46.1299 +    var transparency = parseInt(kmlColor.substr(0, 2), 16);
 46.1300 +    return transparency / 255;
 46.1301 +  } else {
 46.1302 +    return 1;
 46.1303 +  }
 46.1304 +};
 46.1305 +
 46.1306 +// Log a message to the debugging console, if one exists
 46.1307 +geoXML3.log = function(msg) {
 46.1308 +  if (!!window.console) {
 46.1309 +    console.log(msg);
 46.1310 +  } else { alert("log:"+msg); }
 46.1311 +};
 46.1312 +
 46.1313 +/**
 46.1314 + * Creates a new parserOptions object.
 46.1315 + * @class GeoXML3 parser options.
 46.1316 + * @param {Object} overrides Any options you want to declare outside of the defaults should be included here.
 46.1317 + * @property {google.maps.Map} map The API map on which geo objects should be rendered.
 46.1318 + * @property {google.maps.MarkerOptions} markerOptions If the parser is adding Markers to the map itself, any options specified here will be applied to them.
 46.1319 + * @property {google.maps.InfoWindowOptions} infoWindowOptions If the parser is adding Markers to the map itself, any options specified here will be applied to their attached InfoWindows.
 46.1320 + * @property {ProjectedOverlay.options} overlayOptions If the parser is adding ProjectedOverlays to the map itself, any options specified here will be applied to them.
 46.1321 + */
 46.1322 +geoXML3.parserOptions = function (overrides) {
 46.1323 +  this.map                 = null,
 46.1324 +  /** If true, the parser will automatically move the map to a best-fit of the geodata after parsing of a KML document completes.
 46.1325 +   * @type Boolean
 46.1326 +   * @default true
 46.1327 +   */
 46.1328 +  this.zoom                = true,
 46.1329 +  /**#@+ @type Boolean
 46.1330 +   *     @default false */
 46.1331 +  /** If true, only a single Marker created by the parser will be able to have its InfoWindow open at once (simulating the behavior of GMaps API v2). */
 46.1332 +  this.singleInfoWindow    = false,
 46.1333 +  /** If true, suppresses the rendering of info windows. */
 46.1334 +  this.suppressInfoWindows = false,
 46.1335 +  /**
 46.1336 +   * Control whether to process styles now or later.
 46.1337 +   *
 46.1338 +   * <p>By default, the parser only processes KML &lt;Style&gt; elements into their GMaps equivalents
 46.1339 +   * if it will be creating its own Markers (the createMarker option is null). Setting this option
 46.1340 +   * to true will force such processing to happen anyway, useful if you're going to be calling parser.createMarker
 46.1341 +   * yourself later. OTOH, leaving this option false removes runtime dependency on the GMaps API, enabling
 46.1342 +   * the use of geoXML3 as a standalone KML parser.</p>
 46.1343 +   */
 46.1344 +  this.processStyles       = false,
 46.1345 +  /**#@-*/
 46.1346 +
 46.1347 +  this.markerOptions       = {},
 46.1348 +  this.infoWindowOptions   = {},
 46.1349 +  this.overlayOptions      = {},
 46.1350 +
 46.1351 +  /**#@+ @event */
 46.1352 +  /** This function will be called when parsing of a KML document is complete.
 46.1353 +   * @param {geoXML3.parser#docs} doc Parsed KML data. */
 46.1354 +  this.afterParse          = null,
 46.1355 +  /** This function will be called when parsing of a KML document is complete.
 46.1356 +   * @param {geoXML3.parser#docs} doc Parsed KML data. */
 46.1357 +  this.failedParse         = null,
 46.1358 +  /**
 46.1359 +   * If supplied, this function will be called once for each marker <Placemark> in the KML document, instead of the parser adding its own Marker to the map.
 46.1360 +   * @param {geoXML3.parser.render#placemark} placemark Placemark object.
 46.1361 +   * @param {geoXML3.parser#docs} doc Parsed KML data.
 46.1362 +   */
 46.1363 +  this.createMarker        = null,
 46.1364 +  /**
 46.1365 +   * If supplied, this function will be called once for each <GroundOverlay> in the KML document, instead of the parser adding its own ProjectedOverlay to the map.
 46.1366 +   * @param {geoXML3.parser.render#groundOverlay} groundOverlay GroundOverlay object.
 46.1367 +   * @param {geoXML3.parser#docs} doc Parsed KML data.
 46.1368 +   */
 46.1369 +  this.createOverlay       = null
 46.1370 +  /**#@-*/
 46.1371 +
 46.1372 +  if (overrides) {
 46.1373 +    for (var prop in overrides) {
 46.1374 +      if (overrides.hasOwnProperty(prop)) this[prop] = overrides[prop];
 46.1375 +    }
 46.1376 +  }
 46.1377 +  return this;
 46.1378 +};
 46.1379 +
 46.1380 +/**
 46.1381 + * Combine two options objects: a set of default values and a set of override values.
 46.1382 + *
 46.1383 + * @deprecated This has been replaced with {@link geoXML3.parserOptions#combineOptions}.
 46.1384 + * @param {geoXML3.parserOptions|Object} overrides Override values.
 46.1385 + * @param {geoXML3.parserOptions|Object} defaults Default values.
 46.1386 + * @return {geoXML3.parserOptions} Combined result.
 46.1387 + */
 46.1388 +geoXML3.combineOptions = function (overrides, defaults) {
 46.1389 +  var result = {};
 46.1390 +  if (!!overrides) {
 46.1391 +    for (var prop in overrides) {
 46.1392 +      if (overrides.hasOwnProperty(prop))                              result[prop] = overrides[prop];
 46.1393 +    }
 46.1394 +  }
 46.1395 +  if (!!defaults) {
 46.1396 +    for (prop in defaults) {
 46.1397 +      if (defaults.hasOwnProperty(prop) && result[prop] === undefined) result[prop] = defaults[prop];
 46.1398 +    }
 46.1399 +  }
 46.1400 +  return result;
 46.1401 +};
 46.1402 +
 46.1403 +/**
 46.1404 + * Combine two options objects: a set of default values and a set of override values.
 46.1405 + *
 46.1406 + * @function
 46.1407 + * @param {geoXML3.parserOptions|Object} overrides Override values.
 46.1408 + * @param {geoXML3.parserOptions|Object} defaults Default values.
 46.1409 + * @return {geoXML3.parserOptions} Combined result.
 46.1410 + */
 46.1411 +geoXML3.parserOptions.prototype.combineOptions = geoXML3.combineOptions;
 46.1412 +
 46.1413 +// Retrieve an XML document from url and pass it to callback as a DOM document
 46.1414 +geoXML3.fetchers = [];
 46.1415 +
 46.1416 +/**
 46.1417 + * Parses a XML string.
 46.1418 + *
 46.1419 + * <p>Parses the given XML string and returns the parsed document in a
 46.1420 + * DOM data structure. This function will return an empty DOM node if
 46.1421 + * XML parsing is not supported in this browser.</p>
 46.1422 + *
 46.1423 + * @param {String} str XML string.
 46.1424 + * @return {Element|Document} DOM.
 46.1425 + */
 46.1426 +geoXML3.xmlParse = function (str) {
 46.1427 +  if (typeof ActiveXObject != 'undefined' && typeof GetObject != 'undefined') {
 46.1428 +    var doc = new ActiveXObject('Microsoft.XMLDOM');
 46.1429 +    doc.loadXML(str);
 46.1430 +    return doc;
 46.1431 +  }
 46.1432 +
 46.1433 +  if (typeof DOMParser != 'undefined') {
 46.1434 +    return (new DOMParser()).parseFromString(str, 'text/xml');
 46.1435 +  }
 46.1436 +
 46.1437 +  return createElement('div', null);
 46.1438 +}
 46.1439 +
 46.1440 +/**
 46.1441 + * Fetches a XML document.
 46.1442 + *
 46.1443 + * <p>Fetches/parses the given XML URL and passes the parsed document (in a
 46.1444 + * DOM data structure) to the given callback.  Documents are downloaded
 46.1445 + * and parsed asynchronously.</p>
 46.1446 + *
 46.1447 + * @param {String} url URL of XML document.  Must be uncompressed XML only.
 46.1448 + * @param {Function(Document)} callback Function to call when the document is processed.
 46.1449 + */
 46.1450 +geoXML3.fetchXML = function (url, callback) {
 46.1451 +  function timeoutHandler() { callback(); };
 46.1452 +
 46.1453 +  var xhrFetcher = new Object();
 46.1454 +  if      (!!geoXML3.fetchers.length) xhrFetcher = geoXML3.fetchers.pop();
 46.1455 +  else if (!!window.XMLHttpRequest)   xhrFetcher.fetcher = new window.XMLHttpRequest();  // Most browsers
 46.1456 +  else if (!!window.ActiveXObject) {                                                     // Some IE
 46.1457 +    // the many versions of IE's XML fetchers
 46.1458 +    var AXOs = [
 46.1459 +      'MSXML2.XMLHTTP.6.0',
 46.1460 +      'MSXML2.XMLHTTP.5.0',
 46.1461 +      'MSXML2.XMLHTTP.4.0',
 46.1462 +      'MSXML2.XMLHTTP.3.0',
 46.1463 +      'MSXML2.XMLHTTP',
 46.1464 +      'Microsoft.XMLHTTP',
 46.1465 +      'MSXML.XMLHTTP'
 46.1466 +    ];
 46.1467 +    for (var i = 0; i < AXOs.length; i++) {
 46.1468 +      try      { xhrFetcher.fetcher = new ActiveXObject(AXOs[i]); break; }
 46.1469 +      catch(e) { continue; }
 46.1470 +    }
 46.1471 +    if (!xhrFetcher.fetcher) {
 46.1472 +      geoXML3.log('Unable to create XHR object');
 46.1473 +      callback(null);
 46.1474 +      return null;
 46.1475 +    }
 46.1476 +  }
 46.1477 +
 46.1478 +  if (!!xhrFetcher.fetcher.overrideMimeType) xhrFetcher.fetcher.overrideMimeType('text/xml');
 46.1479 +  xhrFetcher.fetcher.open('GET', url, true);
 46.1480 +  xhrFetcher.fetcher.onreadystatechange = function () {
 46.1481 +    if (xhrFetcher.fetcher.readyState === 4) {
 46.1482 +      // Retrieval complete
 46.1483 +      if (!!xhrFetcher.xhrtimeout) clearTimeout(xhrFetcher.xhrtimeout);
 46.1484 +      if (xhrFetcher.fetcher.status >= 400) {
 46.1485 +        geoXML3.log('HTTP error ' + xhrFetcher.fetcher.status + ' retrieving ' + url);
 46.1486 +        callback();
 46.1487 +      }
 46.1488 +      // Returned successfully
 46.1489 +      else {
 46.1490 +        if (xhrFetcher.fetcher.responseXML) {
 46.1491 +        // Sometimes IE will get the data, but won't bother loading it as an XML doc
 46.1492 +        var xmlDoc = xhrFetcher.fetcher.responseXML;
 46.1493 +        if (xmlDoc && !xmlDoc.documentElement && !xmlDoc.ownerElement) xmlDoc.loadXML(xhrFetcher.fetcher.responseText);
 46.1494 +          callback(xmlDoc);          
 46.1495 +        } else // handle valid xml sent with wrong MIME type 
 46.1496 +          callback(geoXML3.xmlParse(xhrFetcher.fetcher.responseText));
 46.1497 +      }
 46.1498 +
 46.1499 +      // We're done with this fetcher object
 46.1500 +      geoXML3.fetchers.push(xhrFetcher);
 46.1501 +    }
 46.1502 +  };
 46.1503 +
 46.1504 +  xhrFetcher.xhrtimeout = setTimeout(timeoutHandler, 60000);
 46.1505 +  xhrFetcher.fetcher.send(null);
 46.1506 +  return null;
 46.1507 +};
 46.1508 +
 46.1509 +var IEversion = function() {
 46.1510 +  // http://msdn.microsoft.com/workshop/author/dhtml/overview/browserdetection.asp
 46.1511 +  // Returns the version of Internet Explorer or a -1
 46.1512 +  // (indicating the use of another browser).
 46.1513 +  var rv = -1; // Return value assumes failure
 46.1514 +  if (navigator.appName == 'Microsoft Internet Explorer') {
 46.1515 +    var ua = navigator.userAgent;
 46.1516 +    var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
 46.1517 +    if (re.exec(ua) != null) {
 46.1518 +      rv = parseFloat( RegExp.$1 );
 46.1519 +    }
 46.1520 +  }
 46.1521 +  return rv;
 46.1522 +};
 46.1523 +
 46.1524 +/**
 46.1525 + * Fetches a KMZ document.
 46.1526 + *
 46.1527 + * <p>Fetches/parses the given ZIP URL, parses each image file, and passes
 46.1528 + * the parsed KML document to the given callback.  Documents are downloaded
 46.1529 + * and parsed asynchronously, though the KML file is always passed after the
 46.1530 + * images have been processed, in case the callback requires the image data.</p>
 46.1531 + *
 46.1532 + * @requires ZipFile.complete.js
 46.1533 + * @param {String} url URL of KMZ document.  Must be a valid KMZ/ZIP archive.
 46.1534 + * @param {Function(Document)} callback Function to call when the document is processed.
 46.1535 + * @param {geoXML3.parser} parser A geoXML3.parser object.  This is used to populate the KMZ image data.
 46.1536 + * @author Brendan Byrd
 46.1537 + * @see http://code.google.com/apis/kml/documentation/kmzarchives.html
 46.1538 + */
 46.1539 +geoXML3.fetchZIP = function (url, callback, parser) {
 46.1540 +  // Just need a single 'new' declaration with a really long function...
 46.1541 +  var zipFile = new ZipFile(url, function (zip) {
 46.1542 +    // Retrieval complete
 46.1543 +
 46.1544 +    // Check for ERRORs in zip.status
 46.1545 +    for (var i = 0; i < zip.status.length; i++) {
 46.1546 +      var msg = zip.status[i];
 46.1547 +      if      (msg.indexOf("ERROR") == 0) {
 46.1548 +        geoXML3.log('HTTP/ZIP error retrieving ' + url + ': ' + msg);
 46.1549 +        callback();
 46.1550 +        return;
 46.1551 +      }
 46.1552 +      else if (msg.indexOf("WARNING") == 0) {  // non-fatal, but still might be useful
 46.1553 +        geoXML3.log('HTTP/ZIP warning retrieving ' + url + ': ' + msg);
 46.1554 +      }
 46.1555 +    }
 46.1556 +
 46.1557 +    // Make sure KMZ structure is according to spec (with a single KML file in the root dir)
 46.1558 +    var KMLCount = 0;
 46.1559 +    var KML;
 46.1560 +    for (var i = 0; i < zip.entries.length; i++) {
 46.1561 +      var name = zip.entries[i].name;
 46.1562 +      if (!/\.kml$/.test(name)) continue;
 46.1563 +
 46.1564 +      KMLCount++;
 46.1565 +      if (KMLCount == 1) KML = i;
 46.1566 +      else {
 46.1567 +        geoXML3.log('KMZ warning retrieving ' + url + ': found extra KML "' + name + '" in KMZ; discarding...');
 46.1568 +      }
 46.1569 +    }
 46.1570 +
 46.1571 +    // Returned successfully, but still needs extracting
 46.1572 +    var baseUrl = cleanURL(defileURL(url), url) + '/';
 46.1573 +    var kmlProcessing = {  // this is an object just so it gets passed properly
 46.1574 +      timer: null,
 46.1575 +      extractLeft: 0,
 46.1576 +      timerCalls: 0
 46.1577 +    };
 46.1578 +    var extractCb = function(entry, entryContent) {
 46.1579 +      var mdUrl = cleanURL(baseUrl, entry.name);
 46.1580 +      var ext = entry.name.substring(entry.name.lastIndexOf(".") + 1).toLowerCase();
 46.1581 +      kmlProcessing.extractLeft--;
 46.1582 +
 46.1583 +      if ((typeof entryContent.description == "string") && (entryContent.name == "Error")) {
 46.1584 +        geoXML3.log('KMZ error extracting ' + mdUrl + ': ' + entryContent.description);
 46.1585 +        callback();
 46.1586 +        return;
 46.1587 +      }
 46.1588 +
 46.1589 +      // MIME types that can be used in KML
 46.1590 +      var mime;
 46.1591 +      if (ext === 'jpg') ext = 'jpeg';
 46.1592 +      if (/^(gif|jpeg|png)$/.test(ext)) mime = 'image/' + ext;
 46.1593 +      else if (ext === 'mp3')           mime = 'audio/mpeg';
 46.1594 +      else if (ext === 'm4a')           mime = 'audio/mp4';
 46.1595 +      else if (ext === 'm4a')           mime = 'audio/MP4-LATM';
 46.1596 +      else                              mime = 'application/octet-stream';
 46.1597 +
 46.1598 +      parser.kmzMetaData[mdUrl] = {};
 46.1599 +      parser.kmzMetaData[mdUrl].entry = entry;
 46.1600 +      // data:image/gif;base64,R0lGODlhEAAOALMA...
 46.1601 +      parser.kmzMetaData[mdUrl].dataUrl = 'data:' + mime + ';base64,' + base64Encode(entryContent);
 46.1602 +      // IE cannot handle GET requests beyond 2071 characters, even if it's an inline image
 46.1603 +	if (/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent))
 46.1604 +        { 
 46.1605 +            if (((IEversion() < 8.0) &&
 46.1606 +                 (parser.kmzMetaData[mdUrl].dataUrl.length > 2071)) ||
 46.1607 +                ((IEversion < 9.0) && 
 46.1608 +                 (parser.kmzMetaData[mdUrl].dataUrl.length > 32767))) {
 46.1609 +             parser.kmzMetaData[mdUrl].dataUrl =
 46.1610 +             // this is a simple IE icon; to hint at the problem...
 46.1611 +             'data:image/gif;base64,R0lGODlhDwAQAOMPADBPvSpQ1Dpoyz1p6FhwvU2A6ECP63CM04CWxYCk+V6x+UK++Jao3rvC3fj7+v///yH5BAEKAA8ALAAAAAAPABAAAASC8Mk5mwCAUMlWwcLRHEelLA' +
 46.1612 +             'oGDMgzSsiyGCAhCETDPMh5XQCBwYBrNBIKWmg0MCQHj8MJU5IoroYCY6AAAgrDIbbQDGIK6DR5UPhlNo0JAlSUNAiDgH7eNAxEDWAKCQM2AAFheVxYAA0AIkFOJ1gBcQQaUQKKA5w7LpcEBwkJaKMUEQA7';
 46.1613 +            } 
 46.1614 +       }
 46.1615 +       parser.kmzMetaData[internalSrc(entry.name)]=parser.kmzMetaData[mdUrl];	
 46.1616 +
 46.1617 +    };
 46.1618 +    var kmlExtractCb = function(entry, entryContent) {
 46.1619 +      if ((typeof entryContent.description == "string") && (entryContent.name == "Error")) {
 46.1620 +        geoXML3.log('KMZ error extracting ' + mdUrl + ': ' + entryContent.description);
 46.1621 +        callback();
 46.1622 +        return;
 46.1623 +      }
 46.1624 +
 46.1625 +      // check to see if the KML is the last file extracted
 46.1626 +      clearTimeout(kmlProcessing.timer);
 46.1627 +      if (kmlProcessing.extractLeft <= 1) {
 46.1628 +        kmlProcessing.extractLeft--;
 46.1629 +        callback(geoXML3.xmlParse(entryContent));
 46.1630 +        return;
 46.1631 +      }
 46.1632 +      else {
 46.1633 +        // KML file isn't last yet; it may need to use those files, so wait a bit (100ms)
 46.1634 +        kmlProcessing.timerCalls++;
 46.1635 +        if (kmlProcessing.timerCalls < 100) {
 46.1636 +          kmlProcessing.timer = setTimeout(function() { kmlExtractCb(entry, entryContent); }, 100);
 46.1637 +        }
 46.1638 +        else {
 46.1639 +          geoXML3.log('KMZ warning extracting ' + url + ': entire ZIP has not been extracted after 10 seconds; running through KML, anyway...');
 46.1640 +          kmlProcessing.extractLeft--;
 46.1641 +          callback(geoXML3.xmlParse(entryContent));
 46.1642 +        }
 46.1643 +      }
 46.1644 +      return;
 46.1645 +    };
 46.1646 +    for (var i = 0; i < zip.entries.length; i++) {
 46.1647 +      var entry = zip.entries[i];
 46.1648 +      var ext = entry.name.substring(entry.name.lastIndexOf(".") + 1).toLowerCase();
 46.1649 +      if (!/^(gif|jpe?g|png|kml)$/.test(ext)) continue;  // not going to bother to extract files we don't support
 46.1650 +      if (ext === "kml" && i != KML)          continue;  // extra KMLs get discarded
 46.1651 +      if (!parser && ext != "kml")            continue;  // cannot store images without a parser object
 46.1652 +
 46.1653 +      // extract asynchronously
 46.1654 +      kmlProcessing.extractLeft++;
 46.1655 +      if (ext === "kml") entry.extract(kmlExtractCb);
 46.1656 +      else               entry.extract(extractCb);
 46.1657 +    }
 46.1658 +  });
 46.1659 +
 46.1660 +};
 46.1661 +
 46.1662 +/**
 46.1663 + * Extract the text value of a DOM node, with leading and trailing whitespace trimmed.
 46.1664 + *
 46.1665 + * @param {Element} node XML node/element.
 46.1666 + * @param {Any} delVal Default value if the node doesn't exist.
 46.1667 + * @return {String|Null}
 46.1668 + */
 46.1669 +geoXML3.nodeValue = function(node, defVal) {
 46.1670 +  var retStr="";
 46.1671 +  if (!node) {
 46.1672 +    return (typeof defVal === 'undefined' || defVal === null) ? null : defVal;
 46.1673 +  }
 46.1674 +   if(node.nodeType==3||node.nodeType==4||node.nodeType==2){
 46.1675 +      retStr+=node.nodeValue;
 46.1676 +   }else if(node.nodeType==1||node.nodeType==9||node.nodeType==11){
 46.1677 +      for(var i=0;i<node.childNodes.length;++i){
 46.1678 +         retStr+=arguments.callee(node.childNodes[i]);
 46.1679 +      }
 46.1680 +   }
 46.1681 +   return retStr;
 46.1682 +};
 46.1683 +
 46.1684 +/**
 46.1685 + * Loosely translate various values of a DOM node to a boolean.
 46.1686 + *
 46.1687 + * @param {Element} node XML node/element.
 46.1688 + * @param {Boolean} delVal Default value if the node doesn't exist.
 46.1689 + * @return {Boolean|Null}
 46.1690 + */
 46.1691 +geoXML3.getBooleanValue = function(node, defVal) {
 46.1692 +  var nodeContents = geoXML3.nodeValue(node);
 46.1693 +  if (nodeContents === null) return defVal || false;
 46.1694 +  nodeContents = parseInt(nodeContents);
 46.1695 +  if (isNaN(nodeContents)) return true;
 46.1696 +  if (nodeContents == 0) return false;
 46.1697 +  else return true;
 46.1698 +}
 46.1699 +
 46.1700 +/**
 46.1701 + * Browser-normalized version of getElementsByTagNameNS.
 46.1702 + *
 46.1703 + * <p>Required because IE8 doesn't define it.</p>
 46.1704 + *
 46.1705 + * @param {Element|Document} node DOM object.
 46.1706 + * @param {String} namespace Full namespace URL to search against.
 46.1707 + * @param {String} tagname XML local tag name.
 46.1708 + * @return {Array of Elements}
 46.1709 + * @author Brendan Byrd
 46.1710 + */
 46.1711 +geoXML3.getElementsByTagNameNS = function(node, namespace, tagname) {
 46.1712 +  if (node && typeof node.getElementsByTagNameNS != 'undefined') return node.getElementsByTagNameNS(namespace, tagname);
 46.1713 +  if (!node) return [];
 46.1714 +
 46.1715 +  var root = node.documentElement || node.ownerDocument && node.ownerDocument.documentElement;
 46.1716 +  if (!root || !root.attributes) return [];
 46.1717 +
 46.1718 +  // search for namespace prefix
 46.1719 +  for (var i = 0; i < root.attributes.length; i++) {
 46.1720 +    var attr = root.attributes[i];
 46.1721 +    if      (attr.prefix   === 'xmlns' && attr.nodeValue === namespace) return node.getElementsByTagName(attr.baseName + ':' + tagname);
 46.1722 +    else if (attr.nodeName === 'xmlns' && attr.nodeValue === namespace) {
 46.1723 +      // default namespace
 46.1724 +      if (typeof node.selectNodes != 'undefined') {
 46.1725 +        // Newer IEs have the SelectionNamespace property that can be used with selectNodes
 46.1726 +        if (!root.ownerDocument.getProperty('SelectionNamespaces'))
 46.1727 +          root.ownerDocument.setProperty('SelectionNamespaces', "xmlns:defaultNS='" + namespace + "'");
 46.1728 +        return node.selectNodes('.//defaultNS:' + tagname);
 46.1729 +      }
 46.1730 +      else {
 46.1731 +        // Otherwise, you can still try to tack on the 'xmlns' attribute to root
 46.1732 +        root.setAttribute('xmlns:defaultNS', namespace);
 46.1733 +        return node.getElementsByTagName('defaultNS:' + tagname);
 46.1734 +      }
 46.1735 +    }
 46.1736 +  }
 46.1737 +  return geoXML3.getElementsByTagName(node, tagname);  // try the unqualified version
 46.1738 +};
 46.1739 +
 46.1740 +/**
 46.1741 + * Browser-normalized version of getElementsByTagName.
 46.1742 + *
 46.1743 + * <p>Required because MSXML 6.0 will treat this function as a NS-qualified function,
 46.1744 + * despite the missing NS parameter.</p>
 46.1745 + *
 46.1746 + * @param {Element|Document} node DOM object.
 46.1747 + * @param {String} tagname XML local tag name.
 46.1748 + * @return {Array of Elements}
 46.1749 + * @author Brendan Byrd
 46.1750 + */
 46.1751 +geoXML3.getElementsByTagName = function(node, tagname) {
 46.1752 +  if (node && typeof node.getElementsByTagNameNS != 'undefined') return node.getElementsByTagName(tagname);  // if it has both functions, it should be accurate
 46.1753 +//  if (node && typeof node.selectNodes != 'undefined')            return node.selectNodes(".//*[local-name()='" + tagname + "']");
 46.1754 +  return node.getElementsByTagName(tagname);  // hope for the best...
 46.1755 +}
 46.1756 +
 46.1757 +/**
 46.1758 + * Turn a directory + relative URL into an absolute one.
 46.1759 + *
 46.1760 + * @private
 46.1761 + * @param {String} d Base directory.
 46.1762 + * @param {String} s Relative URL.
 46.1763 + * @return {String} Absolute URL.
 46.1764 + * @author Brendan Byrd
 46.1765 + */
 46.1766 +var toAbsURL = function (d, s) {
 46.1767 +  var p, f, i;
 46.1768 +  var h = location.protocol + "://" + location.host;
 46.1769 +
 46.1770 +  if (!s.length)           return '';
 46.1771 +  if (/^\w+:/.test(s))     return s;
 46.1772 +  if (s.indexOf('/') == 0) return h + s;
 46.1773 +
 46.1774 +  p = d.replace(/\/[^\/]*$/, '');
 46.1775 +  f = s.match(/\.\.\//g);
 46.1776 +  if (f) {
 46.1777 +    s = s.substring(f.length * 3);
 46.1778 +    for (i = f.length; i--;) { p = p.substring(0, p.lastIndexOf('/')); }
 46.1779 +  }
 46.1780 +
 46.1781 +  return h + p + '/' + s;
 46.1782 +}
 46.1783 +
 46.1784 +var internalSrc = function(src) {
 46.1785 +  //this gets the full url
 46.1786 +  var url = document.location.href;
 46.1787 +  //this removes everything after the last slash in the path
 46.1788 +  url = url.substring(0,url.lastIndexOf("/") + 1);
 46.1789 +  var internalPath= url+src;
 46.1790 +  return internalPath;
 46.1791 +}
 46.1792 +
 46.1793 +/**
 46.1794 + * Remove current host from URL
 46.1795 + *
 46.1796 + * @private
 46.1797 + * @param {String} s Absolute or relative URL.
 46.1798 + * @return {String} Root-based relative URL.
 46.1799 + * @author Brendan Byrd
 46.1800 + */
 46.1801 +var dehostURL = function (s) {
 46.1802 +  var h = location.protocol + "://" + location.host;
 46.1803 +  h = h.replace(/([\.\\\+\*\?\[\^\]\$\(\)])/g, '\\$1');  // quotemeta
 46.1804 +  return s.replace(new RegExp('^' + h, 'i'), '');
 46.1805 +}
 46.1806 +
 46.1807 +/**
 46.1808 + * Removes all query strings, #IDs, '../' references, and
 46.1809 + * hosts from a URL.
 46.1810 + *
 46.1811 + * @private
 46.1812 + * @param {String} d Base directory.
 46.1813 + * @param {String} s Absolute or relative URL.
 46.1814 + * @return {String} Root-based relative URL.
 46.1815 + * @author Brendan Byrd
 46.1816 + */
 46.1817 +var cleanURL  = function (d, s) { return dehostURL(toAbsURL(d ? d.split('#')[0].split('?')[0] : defileURL(location.pathname), s ? s.split('#')[0].split('?')[0] : '')); }
 46.1818 +/**
 46.1819 + * Remove filename from URL
 46.1820 + *
 46.1821 + * @private
 46.1822 + * @param {String} s Relative URL.
 46.1823 + * @return {String} Base directory.
 46.1824 + * @author Brendan Byrd
 46.1825 + */
 46.1826 +var defileURL = function (s)    { return s ? s.substr(0, s.lastIndexOf('/') + 1) : '/'; }
 46.1827 +
 46.1828 +
 46.1829 +// Some extra Array subs for ease of use
 46.1830 +// http://stackoverflow.com/questions/143847/best-way-to-find-an-item-in-a-javascript-array
 46.1831 +Array.prototype.hasObject = (
 46.1832 +  !Array.indexOf ? function (obj) {
 46.1833 +    var l = this.length + 1;
 46.1834 +    while (l--) {
 46.1835 +      if (this[l - 1] === obj) return true;
 46.1836 +    }
 46.1837 +    return false;
 46.1838 +  } : function (obj) {
 46.1839 +    return (this.indexOf(obj) !== -1);
 46.1840 +  }
 46.1841 +);
 46.1842 +Array.prototype.hasItemInObj = function (name, item) {
 46.1843 +  var l = this.length + 1;
 46.1844 +  while (l--) {
 46.1845 +    if (this[l - 1][name] === item) return true;
 46.1846 +  }
 46.1847 +  return false;
 46.1848 +};
 46.1849 +if (!Array.prototype.indexOf) {
 46.1850 +  Array.prototype.indexOf = function (obj, fromIndex) {
 46.1851 +    if (fromIndex == null) {
 46.1852 +      fromIndex = 0;
 46.1853 +    } else if (fromIndex < 0) {
 46.1854 +      fromIndex = Math.max(0, this.length + fromIndex);
 46.1855 +    }
 46.1856 +    for (var i = fromIndex, j = this.length; i < j; i++) {
 46.1857 +      if (this[i] === obj) return i;
 46.1858 +    }
 46.1859 +    return -1;
 46.1860 +  };
 46.1861 +}
 46.1862 +Array.prototype.indexOfObjWithItem = function (name, item, fromIndex) {
 46.1863 +  if (fromIndex == null) {
 46.1864 +    fromIndex = 0;
 46.1865 +  } else if (fromIndex < 0) {
 46.1866 +    fromIndex = Math.max(0, this.length + fromIndex);
 46.1867 +  }
 46.1868 +  for (var i = fromIndex, j = this.length; i < j; i++) {
 46.1869 +    if (this[i][name] === item) return i;
 46.1870 +  }
 46.1871 +  return -1;
 46.1872 +};
 46.1873 +
 46.1874 +/**
 46.1875 + * Borrowed from jquery.base64.js, with some "Array as input" corrections
 46.1876 + *
 46.1877 + * @private
 46.1878 + * @param {Array of charCodes} input An array of byte ASCII codes (0-255).
 46.1879 + * @return {String} A base64-encoded string.
 46.1880 + * @author Brendan Byrd
 46.1881 + */
 46.1882 +var base64Encode = function(input) {
 46.1883 +  var keyString = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
 46.1884 +  var output = "";
 46.1885 +  var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
 46.1886 +  var i = 0;
 46.1887 +  while (i < input.length) {
 46.1888 +    chr1 = input[i++];
 46.1889 +    chr2 = input[i++];
 46.1890 +    chr3 = input[i++];
 46.1891 +    enc1 = chr1 >> 2;
 46.1892 +    enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
 46.1893 +    enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
 46.1894 +    enc4 = chr3 & 63;
 46.1895 +
 46.1896 +    if      (chr2 == undefined) enc3 = enc4 = 64;
 46.1897 +    else if (chr3 == undefined) enc4 = 64;
 46.1898 +
 46.1899 +    output = output + keyString.charAt(enc1) + keyString.charAt(enc2) + keyString.charAt(enc3) + keyString.charAt(enc4);
 46.1900 +  }
 46.1901 +  return output;
 46.1902 +};
    47.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    47.2 +++ b/endpoint/WebContent/js/jquery-1.8.0.min.js	Fri May 02 17:39:27 2014 +0200
    47.3 @@ -0,0 +1,2 @@
    47.4 +/*! jQuery v@1.8.0 jquery.com | jquery.org/license */
    47.5 +(function(a,b){function G(a){var b=F[a]={};return p.each(a.split(s),function(a,c){b[c]=!0}),b}function J(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(I,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:+d+""===d?+d:H.test(d)?p.parseJSON(d):d}catch(f){}p.data(a,c,d)}else d=b}return d}function K(a){var b;for(b in a){if(b==="data"&&p.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function ba(){return!1}function bb(){return!0}function bh(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function bi(a,b){do a=a[b];while(a&&a.nodeType!==1);return a}function bj(a,b,c){b=b||0;if(p.isFunction(b))return p.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return p.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=p.grep(a,function(a){return a.nodeType===1});if(be.test(b))return p.filter(b,d,!c);b=p.filter(b,d)}return p.grep(a,function(a,d){return p.inArray(a,b)>=0===c})}function bk(a){var b=bl.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function bC(a,b){return a.getElementsByTagName(b)[0]||a.appendChild(a.ownerDocument.createElement(b))}function bD(a,b){if(b.nodeType!==1||!p.hasData(a))return;var c,d,e,f=p._data(a),g=p._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;d<e;d++)p.event.add(b,c,h[c][d])}g.data&&(g.data=p.extend({},g.data))}function bE(a,b){var c;if(b.nodeType!==1)return;b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase(),c==="object"?(b.parentNode&&(b.outerHTML=a.outerHTML),p.support.html5Clone&&a.innerHTML&&!p.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):c==="input"&&bv.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):c==="option"?b.selected=a.defaultSelected:c==="input"||c==="textarea"?b.defaultValue=a.defaultValue:c==="script"&&b.text!==a.text&&(b.text=a.text),b.removeAttribute(p.expando)}function bF(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bG(a){bv.test(a.type)&&(a.defaultChecked=a.checked)}function bX(a,b){if(b in a)return b;var c=b.charAt(0).toUpperCase()+b.slice(1),d=b,e=bV.length;while(e--){b=bV[e]+c;if(b in a)return b}return d}function bY(a,b){return a=b||a,p.css(a,"display")==="none"||!p.contains(a.ownerDocument,a)}function bZ(a,b){var c,d,e=[],f=0,g=a.length;for(;f<g;f++){c=a[f];if(!c.style)continue;e[f]=p._data(c,"olddisplay"),b?(!e[f]&&c.style.display==="none"&&(c.style.display=""),c.style.display===""&&bY(c)&&(e[f]=p._data(c,"olddisplay",cb(c.nodeName)))):(d=bH(c,"display"),!e[f]&&d!=="none"&&p._data(c,"olddisplay",d))}for(f=0;f<g;f++){c=a[f];if(!c.style)continue;if(!b||c.style.display==="none"||c.style.display==="")c.style.display=b?e[f]||"":"none"}return a}function b$(a,b,c){var d=bO.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function b_(a,b,c,d){var e=c===(d?"border":"content")?4:b==="width"?1:0,f=0;for(;e<4;e+=2)c==="margin"&&(f+=p.css(a,c+bU[e],!0)),d?(c==="content"&&(f-=parseFloat(bH(a,"padding"+bU[e]))||0),c!=="margin"&&(f-=parseFloat(bH(a,"border"+bU[e]+"Width"))||0)):(f+=parseFloat(bH(a,"padding"+bU[e]))||0,c!=="padding"&&(f+=parseFloat(bH(a,"border"+bU[e]+"Width"))||0));return f}function ca(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=!0,f=p.support.boxSizing&&p.css(a,"boxSizing")==="border-box";if(d<=0){d=bH(a,b);if(d<0||d==null)d=a.style[b];if(bP.test(d))return d;e=f&&(p.support.boxSizingReliable||d===a.style[b]),d=parseFloat(d)||0}return d+b_(a,b,c||(f?"border":"content"),e)+"px"}function cb(a){if(bR[a])return bR[a];var b=p("<"+a+">").appendTo(e.body),c=b.css("display");b.remove();if(c==="none"||c===""){bI=e.body.appendChild(bI||p.extend(e.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!bJ||!bI.createElement)bJ=(bI.contentWindow||bI.contentDocument).document,bJ.write("<!doctype html><html><body>"),bJ.close();b=bJ.body.appendChild(bJ.createElement(a)),c=bH(b,"display"),e.body.removeChild(bI)}return bR[a]=c,c}function ch(a,b,c,d){var e;if(p.isArray(b))p.each(b,function(b,e){c||cd.test(a)?d(a,e):ch(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&p.type(b)==="object")for(e in b)ch(a+"["+e+"]",b[e],c,d);else d(a,b)}function cy(a){return function(b,c){typeof b!="string"&&(c=b,b="*");var d,e,f,g=b.toLowerCase().split(s),h=0,i=g.length;if(p.isFunction(c))for(;h<i;h++)d=g[h],f=/^\+/.test(d),f&&(d=d.substr(1)||"*"),e=a[d]=a[d]||[],e[f?"unshift":"push"](c)}}function cz(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h,i=a[f],j=0,k=i?i.length:0,l=a===cu;for(;j<k&&(l||!h);j++)h=i[j](c,d,e),typeof h=="string"&&(!l||g[h]?h=b:(c.dataTypes.unshift(h),h=cz(a,c,d,e,h,g)));return(l||!h)&&!g["*"]&&(h=cz(a,c,d,e,"*",g)),h}function cA(a,c){var d,e,f=p.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((f[d]?a:e||(e={}))[d]=c[d]);e&&p.extend(!0,a,e)}function cB(a,c,d){var e,f,g,h,i=a.contents,j=a.dataTypes,k=a.responseFields;for(f in k)f in d&&(c[k[f]]=d[f]);while(j[0]==="*")j.shift(),e===b&&(e=a.mimeType||c.getResponseHeader("content-type"));if(e)for(f in i)if(i[f]&&i[f].test(e)){j.unshift(f);break}if(j[0]in d)g=j[0];else{for(f in d){if(!j[0]||a.converters[f+" "+j[0]]){g=f;break}h||(h=f)}g=g||h}if(g)return g!==j[0]&&j.unshift(g),d[g]}function cC(a,b){var c,d,e,f,g=a.dataTypes.slice(),h=g[0],i={},j=0;a.dataFilter&&(b=a.dataFilter(b,a.dataType));if(g[1])for(c in a.converters)i[c.toLowerCase()]=a.converters[c];for(;e=g[++j];)if(e!=="*"){if(h!=="*"&&h!==e){c=i[h+" "+e]||i["* "+e];if(!c)for(d in i){f=d.split(" ");if(f[1]===e){c=i[h+" "+f[0]]||i["* "+f[0]];if(c){c===!0?c=i[d]:i[d]!==!0&&(e=f[0],g.splice(j--,0,e));break}}}if(c!==!0)if(c&&a["throws"])b=c(b);else try{b=c(b)}catch(k){return{state:"parsererror",error:c?k:"No conversion from "+h+" to "+e}}}h=e}return{state:"success",data:b}}function cK(){try{return new a.XMLHttpRequest}catch(b){}}function cL(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function cT(){return setTimeout(function(){cM=b},0),cM=p.now()}function cU(a,b){p.each(b,function(b,c){var d=(cS[b]||[]).concat(cS["*"]),e=0,f=d.length;for(;e<f;e++)if(d[e].call(a,b,c))return})}function cV(a,b,c){var d,e=0,f=0,g=cR.length,h=p.Deferred().always(function(){delete i.elem}),i=function(){var b=cM||cT(),c=Math.max(0,j.startTime+j.duration-b),d=1-(c/j.duration||0),e=0,f=j.tweens.length;for(;e<f;e++)j.tweens[e].run(d);return h.notifyWith(a,[j,d,c]),d<1&&f?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:p.extend({},b),opts:p.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:cM||cT(),duration:c.duration,tweens:[],createTween:function(b,c,d){var e=p.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(e),e},stop:function(b){var c=0,d=b?j.tweens.length:0;for(;c<d;c++)j.tweens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;cW(k,j.opts.specialEasing);for(;e<g;e++){d=cR[e].call(j,a,k,j.opts);if(d)return d}return cU(j,k),p.isFunction(j.opts.start)&&j.opts.start.call(a,j),p.fx.timer(p.extend(i,{anim:j,queue:j.opts.queue,elem:a})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}function cW(a,b){var c,d,e,f,g;for(c in a){d=p.camelCase(c),e=b[d],f=a[c],p.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=p.cssHooks[d];if(g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}}function cX(a,b,c){var d,e,f,g,h,i,j,k,l=this,m=a.style,n={},o=[],q=a.nodeType&&bY(a);c.queue||(j=p._queueHooks(a,"fx"),j.unqueued==null&&(j.unqueued=0,k=j.empty.fire,j.empty.fire=function(){j.unqueued||k()}),j.unqueued++,l.always(function(){l.always(function(){j.unqueued--,p.queue(a,"fx").length||j.empty.fire()})})),a.nodeType===1&&("height"in b||"width"in b)&&(c.overflow=[m.overflow,m.overflowX,m.overflowY],p.css(a,"display")==="inline"&&p.css(a,"float")==="none"&&(!p.support.inlineBlockNeedsLayout||cb(a.nodeName)==="inline"?m.display="inline-block":m.zoom=1)),c.overflow&&(m.overflow="hidden",p.support.shrinkWrapBlocks||l.done(function(){m.overflow=c.overflow[0],m.overflowX=c.overflow[1],m.overflowY=c.overflow[2]}));for(d in b){f=b[d];if(cO.exec(f)){delete b[d];if(f===(q?"hide":"show"))continue;o.push(d)}}g=o.length;if(g){h=p._data(a,"fxshow")||p._data(a,"fxshow",{}),q?p(a).show():l.done(function(){p(a).hide()}),l.done(function(){var b;p.removeData(a,"fxshow",!0);for(b in n)p.style(a,b,n[b])});for(d=0;d<g;d++)e=o[d],i=l.createTween(e,q?h[e]:0),n[e]=h[e]||p.style(a,e),e in h||(h[e]=i.start,q&&(i.end=i.start,i.start=e==="width"||e==="height"?1:0))}}function cY(a,b,c,d,e){return new cY.prototype.init(a,b,c,d,e)}function cZ(a,b){var c,d={height:a},e=0;for(;e<4;e+=2-b)c=bU[e],d["margin"+c]=d["padding"+c]=a;return b&&(d.opacity=d.width=a),d}function c_(a){return p.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}var c,d,e=a.document,f=a.location,g=a.navigator,h=a.jQuery,i=a.$,j=Array.prototype.push,k=Array.prototype.slice,l=Array.prototype.indexOf,m=Object.prototype.toString,n=Object.prototype.hasOwnProperty,o=String.prototype.trim,p=function(a,b){return new p.fn.init(a,b,c)},q=/[\-+]?(?:\d*\.|)\d+(?:[eE][\-+]?\d+|)/.source,r=/\S/,s=/\s+/,t=r.test(" ")?/^[\s\xA0]+|[\s\xA0]+$/g:/^\s+|\s+$/g,u=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,y=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,z=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,A=/^-ms-/,B=/-([\da-z])/gi,C=function(a,b){return(b+"").toUpperCase()},D=function(){e.addEventListener?(e.removeEventListener("DOMContentLoaded",D,!1),p.ready()):e.readyState==="complete"&&(e.detachEvent("onreadystatechange",D),p.ready())},E={};p.fn=p.prototype={constructor:p,init:function(a,c,d){var f,g,h,i;if(!a)return this;if(a.nodeType)return this.context=this[0]=a,this.length=1,this;if(typeof a=="string"){a.charAt(0)==="<"&&a.charAt(a.length-1)===">"&&a.length>=3?f=[null,a,null]:f=u.exec(a);if(f&&(f[1]||!c)){if(f[1])return c=c instanceof p?c[0]:c,i=c&&c.nodeType?c.ownerDocument||c:e,a=p.parseHTML(f[1],i,!0),v.test(f[1])&&p.isPlainObject(c)&&this.attr.call(a,c,!0),p.merge(this,a);g=e.getElementById(f[2]);if(g&&g.parentNode){if(g.id!==f[2])return d.find(a);this.length=1,this[0]=g}return this.context=e,this.selector=a,this}return!c||c.jquery?(c||d).find(a):this.constructor(c).find(a)}return p.isFunction(a)?d.ready(a):(a.selector!==b&&(this.selector=a.selector,this.context=a.context),p.makeArray(a,this))},selector:"",jquery:"1.8.0",length:0,size:function(){return this.length},toArray:function(){return k.call(this)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=p.merge(this.constructor(),a);return d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")"),d},each:function(a,b){return p.each(this,a,b)},ready:function(a){return p.ready.promise().done(a),this},eq:function(a){return a=+a,a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(k.apply(this,arguments),"slice",k.call(arguments).join(","))},map:function(a){return this.pushStack(p.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:j,sort:[].sort,splice:[].splice},p.fn.init.prototype=p.fn,p.extend=p.fn.extend=function(){var a,c,d,e,f,g,h=arguments[0]||{},i=1,j=arguments.length,k=!1;typeof h=="boolean"&&(k=h,h=arguments[1]||{},i=2),typeof h!="object"&&!p.isFunction(h)&&(h={}),j===i&&(h=this,--i);for(;i<j;i++)if((a=arguments[i])!=null)for(c in a){d=h[c],e=a[c];if(h===e)continue;k&&e&&(p.isPlainObject(e)||(f=p.isArray(e)))?(f?(f=!1,g=d&&p.isArray(d)?d:[]):g=d&&p.isPlainObject(d)?d:{},h[c]=p.extend(k,g,e)):e!==b&&(h[c]=e)}return h},p.extend({noConflict:function(b){return a.$===p&&(a.$=i),b&&a.jQuery===p&&(a.jQuery=h),p},isReady:!1,readyWait:1,holdReady:function(a){a?p.readyWait++:p.ready(!0)},ready:function(a){if(a===!0?--p.readyWait:p.isReady)return;if(!e.body)return setTimeout(p.ready,1);p.isReady=!0;if(a!==!0&&--p.readyWait>0)return;d.resolveWith(e,[p]),p.fn.trigger&&p(e).trigger("ready").off("ready")},isFunction:function(a){return p.type(a)==="function"},isArray:Array.isArray||function(a){return p.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):E[m.call(a)]||"object"},isPlainObject:function(a){if(!a||p.type(a)!=="object"||a.nodeType||p.isWindow(a))return!1;try{if(a.constructor&&!n.call(a,"constructor")&&!n.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||n.call(a,d)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},error:function(a){throw new Error(a)},parseHTML:function(a,b,c){var d;return!a||typeof a!="string"?null:(typeof b=="boolean"&&(c=b,b=0),b=b||e,(d=v.exec(a))?[b.createElement(d[1])]:(d=p.buildFragment([a],b,c?null:[]),p.merge([],(d.cacheable?p.clone(d.fragment):d.fragment).childNodes)))},parseJSON:function(b){if(!b||typeof b!="string")return null;b=p.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(w.test(b.replace(y,"@").replace(z,"]").replace(x,"")))return(new Function("return "+b))();p.error("Invalid JSON: "+b)},parseXML:function(c){var d,e;if(!c||typeof c!="string")return null;try{a.DOMParser?(e=new DOMParser,d=e.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(f){d=b}return(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&p.error("Invalid XML: "+c),d},noop:function(){},globalEval:function(b){b&&r.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(A,"ms-").replace(B,C)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var e,f=0,g=a.length,h=g===b||p.isFunction(a);if(d){if(h){for(e in a)if(c.apply(a[e],d)===!1)break}else for(;f<g;)if(c.apply(a[f++],d)===!1)break}else if(h){for(e in a)if(c.call(a[e],e,a[e])===!1)break}else for(;f<g;)if(c.call(a[f],f,a[f++])===!1)break;return a},trim:o?function(a){return a==null?"":o.call(a)}:function(a){return a==null?"":a.toString().replace(t,"")},makeArray:function(a,b){var c,d=b||[];return a!=null&&(c=p.type(a),a.length==null||c==="string"||c==="function"||c==="regexp"||p.isWindow(a)?j.call(d,a):p.merge(d,a)),d},inArray:function(a,b,c){var d;if(b){if(l)return l.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=c.length,e=a.length,f=0;if(typeof d=="number")for(;f<d;f++)a[e++]=c[f];else while(c[f]!==b)a[e++]=c[f++];return a.length=e,a},grep:function(a,b,c){var d,e=[],f=0,g=a.length;c=!!c;for(;f<g;f++)d=!!b(a[f],f),c!==d&&e.push(a[f]);return e},map:function(a,c,d){var e,f,g=[],h=0,i=a.length,j=a instanceof p||i!==b&&typeof i=="number"&&(i>0&&a[0]&&a[i-1]||i===0||p.isArray(a));if(j)for(;h<i;h++)e=c(a[h],h,d),e!=null&&(g[g.length]=e);else for(f in a)e=c(a[f],f,d),e!=null&&(g[g.length]=e);return g.concat.apply([],g)},guid:1,proxy:function(a,c){var d,e,f;return typeof c=="string"&&(d=a[c],c=a,a=d),p.isFunction(a)?(e=k.call(arguments,2),f=function(){return a.apply(c,e.concat(k.call(arguments)))},f.guid=a.guid=a.guid||f.guid||p.guid++,f):b},access:function(a,c,d,e,f,g,h){var i,j=d==null,k=0,l=a.length;if(d&&typeof d=="object"){for(k in d)p.access(a,c,k,d[k],1,g,e);f=1}else if(e!==b){i=h===b&&p.isFunction(e),j&&(i?(i=c,c=function(a,b,c){return i.call(p(a),c)}):(c.call(a,e),c=null));if(c)for(;k<l;k++)c(a[k],d,i?e.call(a[k],k,c(a[k],d)):e,h);f=1}return f?a:j?c.call(a):l?c(a[0],d):g},now:function(){return(new Date).getTime()}}),p.ready.promise=function(b){if(!d){d=p.Deferred();if(e.readyState==="complete"||e.readyState!=="loading"&&e.addEventListener)setTimeout(p.ready,1);else if(e.addEventListener)e.addEventListener("DOMContentLoaded",D,!1),a.addEventListener("load",p.ready,!1);else{e.attachEvent("onreadystatechange",D),a.attachEvent("onload",p.ready);var c=!1;try{c=a.frameElement==null&&e.documentElement}catch(f){}c&&c.doScroll&&function g(){if(!p.isReady){try{c.doScroll("left")}catch(a){return setTimeout(g,50)}p.ready()}}()}}return d.promise(b)},p.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){E["[object "+b+"]"]=b.toLowerCase()}),c=p(e);var F={};p.Callbacks=function(a){a=typeof a=="string"?F[a]||G(a):p.extend({},a);var c,d,e,f,g,h,i=[],j=!a.once&&[],k=function(b){c=a.memory&&b,d=!0,h=f||0,f=0,g=i.length,e=!0;for(;i&&h<g;h++)if(i[h].apply(b[0],b[1])===!1&&a.stopOnFalse){c=!1;break}e=!1,i&&(j?j.length&&k(j.shift()):c?i=[]:l.disable())},l={add:function(){if(i){var b=i.length;(function d(b){p.each(b,function(b,c){p.isFunction(c)&&(!a.unique||!l.has(c))?i.push(c):c&&c.length&&d(c)})})(arguments),e?g=i.length:c&&(f=b,k(c))}return this},remove:function(){return i&&p.each(arguments,function(a,b){var c;while((c=p.inArray(b,i,c))>-1)i.splice(c,1),e&&(c<=g&&g--,c<=h&&h--)}),this},has:function(a){return p.inArray(a,i)>-1},empty:function(){return i=[],this},disable:function(){return i=j=c=b,this},disabled:function(){return!i},lock:function(){return j=b,c||l.disable(),this},locked:function(){return!j},fireWith:function(a,b){return b=b||[],b=[a,b.slice?b.slice():b],i&&(!d||j)&&(e?j.push(b):k(b)),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!d}};return l},p.extend({Deferred:function(a){var b=[["resolve","done",p.Callbacks("once memory"),"resolved"],["reject","fail",p.Callbacks("once memory"),"rejected"],["notify","progress",p.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return p.Deferred(function(c){p.each(b,function(b,d){var f=d[0],g=a[b];e[d[1]](p.isFunction(g)?function(){var a=g.apply(this,arguments);a&&p.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f+"With"](this===e?c:this,[a])}:c[f])}),a=null}).promise()},promise:function(a){return typeof a=="object"?p.extend(a,d):d}},e={};return d.pipe=d.then,p.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[a^1][2].disable,b[2][2].lock),e[f[0]]=g.fire,e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=k.call(arguments),d=c.length,e=d!==1||a&&p.isFunction(a.promise)?d:0,f=e===1?a:p.Deferred(),g=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?k.call(arguments):d,c===h?f.notifyWith(b,c):--e||f.resolveWith(b,c)}},h,i,j;if(d>1){h=new Array(d),i=new Array(d),j=new Array(d);for(;b<d;b++)c[b]&&p.isFunction(c[b].promise)?c[b].promise().done(g(b,j,c)).fail(f.reject).progress(g(b,i,h)):--e}return e||f.resolveWith(j,c),f.promise()}}),p.support=function(){var b,c,d,f,g,h,i,j,k,l,m,n=e.createElement("div");n.setAttribute("className","t"),n.innerHTML="  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",c=n.getElementsByTagName("*"),d=n.getElementsByTagName("a")[0],d.style.cssText="top:1px;float:left;opacity:.5";if(!c||!c.length||!d)return{};f=e.createElement("select"),g=f.appendChild(e.createElement("option")),h=n.getElementsByTagName("input")[0],b={leadingWhitespace:n.firstChild.nodeType===3,tbody:!n.getElementsByTagName("tbody").length,htmlSerialize:!!n.getElementsByTagName("link").length,style:/top/.test(d.getAttribute("style")),hrefNormalized:d.getAttribute("href")==="/a",opacity:/^0.5/.test(d.style.opacity),cssFloat:!!d.style.cssFloat,checkOn:h.value==="on",optSelected:g.selected,getSetAttribute:n.className!=="t",enctype:!!e.createElement("form").enctype,html5Clone:e.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",boxModel:e.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},h.checked=!0,b.noCloneChecked=h.cloneNode(!0).checked,f.disabled=!0,b.optDisabled=!g.disabled;try{delete n.test}catch(o){b.deleteExpando=!1}!n.addEventListener&&n.attachEvent&&n.fireEvent&&(n.attachEvent("onclick",m=function(){b.noCloneEvent=!1}),n.cloneNode(!0).fireEvent("onclick"),n.detachEvent("onclick",m)),h=e.createElement("input"),h.value="t",h.setAttribute("type","radio"),b.radioValue=h.value==="t",h.setAttribute("checked","checked"),h.setAttribute("name","t"),n.appendChild(h),i=e.createDocumentFragment(),i.appendChild(n.lastChild),b.checkClone=i.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=h.checked,i.removeChild(h),i.appendChild(n);if(n.attachEvent)for(k in{submit:!0,change:!0,focusin:!0})j="on"+k,l=j in n,l||(n.setAttribute(j,"return;"),l=typeof n[j]=="function"),b[k+"Bubbles"]=l;return p(function(){var c,d,f,g,h="padding:0;margin:0;border:0;display:block;overflow:hidden;",i=e.getElementsByTagName("body")[0];if(!i)return;c=e.createElement("div"),c.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",i.insertBefore(c,i.firstChild),d=e.createElement("div"),c.appendChild(d),d.innerHTML="<table><tr><td></td><td>t</td></tr></table>",f=d.getElementsByTagName("td"),f[0].style.cssText="padding:0;margin:0;border:0;display:none",l=f[0].offsetHeight===0,f[0].style.display="",f[1].style.display="none",b.reliableHiddenOffsets=l&&f[0].offsetHeight===0,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",b.boxSizing=d.offsetWidth===4,b.doesNotIncludeMarginInBodyOffset=i.offsetTop!==1,a.getComputedStyle&&(b.pixelPosition=(a.getComputedStyle(d,null)||{}).top!=="1%",b.boxSizingReliable=(a.getComputedStyle(d,null)||{width:"4px"}).width==="4px",g=e.createElement("div"),g.style.cssText=d.style.cssText=h,g.style.marginRight=g.style.width="0",d.style.width="1px",d.appendChild(g),b.reliableMarginRight=!parseFloat((a.getComputedStyle(g,null)||{}).marginRight)),typeof d.style.zoom!="undefined"&&(d.innerHTML="",d.style.cssText=h+"width:1px;padding:1px;display:inline;zoom:1",b.inlineBlockNeedsLayout=d.offsetWidth===3,d.style.display="block",d.style.overflow="visible",d.innerHTML="<div></div>",d.firstChild.style.width="5px",b.shrinkWrapBlocks=d.offsetWidth!==3,c.style.zoom=1),i.removeChild(c),c=d=f=g=null}),i.removeChild(n),c=d=f=g=h=i=n=null,b}();var H=/^(?:\{.*\}|\[.*\])$/,I=/([A-Z])/g;p.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(p.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){return a=a.nodeType?p.cache[a[p.expando]]:a[p.expando],!!a&&!K(a)},data:function(a,c,d,e){if(!p.acceptData(a))return;var f,g,h=p.expando,i=typeof c=="string",j=a.nodeType,k=j?p.cache:a,l=j?a[h]:a[h]&&h;if((!l||!k[l]||!e&&!k[l].data)&&i&&d===b)return;l||(j?a[h]=l=p.deletedIds.pop()||++p.uuid:l=h),k[l]||(k[l]={},j||(k[l].toJSON=p.noop));if(typeof c=="object"||typeof c=="function")e?k[l]=p.extend(k[l],c):k[l].data=p.extend(k[l].data,c);return f=k[l],e||(f.data||(f.data={}),f=f.data),d!==b&&(f[p.camelCase(c)]=d),i?(g=f[c],g==null&&(g=f[p.camelCase(c)])):g=f,g},removeData:function(a,b,c){if(!p.acceptData(a))return;var d,e,f,g=a.nodeType,h=g?p.cache:a,i=g?a[p.expando]:p.expando;if(!h[i])return;if(b){d=c?h[i]:h[i].data;if(d){p.isArray(b)||(b in d?b=[b]:(b=p.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,f=b.length;e<f;e++)delete d[b[e]];if(!(c?K:p.isEmptyObject)(d))return}}if(!c){delete h[i].data;if(!K(h[i]))return}g?p.cleanData([a],!0):p.support.deleteExpando||h!=h.window?delete h[i]:h[i]=null},_data:function(a,b,c){return p.data(a,b,c,!0)},acceptData:function(a){var b=a.nodeName&&p.noData[a.nodeName.toLowerCase()];return!b||b!==!0&&a.getAttribute("classid")===b}}),p.fn.extend({data:function(a,c){var d,e,f,g,h,i=this[0],j=0,k=null;if(a===b){if(this.length){k=p.data(i);if(i.nodeType===1&&!p._data(i,"parsedAttrs")){f=i.attributes;for(h=f.length;j<h;j++)g=f[j].name,g.indexOf("data-")===0&&(g=p.camelCase(g.substring(5)),J(i,g,k[g]));p._data(i,"parsedAttrs",!0)}}return k}return typeof a=="object"?this.each(function(){p.data(this,a)}):(d=a.split(".",2),d[1]=d[1]?"."+d[1]:"",e=d[1]+"!",p.access(this,function(c){if(c===b)return k=this.triggerHandler("getData"+e,[d[0]]),k===b&&i&&(k=p.data(i,a),k=J(i,a,k)),k===b&&d[1]?this.data(d[0]):k;d[1]=c,this.each(function(){var b=p(this);b.triggerHandler("setData"+e,d),p.data(this,a,c),b.triggerHandler("changeData"+e,d)})},null,c,arguments.length>1,null,!1))},removeData:function(a){return this.each(function(){p.removeData(this,a)})}}),p.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=p._data(a,b),c&&(!d||p.isArray(c)?d=p._data(a,b,p.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=p.queue(a,b),d=c.shift(),e=p._queueHooks(a,b),f=function(){p.dequeue(a,b)};d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),delete e.stop,d.call(a,f,e)),!c.length&&e&&e.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return p._data(a,c)||p._data(a,c,{empty:p.Callbacks("once memory").add(function(){p.removeData(a,b+"queue",!0),p.removeData(a,c,!0)})})}}),p.fn.extend({queue:function(a,c){var d=2;return typeof a!="string"&&(c=a,a="fx",d--),arguments.length<d?p.queue(this[0],a):c===b?this:this.each(function(){var b=p.queue(this,a,c);p._queueHooks(this,a),a==="fx"&&b[0]!=="inprogress"&&p.dequeue(this,a)})},dequeue:function(a){return this.each(function(){p.dequeue(this,a)})},delay:function(a,b){return a=p.fx?p.fx.speeds[a]||a:a,b=b||"fx",this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){var d,e=1,f=p.Deferred(),g=this,h=this.length,i=function(){--e||f.resolveWith(g,[g])};typeof a!="string"&&(c=a,a=b),a=a||"fx";while(h--)(d=p._data(g[h],a+"queueHooks"))&&d.empty&&(e++,d.empty.add(i));return i(),f.promise(c)}});var L,M,N,O=/[\t\r\n]/g,P=/\r/g,Q=/^(?:button|input)$/i,R=/^(?:button|input|object|select|textarea)$/i,S=/^a(?:rea|)$/i,T=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,U=p.support.getSetAttribute;p.fn.extend({attr:function(a,b){return p.access(this,p.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){p.removeAttr(this,a)})},prop:function(a,b){return p.access(this,p.prop,a,b,arguments.length>1)},removeProp:function(a){return a=p.propFix[a]||a,this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,f,g,h;if(p.isFunction(a))return this.each(function(b){p(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(s);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{f=" "+e.className+" ";for(g=0,h=b.length;g<h;g++)~f.indexOf(" "+b[g]+" ")||(f+=b[g]+" ");e.className=p.trim(f)}}}return this},removeClass:function(a){var c,d,e,f,g,h,i;if(p.isFunction(a))return this.each(function(b){p(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(s);for(h=0,i=this.length;h<i;h++){e=this[h];if(e.nodeType===1&&e.className){d=(" "+e.className+" ").replace(O," ");for(f=0,g=c.length;f<g;f++)while(d.indexOf(" "+c[f]+" ")>-1)d=d.replace(" "+c[f]+" "," ");e.className=a?p.trim(d):""}}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";return p.isFunction(a)?this.each(function(c){p(this).toggleClass(a.call(this,c,this.className,b),b)}):this.each(function(){if(c==="string"){var e,f=0,g=p(this),h=b,i=a.split(s);while(e=i[f++])h=d?h:!g.hasClass(e),g[h?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&p._data(this,"__className__",this.className),this.className=this.className||a===!1?"":p._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(O," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e,f=this[0];if(!arguments.length){if(f)return c=p.valHooks[f.type]||p.valHooks[f.nodeName.toLowerCase()],c&&"get"in c&&(d=c.get(f,"value"))!==b?d:(d=f.value,typeof d=="string"?d.replace(P,""):d==null?"":d);return}return e=p.isFunction(a),this.each(function(d){var f,g=p(this);if(this.nodeType!==1)return;e?f=a.call(this,d,g.val()):f=a,f==null?f="":typeof f=="number"?f+="":p.isArray(f)&&(f=p.map(f,function(a){return a==null?"":a+""})),c=p.valHooks[this.type]||p.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,f,"value")===b)this.value=f})}}),p.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,f=a.selectedIndex,g=[],h=a.options,i=a.type==="select-one";if(f<0)return null;c=i?f:0,d=i?f+1:h.length;for(;c<d;c++){e=h[c];if(e.selected&&(p.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!p.nodeName(e.parentNode,"optgroup"))){b=p(e).val();if(i)return b;g.push(b)}}return i&&!g.length&&h.length?p(h[f]).val():g},set:function(a,b){var c=p.makeArray(b);return p(a).find("option").each(function(){this.selected=p.inArray(p(this).val(),c)>=0}),c.length||(a.selectedIndex=-1),c}}},attrFn:{},attr:function(a,c,d,e){var f,g,h,i=a.nodeType;if(!a||i===3||i===8||i===2)return;if(e&&p.isFunction(p.fn[c]))return p(a)[c](d);if(typeof a.getAttribute=="undefined")return p.prop(a,c,d);h=i!==1||!p.isXMLDoc(a),h&&(c=c.toLowerCase(),g=p.attrHooks[c]||(T.test(c)?M:L));if(d!==b){if(d===null){p.removeAttr(a,c);return}return g&&"set"in g&&h&&(f=g.set(a,d,c))!==b?f:(a.setAttribute(c,""+d),d)}return g&&"get"in g&&h&&(f=g.get(a,c))!==null?f:(f=a.getAttribute(c),f===null?b:f)},removeAttr:function(a,b){var c,d,e,f,g=0;if(b&&a.nodeType===1){d=b.split(s);for(;g<d.length;g++)e=d[g],e&&(c=p.propFix[e]||e,f=T.test(e),f||p.attr(a,e,""),a.removeAttribute(U?e:c),f&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(Q.test(a.nodeName)&&a.parentNode)p.error("type property can't be changed");else if(!p.support.radioValue&&b==="radio"&&p.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}},value:{get:function(a,b){return L&&p.nodeName(a,"button")?L.get(a,b):b in a?a.value:null},set:function(a,b,c){if(L&&p.nodeName(a,"button"))return L.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,f,g,h=a.nodeType;if(!a||h===3||h===8||h===2)return;return g=h!==1||!p.isXMLDoc(a),g&&(c=p.propFix[c]||c,f=p.propHooks[c]),d!==b?f&&"set"in f&&(e=f.set(a,d,c))!==b?e:a[c]=d:f&&"get"in f&&(e=f.get(a,c))!==null?e:a[c]},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):R.test(a.nodeName)||S.test(a.nodeName)&&a.href?0:b}}}}),M={get:function(a,c){var d,e=p.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;return b===!1?p.removeAttr(a,c):(d=p.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase())),c}},U||(N={name:!0,id:!0,coords:!0},L=p.valHooks.button={get:function(a,c){var d;return d=a.getAttributeNode(c),d&&(N[c]?d.value!=="":d.specified)?d.value:b},set:function(a,b,c){var d=a.getAttributeNode(c);return d||(d=e.createAttribute(c),a.setAttributeNode(d)),d.value=b+""}},p.each(["width","height"],function(a,b){p.attrHooks[b]=p.extend(p.attrHooks[b],{set:function(a,c){if(c==="")return a.setAttribute(b,"auto"),c}})}),p.attrHooks.contenteditable={get:L.get,set:function(a,b,c){b===""&&(b="false"),L.set(a,b,c)}}),p.support.hrefNormalized||p.each(["href","src","width","height"],function(a,c){p.attrHooks[c]=p.extend(p.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),p.support.style||(p.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),p.support.optSelected||(p.propHooks.selected=p.extend(p.propHooks.selected,{get:function(a){var b=a.parentNode;return b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex),null}})),p.support.enctype||(p.propFix.enctype="encoding"),p.support.checkOn||p.each(["radio","checkbox"],function(){p.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),p.each(["radio","checkbox"],function(){p.valHooks[this]=p.extend(p.valHooks[this],{set:function(a,b){if(p.isArray(b))return a.checked=p.inArray(p(a).val(),b)>=0}})});var V=/^(?:textarea|input|select)$/i,W=/^([^\.]*|)(?:\.(.+)|)$/,X=/(?:^|\s)hover(\.\S+|)\b/,Y=/^key/,Z=/^(?:mouse|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=function(a){return p.event.special.hover?a:a.replace(X,"mouseenter$1 mouseleave$1")};p.event={add:function(a,c,d,e,f){var g,h,i,j,k,l,m,n,o,q,r;if(a.nodeType===3||a.nodeType===8||!c||!d||!(g=p._data(a)))return;d.handler&&(o=d,d=o.handler,f=o.selector),d.guid||(d.guid=p.guid++),i=g.events,i||(g.events=i={}),h=g.handle,h||(g.handle=h=function(a){return typeof p!="undefined"&&(!a||p.event.triggered!==a.type)?p.event.dispatch.apply(h.elem,arguments):b},h.elem=a),c=p.trim(_(c)).split(" ");for(j=0;j<c.length;j++){k=W.exec(c[j])||[],l=k[1],m=(k[2]||"").split(".").sort(),r=p.event.special[l]||{},l=(f?r.delegateType:r.bindType)||l,r=p.event.special[l]||{},n=p.extend({type:l,origType:k[1],data:e,handler:d,guid:d.guid,selector:f,namespace:m.join(".")},o),q=i[l];if(!q){q=i[l]=[],q.delegateCount=0;if(!r.setup||r.setup.call(a,e,m,h)===!1)a.addEventListener?a.addEventListener(l,h,!1):a.attachEvent&&a.attachEvent("on"+l,h)}r.add&&(r.add.call(a,n),n.handler.guid||(n.handler.guid=d.guid)),f?q.splice(q.delegateCount++,0,n):q.push(n),p.event.global[l]=!0}a=null},global:{},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,q,r=p.hasData(a)&&p._data(a);if(!r||!(m=r.events))return;b=p.trim(_(b||"")).split(" ");for(f=0;f<b.length;f++){g=W.exec(b[f])||[],h=i=g[1],j=g[2];if(!h){for(h in m)p.event.remove(a,h+b[f],c,d,!0);continue}n=p.event.special[h]||{},h=(d?n.delegateType:n.bindType)||h,o=m[h]||[],k=o.length,j=j?new RegExp("(^|\\.)"+j.split(".").sort().join("\\.(?:.*\\.|)")+"(\\.|$)"):null;for(l=0;l<o.length;l++)q=o[l],(e||i===q.origType)&&(!c||c.guid===q.guid)&&(!j||j.test(q.namespace))&&(!d||d===q.selector||d==="**"&&q.selector)&&(o.splice(l--,1),q.selector&&o.delegateCount--,n.remove&&n.remove.call(a,q));o.length===0&&k!==o.length&&((!n.teardown||n.teardown.call(a,j,r.handle)===!1)&&p.removeEvent(a,h,r.handle),delete m[h])}p.isEmptyObject(m)&&(delete r.handle,p.removeData(a,"events",!0))},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,f,g){if(!f||f.nodeType!==3&&f.nodeType!==8){var h,i,j,k,l,m,n,o,q,r,s=c.type||c,t=[];if($.test(s+p.event.triggered))return;s.indexOf("!")>=0&&(s=s.slice(0,-1),i=!0),s.indexOf(".")>=0&&(t=s.split("."),s=t.shift(),t.sort());if((!f||p.event.customEvent[s])&&!p.event.global[s])return;c=typeof c=="object"?c[p.expando]?c:new p.Event(s,c):new p.Event(s),c.type=s,c.isTrigger=!0,c.exclusive=i,c.namespace=t.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+t.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,m=s.indexOf(":")<0?"on"+s:"";if(!f){h=p.cache;for(j in h)h[j].events&&h[j].events[s]&&p.event.trigger(c,d,h[j].handle.elem,!0);return}c.result=b,c.target||(c.target=f),d=d!=null?p.makeArray(d):[],d.unshift(c),n=p.event.special[s]||{};if(n.trigger&&n.trigger.apply(f,d)===!1)return;q=[[f,n.bindType||s]];if(!g&&!n.noBubble&&!p.isWindow(f)){r=n.delegateType||s,k=$.test(r+s)?f:f.parentNode;for(l=f;k;k=k.parentNode)q.push([k,r]),l=k;l===(f.ownerDocument||e)&&q.push([l.defaultView||l.parentWindow||a,r])}for(j=0;j<q.length&&!c.isPropagationStopped();j++)k=q[j][0],c.type=q[j][1],o=(p._data(k,"events")||{})[c.type]&&p._data(k,"handle"),o&&o.apply(k,d),o=m&&k[m],o&&p.acceptData(k)&&o.apply(k,d)===!1&&c.preventDefault();return c.type=s,!g&&!c.isDefaultPrevented()&&(!n._default||n._default.apply(f.ownerDocument,d)===!1)&&(s!=="click"||!p.nodeName(f,"a"))&&p.acceptData(f)&&m&&f[s]&&(s!=="focus"&&s!=="blur"||c.target.offsetWidth!==0)&&!p.isWindow(f)&&(l=f[m],l&&(f[m]=null),p.event.triggered=s,f[s](),p.event.triggered=b,l&&(f[m]=l)),c.result}return},dispatch:function(c){c=p.event.fix(c||a.event);var d,e,f,g,h,i,j,k,l,m,n,o=(p._data(this,"events")||{})[c.type]||[],q=o.delegateCount,r=[].slice.call(arguments),s=!c.exclusive&&!c.namespace,t=p.event.special[c.type]||{},u=[];r[0]=c,c.delegateTarget=this;if(t.preDispatch&&t.preDispatch.call(this,c)===!1)return;if(q&&(!c.button||c.type!=="click")){g=p(this),g.context=this;for(f=c.target;f!=this;f=f.parentNode||this)if(f.disabled!==!0||c.type!=="click"){i={},k=[],g[0]=f;for(d=0;d<q;d++)l=o[d],m=l.selector,i[m]===b&&(i[m]=g.is(m)),i[m]&&k.push(l);k.length&&u.push({elem:f,matches:k})}}o.length>q&&u.push({elem:this,matches:o.slice(q)});for(d=0;d<u.length&&!c.isPropagationStopped();d++){j=u[d],c.currentTarget=j.elem;for(e=0;e<j.matches.length&&!c.isImmediatePropagationStopped();e++){l=j.matches[e];if(s||!c.namespace&&!l.namespace||c.namespace_re&&c.namespace_re.test(l.namespace))c.data=l.data,c.handleObj=l,h=((p.event.special[l.origType]||{}).handle||l.handler).apply(j.elem,r),h!==b&&(c.result=h,h===!1&&(c.preventDefault(),c.stopPropagation()))}}return t.postDispatch&&t.postDispatch.call(this,c),c.result},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,c){var d,f,g,h=c.button,i=c.fromElement;return a.pageX==null&&c.clientX!=null&&(d=a.target.ownerDocument||e,f=d.documentElement,g=d.body,a.pageX=c.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=c.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?c.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0),a}},fix:function(a){if(a[p.expando])return a;var b,c,d=a,f=p.event.fixHooks[a.type]||{},g=f.props?this.props.concat(f.props):this.props;a=p.Event(d);for(b=g.length;b;)c=g[--b],a[c]=d[c];return a.target||(a.target=d.srcElement||e),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey=!!a.metaKey,f.filter?f.filter(a,d):a},special:{ready:{setup:p.bindReady},load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(a,b,c){p.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=p.extend(new p.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?p.event.trigger(e,null,b):p.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},p.event.handle=p.event.dispatch,p.removeEvent=e.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){var d="on"+b;a.detachEvent&&(typeof a[d]=="undefined"&&(a[d]=null),a.detachEvent(d,c))},p.Event=function(a,b){if(this instanceof p.Event)a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?bb:ba):this.type=a,b&&p.extend(this,b),this.timeStamp=a&&a.timeStamp||p.now(),this[p.expando]=!0;else return new p.Event(a,b)},p.Event.prototype={preventDefault:function(){this.isDefaultPrevented=bb;var a=this.originalEvent;if(!a)return;a.preventDefault?a.preventDefault():a.returnValue=!1},stopPropagation:function(){this.isPropagationStopped=bb;var a=this.originalEvent;if(!a)return;a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=bb,this.stopPropagation()},isDefaultPrevented:ba,isPropagationStopped:ba,isImmediatePropagationStopped:ba},p.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){p.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj,g=f.selector;if(!e||e!==d&&!p.contains(d,e))a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b;return c}}}),p.support.submitBubbles||(p.event.special.submit={setup:function(){if(p.nodeName(this,"form"))return!1;p.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=p.nodeName(c,"input")||p.nodeName(c,"button")?c.form:b;d&&!p._data(d,"_submit_attached")&&(p.event.add(d,"submit._submit",function(a){a._submit_bubble=!0}),p._data(d,"_submit_attached",!0))})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&p.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){if(p.nodeName(this,"form"))return!1;p.event.remove(this,"._submit")}}),p.support.changeBubbles||(p.event.special.change={setup:function(){if(V.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")p.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),p.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1),p.event.simulate("change",this,a,!0)});return!1}p.event.add(this,"beforeactivate._change",function(a){var b=a.target;V.test(b.nodeName)&&!p._data(b,"_change_attached")&&(p.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&p.event.simulate("change",this.parentNode,a,!0)}),p._data(b,"_change_attached",!0))})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){return p.event.remove(this,"._change"),V.test(this.nodeName)}}),p.support.focusinBubbles||p.each({focus:"focusin",blur:"focusout"},function(a,b){var c=0,d=function(a){p.event.simulate(b,a.target,p.event.fix(a),!0)};p.event.special[b]={setup:function(){c++===0&&e.addEventListener(a,d,!0)},teardown:function(){--c===0&&e.removeEventListener(a,d,!0)}}}),p.fn.extend({on:function(a,c,d,e,f){var g,h;if(typeof a=="object"){typeof c!="string"&&(d=d||c,c=b);for(h in a)this.on(h,c,d,a[h],f);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=ba;else if(!e)return this;return f===1&&(g=e,e=function(a){return p().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=p.guid++)),this.each(function(){p.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,c,d){var e,f;if(a&&a.preventDefault&&a.handleObj)return e=a.handleObj,p(a.delegateTarget).off(e.namespace?e.origType+"."+e.namespace:e.origType,e.selector,e.handler),this;if(typeof a=="object"){for(f in a)this.off(f,c,a[f]);return this}if(c===!1||typeof c=="function")d=c,c=b;return d===!1&&(d=ba),this.each(function(){p.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){return p(this.context).on(a,this.selector,b,c),this},die:function(a,b){return p(this.context).off(a,this.selector||"**",b),this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length==1?this.off(a,"**"):this.off(b,a||"**",c)},trigger:function(a,b){return this.each(function(){p.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return p.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||p.guid++,d=0,e=function(c){var e=(p._data(this,"lastToggle"+a.guid)||0)%d;return p._data(this,"lastToggle"+a.guid,e+1),c.preventDefault(),b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),p.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){p.fn[b]=function(a,c){return c==null&&(c=a,a=null),arguments.length>0?this.on(b,null,a,c):this.trigger(b)},Y.test(b)&&(p.event.fixHooks[b]=p.event.keyHooks),Z.test(b)&&(p.event.fixHooks[b]=p.event.mouseHooks)}),function(a,b){function bd(a,b,c,d){var e=0,f=b.length;for(;e<f;e++)Z(a,b[e],c,d)}function be(a,b,c,d,e,f){var g,h=$.setFilters[b.toLowerCase()];return h||Z.error(b),(a||!(g=e))&&bd(a||"*",d,g=[],e),g.length>0?h(g,c,f):[]}function bf(a,c,d,e,f){var g,h,i,j,k,l,m,n,p=0,q=f.length,s=L.POS,t=new RegExp("^"+s.source+"(?!"+r+")","i"),u=function(){var a=1,c=arguments.length-2;for(;a<c;a++)arguments[a]===b&&(g[a]=b)};for(;p<q;p++){s.exec(""),a=f[p],j=[],i=0,k=e;while(g=s.exec(a)){n=s.lastIndex=g.index+g[0].length;if(n>i){m=a.slice(i,g.index),i=n,l=[c],B.test(m)&&(k&&(l=k),k=e);if(h=H.test(m))m=m.slice(0,-5).replace(B,"$&*");g.length>1&&g[0].replace(t,u),k=be(m,g[1],g[2],l,k,h)}}k?(j=j.concat(k),(m=a.slice(i))&&m!==")"?B.test(m)?bd(m,j,d,e):Z(m,c,d,e?e.concat(k):k):o.apply(d,j)):Z(a,c,d,e)}return q===1?d:Z.uniqueSort(d)}function bg(a,b,c){var d,e,f,g=[],i=0,j=D.exec(a),k=!j.pop()&&!j.pop(),l=k&&a.match(C)||[""],m=$.preFilter,n=$.filter,o=!c&&b!==h;for(;(e=l[i])!=null&&k;i++){g.push(d=[]),o&&(e=" "+e);while(e){k=!1;if(j=B.exec(e))e=e.slice(j[0].length),k=d.push({part:j.pop().replace(A," "),captures:j});for(f in n)(j=L[f].exec(e))&&(!m[f]||(j=m[f](j,b,c)))&&(e=e.slice(j.shift().length),k=d.push({part:f,captures:j}));if(!k)break}}return k||Z.error(a),g}function bh(a,b,e){var f=b.dir,g=m++;return a||(a=function(a){return a===e}),b.first?function(b,c){while(b=b[f])if(b.nodeType===1)return a(b,c)&&b}:function(b,e){var h,i=g+"."+d,j=i+"."+c;while(b=b[f])if(b.nodeType===1){if((h=b[q])===j)return b.sizset;if(typeof h=="string"&&h.indexOf(i)===0){if(b.sizset)return b}else{b[q]=j;if(a(b,e))return b.sizset=!0,b;b.sizset=!1}}}}function bi(a,b){return a?function(c,d){var e=b(c,d);return e&&a(e===!0?c:e,d)}:b}function bj(a,b,c){var d,e,f=0;for(;d=a[f];f++)$.relative[d.part]?e=bh(e,$.relative[d.part],b):(d.captures.push(b,c),e=bi(e,$.filter[d.part].apply(null,d.captures)));return e}function bk(a){return function(b,c){var d,e=0;for(;d=a[e];e++)if(d(b,c))return!0;return!1}}var c,d,e,f,g,h=a.document,i=h.documentElement,j="undefined",k=!1,l=!0,m=0,n=[].slice,o=[].push,q=("sizcache"+Math.random()).replace(".",""),r="[\\x20\\t\\r\\n\\f]",s="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",t=s.replace("w","w#"),u="([*^$|!~]?=)",v="\\["+r+"*("+s+")"+r+"*(?:"+u+r+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+t+")|)|)"+r+"*\\]",w=":("+s+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|((?:[^,]|\\\\,|(?:,(?=[^\\[]*\\]))|(?:,(?=[^\\(]*\\))))*))\\)|)",x=":(nth|eq|gt|lt|first|last|even|odd)(?:\\((\\d*)\\)|)(?=[^-]|$)",y=r+"*([\\x20\\t\\r\\n\\f>+~])"+r+"*",z="(?=[^\\x20\\t\\r\\n\\f])(?:\\\\.|"+v+"|"+w.replace(2,7)+"|[^\\\\(),])+",A=new RegExp("^"+r+"+|((?:^|[^\\\\])(?:\\\\.)*)"+r+"+$","g"),B=new RegExp("^"+y),C=new RegExp(z+"?(?="+r+"*,|$)","g"),D=new RegExp("^(?:(?!,)(?:(?:^|,)"+r+"*"+z+")*?|"+r+"*(.*?))(\\)|$)"),E=new RegExp(z.slice(19,-6)+"\\x20\\t\\r\\n\\f>+~])+|"+y,"g"),F=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,G=/[\x20\t\r\n\f]*[+~]/,H=/:not\($/,I=/h\d/i,J=/input|select|textarea|button/i,K=/\\(?!\\)/g,L={ID:new RegExp("^#("+s+")"),CLASS:new RegExp("^\\.("+s+")"),NAME:new RegExp("^\\[name=['\"]?("+s+")['\"]?\\]"),TAG:new RegExp("^("+s.replace("[-","[-\\*")+")"),ATTR:new RegExp("^"+v),PSEUDO:new RegExp("^"+w),CHILD:new RegExp("^:(only|nth|last|first)-child(?:\\("+r+"*(even|odd|(([+-]|)(\\d*)n|)"+r+"*(?:([+-]|)"+r+"*(\\d+)|))"+r+"*\\)|)","i"),POS:new RegExp(x,"ig"),needsContext:new RegExp("^"+r+"*[>+~]|"+x,"i")},M={},N=[],O={},P=[],Q=function(a){return a.sizzleFilter=!0,a},R=function(a){return function(b){return b.nodeName.toLowerCase()==="input"&&b.type===a}},S=function(a){return function(b){var c=b.nodeName.toLowerCase();return(c==="input"||c==="button")&&b.type===a}},T=function(a){var b=!1,c=h.createElement("div");try{b=a(c)}catch(d){}return c=null,b},U=T(function(a){a.innerHTML="<select></select>";var b=typeof a.lastChild.getAttribute("multiple");return b!=="boolean"&&b!=="string"}),V=T(function(a){a.id=q+0,a.innerHTML="<a name='"+q+"'></a><div name='"+q+"'></div>",i.insertBefore(a,i.firstChild);var b=h.getElementsByName&&h.getElementsByName(q).length===2+h.getElementsByName(q+0).length;return g=!h.getElementById(q),i.removeChild(a),b}),W=T(function(a){return a.appendChild(h.createComment("")),a.getElementsByTagName("*").length===0}),X=T(function(a){return a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!==j&&a.firstChild.getAttribute("href")==="#"}),Y=T(function(a){return a.innerHTML="<div class='hidden e'></div><div class='hidden'></div>",!a.getElementsByClassName||a.getElementsByClassName("e").length===0?!1:(a.lastChild.className="e",a.getElementsByClassName("e").length!==1)}),Z=function(a,b,c,d){c=c||[],b=b||h;var e,f,g,i,j=b.nodeType;if(j!==1&&j!==9)return[];if(!a||typeof a!="string")return c;g=ba(b);if(!g&&!d)if(e=F.exec(a))if(i=e[1]){if(j===9){f=b.getElementById(i);if(!f||!f.parentNode)return c;if(f.id===i)return c.push(f),c}else if(b.ownerDocument&&(f=b.ownerDocument.getElementById(i))&&bb(b,f)&&f.id===i)return c.push(f),c}else{if(e[2])return o.apply(c,n.call(b.getElementsByTagName(a),0)),c;if((i=e[3])&&Y&&b.getElementsByClassName)return o.apply(c,n.call(b.getElementsByClassName(i),0)),c}return bm(a,b,c,d,g)},$=Z.selectors={cacheLength:50,match:L,order:["ID","TAG"],attrHandle:{},createPseudo:Q,find:{ID:g?function(a,b,c){if(typeof b.getElementById!==j&&!c){var d=b.getElementById(a);return d&&d.parentNode?[d]:[]}}:function(a,c,d){if(typeof c.getElementById!==j&&!d){var e=c.getElementById(a);return e?e.id===a||typeof e.getAttributeNode!==j&&e.getAttributeNode("id").value===a?[e]:b:[]}},TAG:W?function(a,b){if(typeof b.getElementsByTagName!==j)return b.getElementsByTagName(a)}:function(a,b){var c=b.getElementsByTagName(a);if(a==="*"){var d,e=[],f=0;for(;d=c[f];f++)d.nodeType===1&&e.push(d);return e}return c}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(K,""),a[3]=(a[4]||a[5]||"").replace(K,""),a[2]==="~="&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),a[1]==="nth"?(a[2]||Z.error(a[0]),a[3]=+(a[3]?a[4]+(a[5]||1):2*(a[2]==="even"||a[2]==="odd")),a[4]=+(a[6]+a[7]||a[2]==="odd")):a[2]&&Z.error(a[0]),a},PSEUDO:function(a){var b,c=a[4];return L.CHILD.test(a[0])?null:(c&&(b=D.exec(c))&&b.pop()&&(a[0]=a[0].slice(0,b[0].length-c.length-1),c=b[0].slice(0,-1)),a.splice(2,3,c||a[3]),a)}},filter:{ID:g?function(a){return a=a.replace(K,""),function(b){return b.getAttribute("id")===a}}:function(a){return a=a.replace(K,""),function(b){var c=typeof b.getAttributeNode!==j&&b.getAttributeNode("id");return c&&c.value===a}},TAG:function(a){return a==="*"?function(){return!0}:(a=a.replace(K,"").toLowerCase(),function(b){return b.nodeName&&b.nodeName.toLowerCase()===a})},CLASS:function(a){var b=M[a];return b||(b=M[a]=new RegExp("(^|"+r+")"+a+"("+r+"|$)"),N.push(a),N.length>$.cacheLength&&delete M[N.shift()]),function(a){return b.test(a.className||typeof a.getAttribute!==j&&a.getAttribute("class")||"")}},ATTR:function(a,b,c){return b?function(d){var e=Z.attr(d,a),f=e+"";if(e==null)return b==="!=";switch(b){case"=":return f===c;case"!=":return f!==c;case"^=":return c&&f.indexOf(c)===0;case"*=":return c&&f.indexOf(c)>-1;case"$=":return c&&f.substr(f.length-c.length)===c;case"~=":return(" "+f+" ").indexOf(c)>-1;case"|=":return f===c||f.substr(0,c.length+1)===c+"-"}}:function(b){return Z.attr(b,a)!=null}},CHILD:function(a,b,c,d){if(a==="nth"){var e=m++;return function(a){var b,f,g=0,h=a;if(c===1&&d===0)return!0;b=a.parentNode;if(b&&(b[q]!==e||!a.sizset)){for(h=b.firstChild;h;h=h.nextSibling)if(h.nodeType===1){h.sizset=++g;if(h===a)break}b[q]=e}return f=a.sizset-d,c===0?f===0:f%c===0&&f/c>=0}}return function(b){var c=b;switch(a){case"only":case"first":while(c=c.previousSibling)if(c.nodeType===1)return!1;if(a==="first")return!0;c=b;case"last":while(c=c.nextSibling)if(c.nodeType===1)return!1;return!0}}},PSEUDO:function(a,b,c,d){var e=$.pseudos[a]||$.pseudos[a.toLowerCase()];return e||Z.error("unsupported pseudo: "+a),e.sizzleFilter?e(b,c,d):e}},pseudos:{not:Q(function(a,b,c){var d=bl(a.replace(A,"$1"),b,c);return function(a){return!d(a)}}),enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&!!a.checked||b==="option"&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},parent:function(a){return!$.pseudos.empty(a)},empty:function(a){var b;a=a.firstChild;while(a){if(a.nodeName>"@"||(b=a.nodeType)===3||b===4)return!1;a=a.nextSibling}return!0},contains:Q(function(a){return function(b){return(b.textContent||b.innerText||bc(b)).indexOf(a)>-1}}),has:Q(function(a){return function(b){return Z(a,b).length>0}}),header:function(a){return I.test(a.nodeName)},text:function(a){var b,c;return a.nodeName.toLowerCase()==="input"&&(b=a.type)==="text"&&((c=a.getAttribute("type"))==null||c.toLowerCase()===b)},radio:R("radio"),checkbox:R("checkbox"),file:R("file"),password:R("password"),image:R("image"),submit:S("submit"),reset:S("reset"),button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&a.type==="button"||b==="button"},input:function(a){return J.test(a.nodeName)},focus:function(a){var b=a.ownerDocument;return a===b.activeElement&&(!b.hasFocus||b.hasFocus())&&(!!a.type||!!a.href)},active:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b,c){return c?a.slice(1):[a[0]]},last:function(a,b,c){var d=a.pop();return c?a:[d]},even:function(a,b,c){var d=[],e=c?1:0,f=a.length;for(;e<f;e=e+2)d.push(a[e]);return d},odd:function(a,b,c){var d=[],e=c?0:1,f=a.length;for(;e<f;e=e+2)d.push(a[e]);return d},lt:function(a,b,c){return c?a.slice(+b):a.slice(0,+b)},gt:function(a,b,c){return c?a.slice(0,+b+1):a.slice(+b+1)},eq:function(a,b,c){var d=a.splice(+b,1);return c?a:d}}};$.setFilters.nth=$.setFilters.eq,$.filters=$.pseudos,X||($.attrHandle={href:function(a){return a.getAttribute("href",2)},type:function(a){return a.getAttribute("type")}}),V&&($.order.push("NAME"),$.find.NAME=function(a,b){if(typeof b.getElementsByName!==j)return b.getElementsByName(a)}),Y&&($.order.splice(1,0,"CLASS"),$.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!==j&&!c)return b.getElementsByClassName(a)});try{n.call(i.childNodes,0)[0].nodeType}catch(_){n=function(a){var b,c=[];for(;b=this[a];a++)c.push(b);return c}}var ba=Z.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?b.nodeName!=="HTML":!1},bb=Z.contains=i.compareDocumentPosition?function(a,b){return!!(a.compareDocumentPosition(b)&16)}:i.contains?function(a,b){var c=a.nodeType===9?a.documentElement:a,d=b.parentNode;return a===d||!!(d&&d.nodeType===1&&c.contains&&c.contains(d))}:function(a,b){while(b=b.parentNode)if(b===a)return!0;return!1},bc=Z.getText=function(a){var b,c="",d=0,e=a.nodeType;if(e){if(e===1||e===9||e===11){if(typeof a.textContent=="string")return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=bc(a)}else if(e===3||e===4)return a.nodeValue}else for(;b=a[d];d++)c+=bc(b);return c};Z.attr=function(a,b){var c,d=ba(a);return d||(b=b.toLowerCase()),$.attrHandle[b]?$.attrHandle[b](a):U||d?a.getAttribute(b):(c=a.getAttributeNode(b),c?typeof a[b]=="boolean"?a[b]?b:null:c.specified?c.value:null:null)},Z.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},[0,0].sort(function(){return l=0}),i.compareDocumentPosition?e=function(a,b){return a===b?(k=!0,0):(!a.compareDocumentPosition||!b.compareDocumentPosition?a.compareDocumentPosition:a.compareDocumentPosition(b)&4)?-1:1}:(e=function(a,b){if(a===b)return k=!0,0;if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],g=[],h=a.parentNode,i=b.parentNode,j=h;if(h===i)return f(a,b);if(!h)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)g.unshift(j),j=j.parentNode;c=e.length,d=g.length;for(var l=0;l<c&&l<d;l++)if(e[l]!==g[l])return f(e[l],g[l]);return l===c?f(a,g[l],-1):f(e[l],b,1)},f=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),Z.uniqueSort=function(a){var b,c=1;if(e){k=l,a.sort(e);if(k)for(;b=a[c];c++)b===a[c-1]&&a.splice(c--,1)}return a};var bl=Z.compile=function(a,b,c){var d,e,f,g=O[a];if(g&&g.context===b)return g;e=bg(a,b,c);for(f=0;d=e[f];f++)e[f]=bj(d,b,c);return g=O[a]=bk(e),g.context=b,g.runs=g.dirruns=0,P.push(a),P.length>$.cacheLength&&delete O[P.shift()],g};Z.matches=function(a,b){return Z(a,null,null,b)},Z.matchesSelector=function(a,b){return Z(b,null,null,[a]).length>0};var bm=function(a,b,e,f,g){a=a.replace(A,"$1");var h,i,j,k,l,m,p,q,r,s=a.match(C),t=a.match(E),u=b.nodeType;if(L.POS.test(a))return bf(a,b,e,f,s);if(f)h=n.call(f,0);else if(s&&s.length===1){if(t.length>1&&u===9&&!g&&(s=L.ID.exec(t[0]))){b=$.find.ID(s[1],b,g)[0];if(!b)return e;a=a.slice(t.shift().length)}q=(s=G.exec(t[0]))&&!s.index&&b.parentNode||b,r=t.pop(),m=r.split(":not")[0];for(j=0,k=$.order.length;j<k;j++){p=$.order[j];if(s=L[p].exec(m)){h=$.find[p]((s[1]||"").replace(K,""),q,g);if(h==null)continue;m===r&&(a=a.slice(0,a.length-r.length)+m.replace(L[p],""),a||o.apply(e,n.call(h,0)));break}}}if(a){i=bl(a,b,g),d=i.dirruns++,h==null&&(h=$.find.TAG("*",G.test(a)&&b.parentNode||b));for(j=0;l=h[j];j++)c=i.runs++,i(l,b)&&e.push(l)}return e};h.querySelectorAll&&function(){var a,b=bm,c=/'|\\/g,d=/\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,e=[],f=[":active"],g=i.matchesSelector||i.mozMatchesSelector||i.webkitMatchesSelector||i.oMatchesSelector||i.msMatchesSelector;T(function(a){a.innerHTML="<select><option selected></option></select>",a.querySelectorAll("[selected]").length||e.push("\\["+r+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),a.querySelectorAll(":checked").length||e.push(":checked")}),T(function(a){a.innerHTML="<p test=''></p>",a.querySelectorAll("[test^='']").length&&e.push("[*^$]="+r+"*(?:\"\"|'')"),a.innerHTML="<input type='hidden'>",a.querySelectorAll(":enabled").length||e.push(":enabled",":disabled")}),e=e.length&&new RegExp(e.join("|")),bm=function(a,d,f,g,h){if(!g&&!h&&(!e||!e.test(a)))if(d.nodeType===9)try{return o.apply(f,n.call(d.querySelectorAll(a),0)),f}catch(i){}else if(d.nodeType===1&&d.nodeName.toLowerCase()!=="object"){var j=d.getAttribute("id"),k=j||q,l=G.test(a)&&d.parentNode||d;j?k=k.replace(c,"\\$&"):d.setAttribute("id",k);try{return o.apply(f,n.call(l.querySelectorAll(a.replace(C,"[id='"+k+"'] $&")),0)),f}catch(i){}finally{j||d.removeAttribute("id")}}return b(a,d,f,g,h)},g&&(T(function(b){a=g.call(b,"div");try{g.call(b,"[test!='']:sizzle"),f.push($.match.PSEUDO)}catch(c){}}),f=new RegExp(f.join("|")),Z.matchesSelector=function(b,c){c=c.replace(d,"='$1']");if(!ba(b)&&!f.test(c)&&(!e||!e.test(c)))try{var h=g.call(b,c);if(h||a||b.document&&b.document.nodeType!==11)return h}catch(i){}return Z(c,null,null,[b]).length>0})}(),Z.attr=p.attr,p.find=Z,p.expr=Z.selectors,p.expr[":"]=p.expr.pseudos,p.unique=Z.uniqueSort,p.text=Z.getText,p.isXMLDoc=Z.isXML,p.contains=Z.contains}(a);var bc=/Until$/,bd=/^(?:parents|prev(?:Until|All))/,be=/^.[^:#\[\.,]*$/,bf=p.expr.match.needsContext,bg={children:!0,contents:!0,next:!0,prev:!0};p.fn.extend({find:function(a){var b,c,d,e,f,g,h=this;if(typeof a!="string")return p(a).filter(function(){for(b=0,c=h.length;b<c;b++)if(p.contains(h[b],this))return!0});g=this.pushStack("","find",a);for(b=0,c=this.length;b<c;b++){d=g.length,p.find(a,this[b],g);if(b>0)for(e=d;e<g.length;e++)for(f=0;f<d;f++)if(g[f]===g[e]){g.splice(e--,1);break}}return g},has:function(a){var b,c=p(a,this),d=c.length;return this.filter(function(){for(b=0;b<d;b++)if(p.contains(this,c[b]))return!0})},not:function(a){return this.pushStack(bj(this,a,!1),"not",a)},filter:function(a){return this.pushStack(bj(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?bf.test(a)?p(a,this.context).index(this[0])>=0:p.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c,d=0,e=this.length,f=[],g=bf.test(a)||typeof a!="string"?p(a,b||this.context):0;for(;d<e;d++){c=this[d];while(c&&c.ownerDocument&&c!==b&&c.nodeType!==11){if(g?g.index(c)>-1:p.find.matchesSelector(c,a)){f.push(c);break}c=c.parentNode}}return f=f.length>1?p.unique(f):f,this.pushStack(f,"closest",a)},index:function(a){return a?typeof a=="string"?p.inArray(this[0],p(a)):p.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(a,b){var c=typeof a=="string"?p(a,b):p.makeArray(a&&a.nodeType?[a]:a),d=p.merge(this.get(),c);return this.pushStack(bh(c[0])||bh(d[0])?d:p.unique(d))},addBack:function(a){return this.add(a==null?this.prevObject:this.prevObject.filter(a))}}),p.fn.andSelf=p.fn.addBack,p.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return p.dir(a,"parentNode")},parentsUntil:function(a,b,c){return p.dir(a,"parentNode",c)},next:function(a){return bi(a,"nextSibling")},prev:function(a){return bi(a,"previousSibling")},nextAll:function(a){return p.dir(a,"nextSibling")},prevAll:function(a){return p.dir(a,"previousSibling")},nextUntil:function(a,b,c){return p.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return p.dir(a,"previousSibling",c)},siblings:function(a){return p.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return p.sibling(a.firstChild)},contents:function(a){return p.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:p.merge([],a.childNodes)}},function(a,b){p.fn[a]=function(c,d){var e=p.map(this,b,c);return bc.test(a)||(d=c),d&&typeof d=="string"&&(e=p.filter(d,e)),e=this.length>1&&!bg[a]?p.unique(e):e,this.length>1&&bd.test(a)&&(e=e.reverse()),this.pushStack(e,a,k.call(arguments).join(","))}}),p.extend({filter:function(a,b,c){return c&&(a=":not("+a+")"),b.length===1?p.find.matchesSelector(b[0],a)?[b[0]]:[]:p.find.matches(a,b)},dir:function(a,c,d){var e=[],f=a[c];while(f&&f.nodeType!==9&&(d===b||f.nodeType!==1||!p(f).is(d)))f.nodeType===1&&e.push(f),f=f[c];return e},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var bl="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",bm=/ jQuery\d+="(?:null|\d+)"/g,bn=/^\s+/,bo=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bp=/<([\w:]+)/,bq=/<tbody/i,br=/<|&#?\w+;/,bs=/<(?:script|style|link)/i,bt=/<(?:script|object|embed|option|style)/i,bu=new RegExp("<(?:"+bl+")[\\s/>]","i"),bv=/^(?:checkbox|radio)$/,bw=/checked\s*(?:[^=]|=\s*.checked.)/i,bx=/\/(java|ecma)script/i,by=/^\s*<!(?:\[CDATA\[|\-\-)|[\]\-]{2}>\s*$/g,bz={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},bA=bk(e),bB=bA.appendChild(e.createElement("div"));bz.optgroup=bz.option,bz.tbody=bz.tfoot=bz.colgroup=bz.caption=bz.thead,bz.th=bz.td,p.support.htmlSerialize||(bz._default=[1,"X<div>","</div>"]),p.fn.extend({text:function(a){return p.access(this,function(a){return a===b?p.text(this):this.empty().append((this[0]&&this[0].ownerDocument||e).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(p.isFunction(a))return this.each(function(b){p(this).wrapAll(a.call(this,b))});if(this[0]){var b=p(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return p.isFunction(a)?this.each(function(b){p(this).wrapInner(a.call(this,b))}):this.each(function(){var b=p(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=p.isFunction(a);return this.each(function(c){p(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){p.nodeName(this,"body")||p(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(a,this.firstChild)})},before:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(a,this),"before",this.selector)}},after:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(this,a),"after",this.selector)}},remove:function(a,b){var c,d=0;for(;(c=this[d])!=null;d++)if(!a||p.filter(a,[c]).length)!b&&c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),p.cleanData([c])),c.parentNode&&c.parentNode.removeChild(c);return this},empty:function(){var a,b=0;for(;(a=this[b])!=null;b++){a.nodeType===1&&p.cleanData(a.getElementsByTagName("*"));while(a.firstChild)a.removeChild(a.firstChild)}return this},clone:function(a,b){return a=a==null?!1:a,b=b==null?a:b,this.map(function(){return p.clone(this,a,b)})},html:function(a){return p.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(bm,""):b;if(typeof a=="string"&&!bs.test(a)&&(p.support.htmlSerialize||!bu.test(a))&&(p.support.leadingWhitespace||!bn.test(a))&&!bz[(bp.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(bo,"<$1></$2>");try{for(;d<e;d++)c=this[d]||{},c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),c.innerHTML=a);c=0}catch(f){}}c&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(a){return bh(this[0])?this.length?this.pushStack(p(p.isFunction(a)?a():a),"replaceWith",a):this:p.isFunction(a)?this.each(function(b){var c=p(this),d=c.html();c.replaceWith(a.call(this,b,d))}):(typeof a!="string"&&(a=p(a).detach()),this.each(function(){var b=this.nextSibling,c=this.parentNode;p(this).remove(),b?p(b).before(a):p(c).append(a)}))},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){a=[].concat.apply([],a);var e,f,g,h,i=0,j=a[0],k=[],l=this.length;if(!p.support.checkClone&&l>1&&typeof j=="string"&&bw.test(j))return this.each(function(){p(this).domManip(a,c,d)});if(p.isFunction(j))return this.each(function(e){var f=p(this);a[0]=j.call(this,e,c?f.html():b),f.domManip(a,c,d)});if(this[0]){e=p.buildFragment(a,this,k),g=e.fragment,f=g.firstChild,g.childNodes.length===1&&(g=f);if(f){c=c&&p.nodeName(f,"tr");for(h=e.cacheable||l-1;i<l;i++)d.call(c&&p.nodeName(this[i],"table")?bC(this[i],"tbody"):this[i],i===h?g:p.clone(g,!0,!0))}g=f=null,k.length&&p.each(k,function(a,b){b.src?p.ajax?p.ajax({url:b.src,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0}):p.error("no ajax"):p.globalEval((b.text||b.textContent||b.innerHTML||"").replace(by,"")),b.parentNode&&b.parentNode.removeChild(b)})}return this}}),p.buildFragment=function(a,c,d){var f,g,h,i=a[0];return c=c||e,c=(c[0]||c).ownerDocument||c[0]||c,typeof c.createDocumentFragment=="undefined"&&(c=e),a.length===1&&typeof i=="string"&&i.length<512&&c===e&&i.charAt(0)==="<"&&!bt.test(i)&&(p.support.checkClone||!bw.test(i))&&(p.support.html5Clone||!bu.test(i))&&(g=!0,f=p.fragments[i],h=f!==b),f||(f=c.createDocumentFragment(),p.clean(a,c,f,d),g&&(p.fragments[i]=h&&f)),{fragment:f,cacheable:g}},p.fragments={},p.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){p.fn[a]=function(c){var d,e=0,f=[],g=p(c),h=g.length,i=this.length===1&&this[0].parentNode;if((i==null||i&&i.nodeType===11&&i.childNodes.length===1)&&h===1)return g[b](this[0]),this;for(;e<h;e++)d=(e>0?this.clone(!0):this).get(),p(g[e])[b](d),f=f.concat(d);return this.pushStack(f,a,g.selector)}}),p.extend({clone:function(a,b,c){var d,e,f,g;p.support.html5Clone||p.isXMLDoc(a)||!bu.test("<"+a.nodeName+">")?g=a.cloneNode(!0):(bB.innerHTML=a.outerHTML,bB.removeChild(g=bB.firstChild));if((!p.support.noCloneEvent||!p.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!p.isXMLDoc(a)){bE(a,g),d=bF(a),e=bF(g);for(f=0;d[f];++f)e[f]&&bE(d[f],e[f])}if(b){bD(a,g);if(c){d=bF(a),e=bF(g);for(f=0;d[f];++f)bD(d[f],e[f])}}return d=e=null,g},clean:function(a,b,c,d){var f,g,h,i,j,k,l,m,n,o,q,r,s=0,t=[];if(!b||typeof b.createDocumentFragment=="undefined")b=e;for(g=b===e&&bA;(h=a[s])!=null;s++){typeof h=="number"&&(h+="");if(!h)continue;if(typeof h=="string")if(!br.test(h))h=b.createTextNode(h);else{g=g||bk(b),l=l||g.appendChild(b.createElement("div")),h=h.replace(bo,"<$1></$2>"),i=(bp.exec(h)||["",""])[1].toLowerCase(),j=bz[i]||bz._default,k=j[0],l.innerHTML=j[1]+h+j[2];while(k--)l=l.lastChild;if(!p.support.tbody){m=bq.test(h),n=i==="table"&&!m?l.firstChild&&l.firstChild.childNodes:j[1]==="<table>"&&!m?l.childNodes:[];for(f=n.length-1;f>=0;--f)p.nodeName(n[f],"tbody")&&!n[f].childNodes.length&&n[f].parentNode.removeChild(n[f])}!p.support.leadingWhitespace&&bn.test(h)&&l.insertBefore(b.createTextNode(bn.exec(h)[0]),l.firstChild),h=l.childNodes,l=g.lastChild}h.nodeType?t.push(h):t=p.merge(t,h)}l&&(g.removeChild(l),h=l=g=null);if(!p.support.appendChecked)for(s=0;(h=t[s])!=null;s++)p.nodeName(h,"input")?bG(h):typeof h.getElementsByTagName!="undefined"&&p.grep(h.getElementsByTagName("input"),bG);if(c){q=function(a){if(!a.type||bx.test(a.type))return d?d.push(a.parentNode?a.parentNode.removeChild(a):a):c.appendChild(a)};for(s=0;(h=t[s])!=null;s++)if(!p.nodeName(h,"script")||!q(h))c.appendChild(h),typeof h.getElementsByTagName!="undefined"&&(r=p.grep(p.merge([],h.getElementsByTagName("script")),q),t.splice.apply(t,[s+1,0].concat(r)),s+=r.length)}return t},cleanData:function(a,b){var c,d,e,f,g=0,h=p.expando,i=p.cache,j=p.support.deleteExpando,k=p.event.special;for(;(e=a[g])!=null;g++)if(b||p.acceptData(e)){d=e[h],c=d&&i[d];if(c){if(c.events)for(f in c.events)k[f]?p.event.remove(e,f):p.removeEvent(e,f,c.handle);i[d]&&(delete i[d],j?delete e[h]:e.removeAttribute?e.removeAttribute(h):e[h]=null,p.deletedIds.push(d))}}}}),function(){var a,b;p.uaMatch=function(a){a=a.toLowerCase();var b=/(chrome)[ \/]([\w.]+)/.exec(a)||/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||a.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},a=p.uaMatch(g.userAgent),b={},a.browser&&(b[a.browser]=!0,b.version=a.version),b.webkit&&(b.safari=!0),p.browser=b,p.sub=function(){function a(b,c){return new a.fn.init(b,c)}p.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function c(c,d){return d&&d instanceof p&&!(d instanceof a)&&(d=a(d)),p.fn.init.call(this,c,d,b)},a.fn.init.prototype=a.fn;var b=a(e);return a}}();var bH,bI,bJ,bK=/alpha\([^)]*\)/i,bL=/opacity=([^)]*)/,bM=/^(top|right|bottom|left)$/,bN=/^margin/,bO=new RegExp("^("+q+")(.*)$","i"),bP=new RegExp("^("+q+")(?!px)[a-z%]+$","i"),bQ=new RegExp("^([-+])=("+q+")","i"),bR={},bS={position:"absolute",visibility:"hidden",display:"block"},bT={letterSpacing:0,fontWeight:400,lineHeight:1},bU=["Top","Right","Bottom","Left"],bV=["Webkit","O","Moz","ms"],bW=p.fn.toggle;p.fn.extend({css:function(a,c){return p.access(this,function(a,c,d){return d!==b?p.style(a,c,d):p.css(a,c)},a,c,arguments.length>1)},show:function(){return bZ(this,!0)},hide:function(){return bZ(this)},toggle:function(a,b){var c=typeof a=="boolean";return p.isFunction(a)&&p.isFunction(b)?bW.apply(this,arguments):this.each(function(){(c?a:bY(this))?p(this).show():p(this).hide()})}}),p.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bH(a,"opacity");return c===""?"1":c}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":p.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!a||a.nodeType===3||a.nodeType===8||!a.style)return;var f,g,h,i=p.camelCase(c),j=a.style;c=p.cssProps[i]||(p.cssProps[i]=bX(j,i)),h=p.cssHooks[c]||p.cssHooks[i];if(d===b)return h&&"get"in h&&(f=h.get(a,!1,e))!==b?f:j[c];g=typeof d,g==="string"&&(f=bQ.exec(d))&&(d=(f[1]+1)*f[2]+parseFloat(p.css(a,c)),g="number");if(d==null||g==="number"&&isNaN(d))return;g==="number"&&!p.cssNumber[i]&&(d+="px");if(!h||!("set"in h)||(d=h.set(a,d,e))!==b)try{j[c]=d}catch(k){}},css:function(a,c,d,e){var f,g,h,i=p.camelCase(c);return c=p.cssProps[i]||(p.cssProps[i]=bX(a.style,i)),h=p.cssHooks[c]||p.cssHooks[i],h&&"get"in h&&(f=h.get(a,!0,e)),f===b&&(f=bH(a,c)),f==="normal"&&c in bT&&(f=bT[c]),d||e!==b?(g=parseFloat(f),d||p.isNumeric(g)?g||0:f):f},swap:function(a,b,c){var d,e,f={};for(e in b)f[e]=a.style[e],a.style[e]=b[e];d=c.call(a);for(e in b)a.style[e]=f[e];return d}}),a.getComputedStyle?bH=function(a,b){var c,d,e,f,g=getComputedStyle(a,null),h=a.style;return g&&(c=g[b],c===""&&!p.contains(a.ownerDocument.documentElement,a)&&(c=p.style(a,b)),bP.test(c)&&bN.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=c,c=g.width,h.width=d,h.minWidth=e,h.maxWidth=f)),c}:e.documentElement.currentStyle&&(bH=function(a,b){var c,d,e=a.currentStyle&&a.currentStyle[b],f=a.style;return e==null&&f&&f[b]&&(e=f[b]),bP.test(e)&&!bM.test(b)&&(c=f.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":e,e=f.pixelLeft+"px",f.left=c,d&&(a.runtimeStyle.left=d)),e===""?"auto":e}),p.each(["height","width"],function(a,b){p.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth!==0||bH(a,"display")!=="none"?ca(a,b,d):p.swap(a,bS,function(){return ca(a,b,d)})},set:function(a,c,d){return b$(a,c,d?b_(a,b,d,p.support.boxSizing&&p.css(a,"boxSizing")==="border-box"):0)}}}),p.support.opacity||(p.cssHooks.opacity={get:function(a,b){return bL.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=p.isNumeric(b)?"alpha(opacity="+b*100+")":"",f=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&p.trim(f.replace(bK,""))===""&&c.removeAttribute){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bK.test(f)?f.replace(bK,e):f+" "+e}}),p(function(){p.support.reliableMarginRight||(p.cssHooks.marginRight={get:function(a,b){return p.swap(a,{display:"inline-block"},function(){if(b)return bH(a,"marginRight")})}}),!p.support.pixelPosition&&p.fn.position&&p.each(["top","left"],function(a,b){p.cssHooks[b]={get:function(a,c){if(c){var d=bH(a,b);return bP.test(d)?p(a).position()[b]+"px":d}}}})}),p.expr&&p.expr.filters&&(p.expr.filters.hidden=function(a){return a.offsetWidth===0&&a.offsetHeight===0||!p.support.reliableHiddenOffsets&&(a.style&&a.style.display||bH(a,"display"))==="none"},p.expr.filters.visible=function(a){return!p.expr.filters.hidden(a)}),p.each({margin:"",padding:"",border:"Width"},function(a,b){p.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bU[d]+b]=e[d]||e[d-2]||e[0];return f}},bN.test(a)||(p.cssHooks[a+b].set=b$)});var cc=/%20/g,cd=/\[\]$/,ce=/\r?\n/g,cf=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,cg=/^(?:select|textarea)/i;p.fn.extend({serialize:function(){return p.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?p.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||cg.test(this.nodeName)||cf.test(this.type))}).map(function(a,b){var c=p(this).val();return c==null?null:p.isArray(c)?p.map(c,function(a,c){return{name:b.name,value:a.replace(ce,"\r\n")}}):{name:b.name,value:c.replace(ce,"\r\n")}}).get()}}),p.param=function(a,c){var d,e=[],f=function(a,b){b=p.isFunction(b)?b():b==null?"":b,e[e.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=p.ajaxSettings&&p.ajaxSettings.traditional);if(p.isArray(a)||a.jquery&&!p.isPlainObject(a))p.each(a,function(){f(this.name,this.value)});else for(d in a)ch(d,a[d],c,f);return e.join("&").replace(cc,"+")};var ci,cj,ck=/#.*$/,cl=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,cm=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,cn=/^(?:GET|HEAD)$/,co=/^\/\//,cp=/\?/,cq=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,cr=/([?&])_=[^&]*/,cs=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,ct=p.fn.load,cu={},cv={},cw=["*/"]+["*"];try{ci=f.href}catch(cx){ci=e.createElement("a"),ci.href="",ci=ci.href}cj=cs.exec(ci.toLowerCase())||[],p.fn.load=function(a,c,d){if(typeof a!="string"&&ct)return ct.apply(this,arguments);if(!this.length)return this;var e,f,g,h=this,i=a.indexOf(" ");return i>=0&&(e=a.slice(i,a.length),a=a.slice(0,i)),p.isFunction(c)?(d=c,c=b):typeof c=="object"&&(f="POST"),p.ajax({url:a,type:f,dataType:"html",data:c,complete:function(a,b){d&&h.each(d,g||[a.responseText,b,a])}}).done(function(a){g=arguments,h.html(e?p("<div>").append(a.replace(cq,"")).find(e):a)}),this},p.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){p.fn[b]=function(a){return this.on(b,a)}}),p.each(["get","post"],function(a,c){p[c]=function(a,d,e,f){return p.isFunction(d)&&(f=f||e,e=d,d=b),p.ajax({type:c,url:a,data:d,success:e,dataType:f})}}),p.extend({getScript:function(a,c){return p.get(a,b,c,"script")},getJSON:function(a,b,c){return p.get(a,b,c,"json")},ajaxSetup:function(a,b){return b?cA(a,p.ajaxSettings):(b=a,a=p.ajaxSettings),cA(a,b),a},ajaxSettings:{url:ci,isLocal:cm.test(cj[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":cw},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":p.parseJSON,"text xml":p.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:cy(cu),ajaxTransport:cy(cv),ajax:function(a,c){function y(a,c,f,i){var k,s,t,u,w,y=c;if(v===2)return;v=2,h&&clearTimeout(h),g=b,e=i||"",x.readyState=a>0?4:0,f&&(u=cB(l,x,f));if(a>=200&&a<300||a===304)l.ifModified&&(w=x.getResponseHeader("Last-Modified"),w&&(p.lastModified[d]=w),w=x.getResponseHeader("Etag"),w&&(p.etag[d]=w)),a===304?(y="notmodified",k=!0):(k=cC(l,u),y=k.state,s=k.data,t=k.error,k=!t);else{t=y;if(!y||a)y="error",a<0&&(a=0)}x.status=a,x.statusText=""+(c||y),k?o.resolveWith(m,[s,y,x]):o.rejectWith(m,[x,y,t]),x.statusCode(r),r=b,j&&n.trigger("ajax"+(k?"Success":"Error"),[x,l,k?s:t]),q.fireWith(m,[x,y]),j&&(n.trigger("ajaxComplete",[x,l]),--p.active||p.event.trigger("ajaxStop"))}typeof a=="object"&&(c=a,a=b),c=c||{};var d,e,f,g,h,i,j,k,l=p.ajaxSetup({},c),m=l.context||l,n=m!==l&&(m.nodeType||m instanceof p)?p(m):p.event,o=p.Deferred(),q=p.Callbacks("once memory"),r=l.statusCode||{},t={},u={},v=0,w="canceled",x={readyState:0,setRequestHeader:function(a,b){if(!v){var c=a.toLowerCase();a=u[c]=u[c]||a,t[a]=b}return this},getAllResponseHeaders:function(){return v===2?e:null},getResponseHeader:function(a){var c;if(v===2){if(!f){f={};while(c=cl.exec(e))f[c[1].toLowerCase()]=c[2]}c=f[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){return v||(l.mimeType=a),this},abort:function(a){return a=a||w,g&&g.abort(a),y(0,a),this}};o.promise(x),x.success=x.done,x.error=x.fail,x.complete=q.add,x.statusCode=function(a){if(a){var b;if(v<2)for(b in a)r[b]=[r[b],a[b]];else b=a[x.status],x.always(b)}return this},l.url=((a||l.url)+"").replace(ck,"").replace(co,cj[1]+"//"),l.dataTypes=p.trim(l.dataType||"*").toLowerCase().split(s),l.crossDomain==null&&(i=cs.exec(l.url.toLowerCase()),l.crossDomain=!(!i||i[1]==cj[1]&&i[2]==cj[2]&&(i[3]||(i[1]==="http:"?80:443))==(cj[3]||(cj[1]==="http:"?80:443)))),l.data&&l.processData&&typeof l.data!="string"&&(l.data=p.param(l.data,l.traditional)),cz(cu,l,c,x);if(v===2)return x;j=l.global,l.type=l.type.toUpperCase(),l.hasContent=!cn.test(l.type),j&&p.active++===0&&p.event.trigger("ajaxStart");if(!l.hasContent){l.data&&(l.url+=(cp.test(l.url)?"&":"?")+l.data,delete l.data),d=l.url;if(l.cache===!1){var z=p.now(),A=l.url.replace(cr,"$1_="+z);l.url=A+(A===l.url?(cp.test(l.url)?"&":"?")+"_="+z:"")}}(l.data&&l.hasContent&&l.contentType!==!1||c.contentType)&&x.setRequestHeader("Content-Type",l.contentType),l.ifModified&&(d=d||l.url,p.lastModified[d]&&x.setRequestHeader("If-Modified-Since",p.lastModified[d]),p.etag[d]&&x.setRequestHeader("If-None-Match",p.etag[d])),x.setRequestHeader("Accept",l.dataTypes[0]&&l.accepts[l.dataTypes[0]]?l.accepts[l.dataTypes[0]]+(l.dataTypes[0]!=="*"?", "+cw+"; q=0.01":""):l.accepts["*"]);for(k in l.headers)x.setRequestHeader(k,l.headers[k]);if(!l.beforeSend||l.beforeSend.call(m,x,l)!==!1&&v!==2){w="abort";for(k in{success:1,error:1,complete:1})x[k](l[k]);g=cz(cv,l,c,x);if(!g)y(-1,"No Transport");else{x.readyState=1,j&&n.trigger("ajaxSend",[x,l]),l.async&&l.timeout>0&&(h=setTimeout(function(){x.abort("timeout")},l.timeout));try{v=1,g.send(t,y)}catch(B){if(v<2)y(-1,B);else throw B}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var cD=[],cE=/\?/,cF=/(=)\?(?=&|$)|\?\?/,cG=p.now();p.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=cD.pop()||p.expando+"_"+cG++;return this[a]=!0,a}}),p.ajaxPrefilter("json jsonp",function(c,d,e){var f,g,h,i=c.data,j=c.url,k=c.jsonp!==!1,l=k&&cF.test(j),m=k&&!l&&typeof i=="string"&&!(c.contentType||"").indexOf("application/x-www-form-urlencoded")&&cF.test(i);if(c.dataTypes[0]==="jsonp"||l||m)return f=c.jsonpCallback=p.isFunction(c.jsonpCallback)?c.jsonpCallback():c.jsonpCallback,g=a[f],l?c.url=j.replace(cF,"$1"+f):m?c.data=i.replace(cF,"$1"+f):k&&(c.url+=(cE.test(j)?"&":"?")+c.jsonp+"="+f),c.converters["script json"]=function(){return h||p.error(f+" was not called"),h[0]},c.dataTypes[0]="json",a[f]=function(){h=arguments},e.always(function(){a[f]=g,c[f]&&(c.jsonpCallback=d.jsonpCallback,cD.push(f)),h&&p.isFunction(g)&&g(h[0]),h=g=b}),"script"}),p.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){return p.globalEval(a),a}}}),p.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),p.ajaxTransport("script",function(a){if(a.crossDomain){var c,d=e.head||e.getElementsByTagName("head")[0]||e.documentElement;return{send:function(f,g){c=e.createElement("script"),c.async="async",a.scriptCharset&&(c.charset=a.scriptCharset),c.src=a.url,c.onload=c.onreadystatechange=function(a,e){if(e||!c.readyState||/loaded|complete/.test(c.readyState))c.onload=c.onreadystatechange=null,d&&c.parentNode&&d.removeChild(c),c=b,e||g(200,"success")},d.insertBefore(c,d.firstChild)},abort:function(){c&&c.onload(0,1)}}}});var cH,cI=a.ActiveXObject?function(){for(var a in cH)cH[a](0,1)}:!1,cJ=0;p.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&cK()||cL()}:cK,function(a){p.extend(p.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(p.ajaxSettings.xhr()),p.support.ajax&&p.ajaxTransport(function(c){if(!c.crossDomain||p.support.cors){var d;return{send:function(e,f){var g,h,i=c.xhr();c.username?i.open(c.type,c.url,c.async,c.username,c.password):i.open(c.type,c.url,c.async);if(c.xhrFields)for(h in c.xhrFields)i[h]=c.xhrFields[h];c.mimeType&&i.overrideMimeType&&i.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(h in e)i.setRequestHeader(h,e[h])}catch(j){}i.send(c.hasContent&&c.data||null),d=function(a,e){var h,j,k,l,m;try{if(d&&(e||i.readyState===4)){d=b,g&&(i.onreadystatechange=p.noop,cI&&delete cH[g]);if(e)i.readyState!==4&&i.abort();else{h=i.status,k=i.getAllResponseHeaders(),l={},m=i.responseXML,m&&m.documentElement&&(l.xml=m);try{l.text=i.responseText}catch(a){}try{j=i.statusText}catch(n){j=""}!h&&c.isLocal&&!c.crossDomain?h=l.text?200:404:h===1223&&(h=204)}}}catch(o){e||f(-1,o)}l&&f(h,j,l,k)},c.async?i.readyState===4?setTimeout(d,0):(g=++cJ,cI&&(cH||(cH={},p(a).unload(cI)),cH[g]=d),i.onreadystatechange=d):d()},abort:function(){d&&d(0,1)}}}});var cM,cN,cO=/^(?:toggle|show|hide)$/,cP=new RegExp("^(?:([-+])=|)("+q+")([a-z%]*)$","i"),cQ=/queueHooks$/,cR=[cX],cS={"*":[function(a,b){var c,d,e,f=this.createTween(a,b),g=cP.exec(b),h=f.cur(),i=+h||0,j=1;if(g){c=+g[2],d=g[3]||(p.cssNumber[a]?"":"px");if(d!=="px"&&i){i=p.css(f.elem,a,!0)||c||1;do e=j=j||".5",i=i/j,p.style(f.elem,a,i+d),j=f.cur()/h;while(j!==1&&j!==e)}f.unit=d,f.start=i,f.end=g[1]?i+(g[1]+1)*c:c}return f}]};p.Animation=p.extend(cV,{tweener:function(a,b){p.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");var c,d=0,e=a.length;for(;d<e;d++)c=a[d],cS[c]=cS[c]||[],cS[c].unshift(b)},prefilter:function(a,b){b?cR.unshift(a):cR.push(a)}}),p.Tween=cY,cY.prototype={constructor:cY,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||"swing",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(p.cssNumber[c]?"":"px")},cur:function(){var a=cY.propHooks[this.prop];return a&&a.get?a.get(this):cY.propHooks._default.get(this)},run:function(a){var b,c=cY.propHooks[this.prop];return this.pos=b=p.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration),this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):cY.propHooks._default.set(this),this}},cY.prototype.init.prototype=cY.prototype,cY.propHooks={_default:{get:function(a){var b;return a.elem[a.prop]==null||!!a.elem.style&&a.elem.style[a.prop]!=null?(b=p.css(a.elem,a.prop,!1,""),!b||b==="auto"?0:b):a.elem[a.prop]},set:function(a){p.fx.step[a.prop]?p.fx.step[a.prop](a):a.elem.style&&(a.elem.style[p.cssProps[a.prop]]!=null||p.cssHooks[a.prop])?p.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},cY.propHooks.scrollTop=cY.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},p.each(["toggle","show","hide"],function(a,b){var c=p.fn[b];p.fn[b]=function(d,e,f){return d==null||typeof d=="boolean"||!a&&p.isFunction(d)&&p.isFunction(e)?c.apply(this,arguments):this.animate(cZ(b,!0),d,e,f)}}),p.fn.extend({fadeTo:function(a,b,c,d){return this.filter(bY).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=p.isEmptyObject(a),f=p.speed(b,c,d),g=function(){var b=cV(this,p.extend({},a),f);e&&b.stop(!0)};return e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,c,d){var e=function(a){var b=a.stop;delete a.stop,b(d)};return typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,c=a!=null&&a+"queueHooks",f=p.timers,g=p._data(this);if(c)g[c]&&g[c].stop&&e(g[c]);else for(c in g)g[c]&&g[c].stop&&cQ.test(c)&&e(g[c]);for(c=f.length;c--;)f[c].elem===this&&(a==null||f[c].queue===a)&&(f[c].anim.stop(d),b=!1,f.splice(c,1));(b||!d)&&p.dequeue(this,a)})}}),p.each({slideDown:cZ("show"),slideUp:cZ("hide"),slideToggle:cZ("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){p.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),p.speed=function(a,b,c){var d=a&&typeof a=="object"?p.extend({},a):{complete:c||!c&&b||p.isFunction(a)&&a,duration:a,easing:c&&b||b&&!p.isFunction(b)&&b};d.duration=p.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in p.fx.speeds?p.fx.speeds[d.duration]:p.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";return d.old=d.complete,d.complete=function(){p.isFunction(d.old)&&d.old.call(this),d.queue&&p.dequeue(this,d.queue)},d},p.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},p.timers=[],p.fx=cY.prototype.init,p.fx.tick=function(){var a,b=p.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||p.fx.stop()},p.fx.timer=function(a){a()&&p.timers.push(a)&&!cN&&(cN=setInterval(p.fx.tick,p.fx.interval))},p.fx.interval=13,p.fx.stop=function(){clearInterval(cN),cN=null},p.fx.speeds={slow:600,fast:200,_default:400},p.fx.step={},p.expr&&p.expr.filters&&(p.expr.filters.animated=function(a){return p.grep(p.timers,function(b){return a===b.elem}).length});var c$=/^(?:body|html)$/i;p.fn.offset=function(a){if(arguments.length)return a===b?this:this.each(function(b){p.offset.setOffset(this,a,b)});var c,d,e,f,g,h,i,j,k,l,m=this[0],n=m&&m.ownerDocument;if(!n)return;return(e=n.body)===m?p.offset.bodyOffset(m):(d=n.documentElement,p.contains(d,m)?(c=m.getBoundingClientRect(),f=c_(n),g=d.clientTop||e.clientTop||0,h=d.clientLeft||e.clientLeft||0,i=f.pageYOffset||d.scrollTop,j=f.pageXOffset||d.scrollLeft,k=c.top+i-g,l=c.left+j-h,{top:k,left:l}):{top:0,left:0})},p.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;return p.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(p.css(a,"marginTop"))||0,c+=parseFloat(p.css(a,"marginLeft"))||0),{top:b,left:c}},setOffset:function(a,b,c){var d=p.css(a,"position");d==="static"&&(a.style.position="relative");var e=p(a),f=e.offset(),g=p.css(a,"top"),h=p.css(a,"left"),i=(d==="absolute"||d==="fixed")&&p.inArray("auto",[g,h])>-1,j={},k={},l,m;i?(k=e.position(),l=k.top,m=k.left):(l=parseFloat(g)||0,m=parseFloat(h)||0),p.isFunction(b)&&(b=b.call(a,c,f)),b.top!=null&&(j.top=b.top-f.top+l),b.left!=null&&(j.left=b.left-f.left+m),"using"in b?b.using.call(a,j):e.css(j)}},p.fn.extend({position:function(){if(!this[0])return;var a=this[0],b=this.offsetParent(),c=this.offset(),d=c$.test(b[0].nodeName)?{top:0,left:0}:b.offset();return c.top-=parseFloat(p.css(a,"marginTop"))||0,c.left-=parseFloat(p.css(a,"marginLeft"))||0,d.top+=parseFloat(p.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(p.css(b[0],"borderLeftWidth"))||0,{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||e.body;while(a&&!c$.test(a.nodeName)&&p.css(a,"position")==="static")a=a.offsetParent;return a||e.body})}}),p.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);p.fn[a]=function(e){return p.access(this,function(a,e,f){var g=c_(a);if(f===b)return g?c in g?g[c]:g.document.documentElement[e]:a[e];g?g.scrollTo(d?p(g).scrollLeft():f,d?f:p(g).scrollTop()):a[e]=f},a,e,arguments.length,null)}}),p.each({Height:"height",Width:"width"},function(a,c){p.each({padding:"inner"+a,content:c,"":"outer"+a},function(d,e){p.fn[e]=function(e,f){var g=arguments.length&&(d||typeof e!="boolean"),h=d||(e===!0||f===!0?"margin":"border");return p.access(this,function(c,d,e){var f;return p.isWindow(c)?c.document.documentElement["client"+a]:c.nodeType===9?(f=c.documentElement,Math.max(c.body["scroll"+a],f["scroll"+a],c.body["offset"+a],f["offset"+a],f["client"+a])):e===b?p.css(c,d,e,h):p.style(c,d,e,h)},c,g?e:b,g)}})}),a.jQuery=a.$=p,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return p})})(window);
    47.6 \ No newline at end of file
    48.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    48.2 +++ b/endpoint/WebContent/js/jquery-ui-1.8.23.custom.min.js	Fri May 02 17:39:27 2014 +0200
    48.3 @@ -0,0 +1,21 @@
    48.4 +/*! jQuery UI - v1.8.23 - 2012-08-15
    48.5 +* https://github.com/jquery/jquery-ui
    48.6 +* Includes: jquery.ui.core.js
    48.7 +* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */
    48.8 +(function(a,b){function c(b,c){var e=b.nodeName.toLowerCase();if("area"===e){var f=b.parentNode,g=f.name,h;return!b.href||!g||f.nodeName.toLowerCase()!=="map"?!1:(h=a("img[usemap=#"+g+"]")[0],!!h&&d(h))}return(/input|select|textarea|button|object/.test(e)?!b.disabled:"a"==e?b.href||c:c)&&d(b)}function d(b){return!a(b).parents().andSelf().filter(function(){return a.curCSS(this,"visibility")==="hidden"||a.expr.filters.hidden(this)}).length}a.ui=a.ui||{};if(a.ui.version)return;a.extend(a.ui,{version:"1.8.23",keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91}}),a.fn.extend({propAttr:a.fn.prop||a.fn.attr,_focus:a.fn.focus,focus:function(b,c){return typeof b=="number"?this.each(function(){var d=this;setTimeout(function(){a(d).focus(),c&&c.call(d)},b)}):this._focus.apply(this,arguments)},scrollParent:function(){var b;return a.browser.msie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?b=this.parents().filter(function(){return/(relative|absolute|fixed)/.test(a.curCSS(this,"position",1))&&/(auto|scroll)/.test(a.curCSS(this,"overflow",1)+a.curCSS(this,"overflow-y",1)+a.curCSS(this,"overflow-x",1))}).eq(0):b=this.parents().filter(function(){return/(auto|scroll)/.test(a.curCSS(this,"overflow",1)+a.curCSS(this,"overflow-y",1)+a.curCSS(this,"overflow-x",1))}).eq(0),/fixed/.test(this.css("position"))||!b.length?a(document):b},zIndex:function(c){if(c!==b)return this.css("zIndex",c);if(this.length){var d=a(this[0]),e,f;while(d.length&&d[0]!==document){e=d.css("position");if(e==="absolute"||e==="relative"||e==="fixed"){f=parseInt(d.css("zIndex"),10);if(!isNaN(f)&&f!==0)return f}d=d.parent()}}return 0},disableSelection:function(){return this.bind((a.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(a){a.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),a("<a>").outerWidth(1).jquery||a.each(["Width","Height"],function(c,d){function h(b,c,d,f){return a.each(e,function(){c-=parseFloat(a.curCSS(b,"padding"+this,!0))||0,d&&(c-=parseFloat(a.curCSS(b,"border"+this+"Width",!0))||0),f&&(c-=parseFloat(a.curCSS(b,"margin"+this,!0))||0)}),c}var e=d==="Width"?["Left","Right"]:["Top","Bottom"],f=d.toLowerCase(),g={innerWidth:a.fn.innerWidth,innerHeight:a.fn.innerHeight,outerWidth:a.fn.outerWidth,outerHeight:a.fn.outerHeight};a.fn["inner"+d]=function(c){return c===b?g["inner"+d].call(this):this.each(function(){a(this).css(f,h(this,c)+"px")})},a.fn["outer"+d]=function(b,c){return typeof b!="number"?g["outer"+d].call(this,b):this.each(function(){a(this).css(f,h(this,b,!0,c)+"px")})}}),a.extend(a.expr[":"],{data:a.expr.createPseudo?a.expr.createPseudo(function(b){return function(c){return!!a.data(c,b)}}):function(b,c,d){return!!a.data(b,d[3])},focusable:function(b){return c(b,!isNaN(a.attr(b,"tabindex")))},tabbable:function(b){var d=a.attr(b,"tabindex"),e=isNaN(d);return(e||d>=0)&&c(b,!e)}}),a(function(){var b=document.body,c=b.appendChild(c=document.createElement("div"));c.offsetHeight,a.extend(c.style,{minHeight:"100px",height:"auto",padding:0,borderWidth:0}),a.support.minHeight=c.offsetHeight===100,a.support.selectstart="onselectstart"in c,b.removeChild(c).style.display="none"}),a.curCSS||(a.curCSS=a.css),a.extend(a.ui,{plugin:{add:function(b,c,d){var e=a.ui[b].prototype;for(var f in d)e.plugins[f]=e.plugins[f]||[],e.plugins[f].push([c,d[f]])},call:function(a,b,c){var d=a.plugins[b];if(!d||!a.element[0].parentNode)return;for(var e=0;e<d.length;e++)a.options[d[e][0]]&&d[e][1].apply(a.element,c)}},contains:function(a,b){return document.compareDocumentPosition?a.compareDocumentPosition(b)&16:a!==b&&a.contains(b)},hasScroll:function(b,c){if(a(b).css("overflow")==="hidden")return!1;var d=c&&c==="left"?"scrollLeft":"scrollTop",e=!1;return b[d]>0?!0:(b[d]=1,e=b[d]>0,b[d]=0,e)},isOverAxis:function(a,b,c){return a>b&&a<b+c},isOver:function(b,c,d,e,f,g){return a.ui.isOverAxis(b,d,f)&&a.ui.isOverAxis(c,e,g)}})})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15
    48.9 +* https://github.com/jquery/jquery-ui
   48.10 +* Includes: jquery.ui.widget.js
   48.11 +* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */
   48.12 +(function(a,b){if(a.cleanData){var c=a.cleanData;a.cleanData=function(b){for(var d=0,e;(e=b[d])!=null;d++)try{a(e).triggerHandler("remove")}catch(f){}c(b)}}else{var d=a.fn.remove;a.fn.remove=function(b,c){return this.each(function(){return c||(!b||a.filter(b,[this]).length)&&a("*",this).add([this]).each(function(){try{a(this).triggerHandler("remove")}catch(b){}}),d.call(a(this),b,c)})}}a.widget=function(b,c,d){var e=b.split(".")[0],f;b=b.split(".")[1],f=e+"-"+b,d||(d=c,c=a.Widget),a.expr[":"][f]=function(c){return!!a.data(c,b)},a[e]=a[e]||{},a[e][b]=function(a,b){arguments.length&&this._createWidget(a,b)};var g=new c;g.options=a.extend(!0,{},g.options),a[e][b].prototype=a.extend(!0,g,{namespace:e,widgetName:b,widgetEventPrefix:a[e][b].prototype.widgetEventPrefix||b,widgetBaseClass:f},d),a.widget.bridge(b,a[e][b])},a.widget.bridge=function(c,d){a.fn[c]=function(e){var f=typeof e=="string",g=Array.prototype.slice.call(arguments,1),h=this;return e=!f&&g.length?a.extend.apply(null,[!0,e].concat(g)):e,f&&e.charAt(0)==="_"?h:(f?this.each(function(){var d=a.data(this,c),f=d&&a.isFunction(d[e])?d[e].apply(d,g):d;if(f!==d&&f!==b)return h=f,!1}):this.each(function(){var b=a.data(this,c);b?b.option(e||{})._init():a.data(this,c,new d(e,this))}),h)}},a.Widget=function(a,b){arguments.length&&this._createWidget(a,b)},a.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",options:{disabled:!1},_createWidget:function(b,c){a.data(c,this.widgetName,this),this.element=a(c),this.options=a.extend(!0,{},this.options,this._getCreateOptions(),b);var d=this;this.element.bind("remove."+this.widgetName,function(){d.destroy()}),this._create(),this._trigger("create"),this._init()},_getCreateOptions:function(){return a.metadata&&a.metadata.get(this.element[0])[this.widgetName]},_create:function(){},_init:function(){},destroy:function(){this.element.unbind("."+this.widgetName).removeData(this.widgetName),this.widget().unbind("."+this.widgetName).removeAttr("aria-disabled").removeClass(this.widgetBaseClass+"-disabled "+"ui-state-disabled")},widget:function(){return this.element},option:function(c,d){var e=c;if(arguments.length===0)return a.extend({},this.options);if(typeof c=="string"){if(d===b)return this.options[c];e={},e[c]=d}return this._setOptions(e),this},_setOptions:function(b){var c=this;return a.each(b,function(a,b){c._setOption(a,b)}),this},_setOption:function(a,b){return this.options[a]=b,a==="disabled"&&this.widget()[b?"addClass":"removeClass"](this.widgetBaseClass+"-disabled"+" "+"ui-state-disabled").attr("aria-disabled",b),this},enable:function(){return this._setOption("disabled",!1)},disable:function(){return this._setOption("disabled",!0)},_trigger:function(b,c,d){var e,f,g=this.options[b];d=d||{},c=a.Event(c),c.type=(b===this.widgetEventPrefix?b:this.widgetEventPrefix+b).toLowerCase(),c.target=this.element[0],f=c.originalEvent;if(f)for(e in f)e in c||(c[e]=f[e]);return this.element.trigger(c,d),!(a.isFunction(g)&&g.call(this.element[0],c,d)===!1||c.isDefaultPrevented())}}})(jQuery);;/*! jQuery UI - v1.8.23 - 2012-08-15
   48.13 +* https://github.com/jquery/jquery-ui
   48.14 +* Includes: jquery.ui.mouse.js
   48.15 +* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */
   48.16 +(function(a,b){var c=!1;a(document).mouseup(function(a){c=!1}),a.widget("ui.mouse",{options:{cancel:":input,option",distance:1,delay:0},_mouseInit:function(){var b=this;this.element.bind("mousedown."+this.widgetName,function(a){return b._mouseDown(a)}).bind("click."+this.widgetName,function(c){if(!0===a.data(c.target,b.widgetName+".preventClickEvent"))return a.removeData(c.target,b.widgetName+".preventClickEvent"),c.stopImmediatePropagation(),!1}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName),this._mouseMoveDelegate&&a(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(b){if(c)return;this._mouseStarted&&this._mouseUp(b),this._mouseDownEvent=b;var d=this,e=b.which==1,f=typeof this.options.cancel=="string"&&b.target.nodeName?a(b.target).closest(this.options.cancel).length:!1;if(!e||f||!this._mouseCapture(b))return!0;this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){d.mouseDelayMet=!0},this.options.delay));if(this._mouseDistanceMet(b)&&this._mouseDelayMet(b)){this._mouseStarted=this._mouseStart(b)!==!1;if(!this._mouseStarted)return b.preventDefault(),!0}return!0===a.data(b.target,this.widgetName+".preventClickEvent")&&a.removeData(b.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(a){return d._mouseMove(a)},this._mouseUpDelegate=function(a){return d._mouseUp(a)},a(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),b.preventDefault(),c=!0,!0},_mouseMove:function(b){return!a.browser.msi