commit b1d73a725dc7ab9fb7eb789296efd2b7e4b08306 Author: n1474335 Date: Mon Nov 28 10:42:58 2016 +0000 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100755 index 00000000..482be5c7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +node_modules +npm-debug.log +build/dev +docs/* +!docs/*.conf.json +!docs/*.ico diff --git a/Gruntfile.js b/Gruntfile.js new file mode 100755 index 00000000..2963e138 --- /dev/null +++ b/Gruntfile.js @@ -0,0 +1,444 @@ +module.exports = function(grunt) { + grunt.file.defaultEncoding = "utf8"; + grunt.file.preserveBOM = false; + + // Tasks + grunt.registerTask("dev", + "A persistent task which creates a development build whenever source files are modified.", + ["clean:dev", "concat:css", "concat:js", "copy:html_dev", "copy:static_dev", "chmod:build", "watch"]); + + grunt.registerTask("prod", + "Creates a production-ready build. Use the --msg flag to add a compile message.", + ["jshint", "exec:stats", "clean", "jsdoc", "concat", "copy", "cssmin", "uglify:prod", "inline", "htmlmin", "chmod"]); + + grunt.registerTask("docs", + "Compiles documentation in the /docs directory.", + ["clean:docs", "jsdoc", "chmod:docs"]); + + grunt.registerTask("stats", + "Provides statistics about the code base such as how many lines there are as well as details of file sizes before and after compression.", + ["concat:js", "uglify:prod", "exec:stats", "exec:repo_size", "exec:display_stats"]); + + grunt.registerTask("default", + "Lints the code base and shows stats", + ["jshint", "exec:stats", "exec:display_stats"]); + + grunt.registerTask("doc", "docs"); + grunt.registerTask("lint", "jshint"); + + + // Load tasks provided by each plugin + grunt.loadNpmTasks("grunt-contrib-jshint"); + grunt.loadNpmTasks("grunt-jsdoc"); + grunt.loadNpmTasks("grunt-contrib-clean"); + grunt.loadNpmTasks("grunt-contrib-concat"); + grunt.loadNpmTasks("grunt-contrib-copy"); + grunt.loadNpmTasks("grunt-contrib-uglify"); + grunt.loadNpmTasks("grunt-contrib-cssmin"); + grunt.loadNpmTasks("grunt-contrib-htmlmin"); + grunt.loadNpmTasks("grunt-inline-alt"); + grunt.loadNpmTasks("grunt-chmod"); + grunt.loadNpmTasks("grunt-exec"); + grunt.loadNpmTasks("grunt-contrib-watch"); + + + // JS includes + var js_files = [ + // Third party framework libraries + "src/js/lib/jquery-2.1.1.js", + "src/js/lib/bootstrap-3.3.6.js", + "src/js/lib/split.js", + "src/js/lib/bootstrap-switch.js", + "src/js/lib/yahoo.js", + "src/js/lib/snowfall.jquery.js", + + // Third party operation libraries + "src/js/lib/cryptojs/core.js", + "src/js/lib/cryptojs/x64-core.js", + "src/js/lib/cryptojs/enc-base64.js", + "src/js/lib/cryptojs/enc-utf16.js", + "src/js/lib/cryptojs/md5.js", + "src/js/lib/cryptojs/evpkdf.js", + "src/js/lib/cryptojs/cipher-core.js", + "src/js/lib/cryptojs/mode-cfb.js", + "src/js/lib/cryptojs/mode-ctr-gladman.js", + "src/js/lib/cryptojs/mode-ctr.js", + "src/js/lib/cryptojs/mode-ecb.js", + "src/js/lib/cryptojs/mode-ofb.js", + "src/js/lib/cryptojs/format-hex.js", + "src/js/lib/cryptojs/lib-typedarrays.js", + "src/js/lib/cryptojs/pad-ansix923.js", + "src/js/lib/cryptojs/pad-iso10126.js", + "src/js/lib/cryptojs/pad-iso97971.js", + "src/js/lib/cryptojs/pad-nopadding.js", + "src/js/lib/cryptojs/pad-zeropadding.js", + "src/js/lib/cryptojs/aes.js", + "src/js/lib/cryptojs/hmac.js", + "src/js/lib/cryptojs/rabbit-legacy.js", + "src/js/lib/cryptojs/rabbit.js", + "src/js/lib/cryptojs/ripemd160.js", + "src/js/lib/cryptojs/sha1.js", + "src/js/lib/cryptojs/sha256.js", + "src/js/lib/cryptojs/sha224.js", + "src/js/lib/cryptojs/sha512.js", + "src/js/lib/cryptojs/sha384.js", + "src/js/lib/cryptojs/sha3.js", + "src/js/lib/cryptojs/tripledes.js", + "src/js/lib/cryptojs/rc4.js", + "src/js/lib/cryptojs/pbkdf2.js", + "src/js/lib/jsbn/jsbn.js", + "src/js/lib/jsbn/jsbn2.js", + "src/js/lib/jsbn/base64.js", + "src/js/lib/jsbn/ec.js", + "src/js/lib/jsbn/prng4.js", + "src/js/lib/jsbn/rng.js", + "src/js/lib/jsbn/rsa.js", + "src/js/lib/jsbn/sec.js", + "src/js/lib/jsrasign/asn1-1.0.js", + "src/js/lib/jsrasign/asn1hex-1.1.js", + "src/js/lib/jsrasign/asn1x509-1.0.js", + "src/js/lib/jsrasign/base64x-1.1.js", + "src/js/lib/jsrasign/crypto-1.1.js", + "src/js/lib/jsrasign/dsa-modified-1.0.js", + "src/js/lib/jsrasign/ecdsa-modified-1.0.js", + "src/js/lib/jsrasign/ecparam-1.0.js", + "src/js/lib/jsrasign/keyutil-1.0.js", + "src/js/lib/jsrasign/x509-1.1.js", + "src/js/lib/blowfish.dojo.js", + "src/js/lib/rawdeflate.js", + "src/js/lib/rawinflate.js", + "src/js/lib/zip.js", + "src/js/lib/unzip.js", + "src/js/lib/zlib_and_gzip.js", + "src/js/lib/bzip2.js", + "src/js/lib/punycode.js", + "src/js/lib/uas_parser.js", + "src/js/lib/esprima.js", + "src/js/lib/escodegen.browser.js", + "src/js/lib/esmangle.min.js", + "src/js/lib/diff.js", + "src/js/lib/moment.js", + "src/js/lib/moment-timezone.js", + "src/js/lib/prettify.js", + "src/js/lib/vkbeautify.js", + "src/js/lib/Sortable.js", + "src/js/lib/bootstrap-colorpicker.js", + + // Custom libraries + "src/js/lib/canvas_components.js", + + // Utility functions + "src/js/core/Utils.js", + + // Operation objects + "src/js/operations/*.js", + + // Core framework objects + "src/js/core/*.js", + "src/js/config/Categories.js", + "src/js/config/OperationConfig.js", + + // HTML view objects + "src/js/views/html/*.js", + "!src/js/views/html/main.js", + + // Start the app! + "src/js/views/html/main.js", + ]; + + var banner = '/**\n\ + * CyberChef - The Cyber Swiss Army Knife\n\ + *\n\ + * @copyright Crown Copyright 2016\n\ + * @license Apache-2.0\n\ + *\n\ + * Copyright 2016 Crown Copyright\n\ + *\n\ + * Licensed under the Apache License, Version 2.0 (the "License");\n\ + * you may not use this file except in compliance with the License.\n\ + * You may obtain a copy of the License at\n\ + *\n\ + * http://www.apache.org/licenses/LICENSE-2.0\n\ + *\n\ + * Unless required by applicable law or agreed to in writing, software\n\ + * distributed under the License is distributed on an "AS IS" BASIS,\n\ + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n\ + * See the License for the specific language governing permissions and\n\ + * limitations under the License.\n\ + */\n'; + + var template_options = { + data: { + compile_msg: grunt.option("compile-msg") || grunt.option("msg") || "", + codebase_stats: grunt.file.read("src/static/stats.txt").split("\n").join("
") + } + }; + + // Project configuration + grunt.initConfig({ + jshint: { + options: { + jshintrc: "src/js/.jshintrc" + }, + gruntfile: ["Gruntfile.js"], + core: ["src/js/core/**/*.js"], + config: ["src/js/config/**/*.js"], + views: ["src/js/views/**/*.js"], + operations: ["src/js/operations/**/*.js"], + }, + jsdoc: { + options: { + destination: "docs", + template: "node_modules/ink-docstrap/template", + recurse: true, + readme: "./README.md", + configure: "docs/jsdoc.conf.json" + }, + all: { + src: [ + "src/js/**/*.js", + "!src/js/lib/**/*", + ], + } + }, + clean: { + dev: ["build/dev/*"], + prod: ["build/prod/*"], + docs: ["docs/*", "!docs/*.conf.json", "!docs/*.ico"], + }, + concat: { + options: { + process: template_options + }, + css: { + options: { + banner: banner.replace(/\/\*\*/g, "/*!"), + process: function(content, srcpath) { + // Change special comments from /** to /*! to comply with cssmin + content = content.replace(/^\/\*\* /g, "/*! "); + return grunt.template.process(content); + } + }, + src: [ + "src/css/lib/**/*.css", + "src/css/structure/**/*.css", + "src/css/themes/classic.css" + ], + dest: "build/dev/styles.css" + }, + js: { + options: { + banner: '"use strict";\n' + }, + src: js_files, + dest: "build/dev/scripts.js" + } + }, + copy: { + html_dev: { + options: { + process: function(content, srcpath) { + return grunt.template.process(content, template_options); + } + }, + src: "src/html/index.html", + dest: "build/dev/index.html" + }, + html_prod: { + options: { + process: function(content, srcpath) { + return grunt.template.process(content, template_options); + } + }, + src: "src/html/index.html", + dest: "build/prod/index.html" + }, + html_inline: { + options: { + process: function(content, srcpath) { + // TODO: Do all this in Jade + content = content.replace( + 'Download CyberChef', + 'Compile time: ' + grunt.template.today("dd/mm/yyyy HH:MM:ss") + ' UTC'); + return grunt.template.process(content, template_options); + } + }, + src: "src/html/index.html", + dest: "build/prod/cyberchef.htm" + }, + static_dev: { + files: [ + { + expand: true, + cwd: "src/static/", + src: [ + "**/*", + "**/.*", + "!stats.txt" + ], + dest: "build/dev/" + } + ] + }, + static_prod: { + files: [ + { + expand: true, + cwd: "src/static/", + src: [ + "**/*", + "**/.*", + "!stats.txt" + ], + dest: "build/prod/" + } + ] + } + }, + uglify: { + options: { + preserveComments: function(node, comment) { + if (comment.value.indexOf("* @license") === 0) return true; + return false; + }, + screwIE8: true, + ASCIIOnly: true, + beautify: { + beautify: false, + inline_script: true, + ascii_only: true, + screw_ie8: true + }, + compress: { + screw_ie8: true + }, + banner: banner + }, + prod: { + src: "build/dev/scripts.js", + dest: "build/prod/scripts.js" + } + }, + cssmin: { + prod: { + src: "build/dev/styles.css", + dest: "build/prod/styles.css" + } + }, + htmlmin: { + prod: { + options: { + removeComments: true, + collapseWhitespace: true, + minifyJS: true, + minifyCSS: true + }, + src: "build/prod/index.html", + dest: "build/prod/index.html" + }, + inline: { + options: { + removeComments: true, + collapseWhitespace: true, + minifyJS: false, + minifyCSS: false + }, + src: "build/prod/cyberchef.htm", + dest: "build/prod/cyberchef.htm" + } + }, + inline: { + options: { + tag: "", + inlineTagAttributes: { + js: "type='application/javascript'", + css: "type='text/css'" + } + }, + prod: { + src: "build/prod/cyberchef.htm", + dest: "build/prod/cyberchef.htm" + } + }, + chmod: { + build: { + options: { + mode: "755", + }, + src: ["build/**/*", "build/**/.htaccess", "build/"] + }, + docs: { + options: { + mode: "755", + }, + src: ["docs/**/*", "docs/"] + } + }, + exec: { + repo_size: { + command: [ + "git ls-files | wc -l | xargs printf '\n%b\ttracked files\n'", + "du -hs | egrep -o '^[^\t]*' | xargs printf '%b\trepository size\n'" + ].join(";"), + stderr: false + }, + stats: { + command: "rm src/static/stats.txt;" + + [ + "ls src/ -R1 | grep '^$' -v | grep ':$' -v | wc -l | xargs printf '%b\tsource files\n'", + "find src/ -regex '.*\..*' -print | xargs cat | wc -l | xargs printf '%b\tlines\n'", + "du -hs src/ | pcregrep -o '^[^\t]*' | xargs printf '%b\tsize\n'", + + "ls src/js/ -R1 | grep '\.js$' | wc -l | xargs printf '\n%b\tJavaScript source files\n'", + "find src/js/ -regex '.*\.js' -print | xargs cat | wc -l | xargs printf '%b\tlines\n'", + "find src/js/ -regex '.*\.js' -exec du -hcs {} \+ | tail -n1 | egrep -o '^[^\t]*' | xargs printf '%b\tsize\n'", + + "find src/js/ -regex '.*/lib/.*\.js' -print | wc -l | xargs printf '\n%b\tthird party JavaScript source files\n'", + "find src/js/ -regex '.*/lib/.*\.js' -print | xargs cat | wc -l | xargs printf '%b\tlines\n'", + "find src/js/ -regex '.*/lib/.*\.js' -exec du -hcs {} \+ | tail -n1 | egrep -o '^[^\t]*' | xargs printf '%b\tsize\n'", + + "find src/js/ -regex '.*\.js' -not -regex '.*/lib/.*' -print | wc -l | xargs printf '\n%b\tfirst party JavaScript source files\n'", + "find src/js/ -regex '.*\.js' -not -regex '.*/lib/.*' -print | xargs cat | wc -l | xargs printf '%b\tlines\n'", + "find src/js/ -regex '.*\.js' -not -regex '.*/lib/.*' -exec du -hcs {} \+ | tail -n1 | egrep -o '^[^\t]*' | xargs printf '%b\tsize\n'", + + "du build/dev/scripts.js -h | egrep -o '^[^\t]*' | xargs printf '\n%b\tuncompressed JavaScript size\n'", + "du build/prod/scripts.js -h | egrep -o '^[^\t]*' | xargs printf '%b\tcompressed JavaScript size\n'", + + "grep -E '^\\s+name: ' src/js/config/Categories.js | wc -l | xargs printf '\n%b\tcategories\n'", + "grep -E '^\\s+\"[A-Za-z0-9 \\-]+\": {' src/js/config/OperationConfig.js | wc -l | xargs printf '%b\toperations\n'", + + ].join(" >> src/static/stats.txt;") + " >> src/static/stats.txt;", + stderr: false + }, + display_stats: { + command: "cat src/static/stats.txt" + }, + clean_git: { + command: "git gc --prune=now --aggressive" + }, + }, + watch: { + css: { + files: "src/css/**/*.css", + tasks: ["concat:css", "chmod:build"] + }, + js: { + files: "src/js/**/*.js", + tasks: ["concat:js_all", "chmod:build"] + }, + html: { + files: "src/html/**/*.html", + tasks: ["copy:html_dev", "chmod:build"] + }, + static: { + files: ["src/static/**/*", "src/static/**/.*"], + tasks: ["copy:static_dev", "chmod:build"] + }, + grunt: { + files: "Gruntfile.js", + tasks: ["clean:dev", "concat:css", "concat:js_all", "copy:html_dev", "copy:static_dev", "chmod:build"] + } + }, + }); + +}; diff --git a/LICENSE b/LICENSE new file mode 100755 index 00000000..7a4a3ea2 --- /dev/null +++ b/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100755 index 00000000..c49873d6 --- /dev/null +++ b/README.md @@ -0,0 +1,89 @@ +# CyberChef + +####*The Cyber Swiss Army Knife* + +CyberChef is a simple, intuitive web app for carrying out all manner of "cyber" operations within a web browser. These operations include creating hexdumps, simple encoding like XOR or Base64, more complex encryption like AES, DES and Blowfish, data compression and decompression, calculating hashes and checksums, IPv6 and X.509 parsing, and much more. + +The tool is designed to enable both technical and non-technical analysts to manipulate data in complex ways without having to deal with complex tools or algorithms. It was conceived, designed, built and incrementally improved by an analyst in their 10% innovation time over several years. Every effort has been made to structure the code in a readable and extendable format, however it should be noted that the analyst is not a professional developer and the code has not been peer-reviewed for compliance with a formal specification. + +## Live demo + +CyberChef is still under active development. As a result, it shouldn't be considered a finished product. There is still testing and bug fixing to do, new features to be added and additional documentation to write. Please contribute! + +Cryptographic operations in CyberChef should not be relied upon to provide security in any situation. No guarantee is offered for their correctness. + +[A live demo can be found here][1] - have fun! +Note: Use Chrome or Firefox, see the Browser Support section below for details. + + +## How it works + +There are four main areas in CyberChef: + + 1. The **input** box in the top right, where you can paste, type or drag the data you want to operate on. + 2. The **output** box in the bottom right, where the outcome of the specified processing will be displayed. + 3. The **operations** list on the far left, where you can find all the operations that CyberChef is capable of in categorised lists, or by searching. + 4. The **recipe** area in the middle, where you drag the operations that you want to use and specify arguments and options. + +You can use as many operations as you like in simple or complex ways. Some examples are as follows: + + - [Decode a Base64-encoded string][2] + - [Convert a date and time to a different time zone][3] + - [Parse a Teredo IPv6 address][4] + - [Convert data from a hexdump, then decompress][5] + - [Display multiple timestamps as full dates][6] + - [Carry out different operations on data of different types][7] + + +## Features + + - Drag and drop + - Operations can be dragged in and out of the recipe list, or reorganised. + - Files can be dragged over the input box to load them directly. + - Auto Bake + - Whenever you modify the input or the recipe, CyberChef will automatically “bake” for you and produce the output immediately. + - This can be turned off and operated manually if it is affecting performance (if the input is very large, for instance). + - If any bake takes longer than 200 milliseconds, auto bake will be switched off automatically to prevent further performance issues. + - Breakpoints + - You can set breakpoints on any operation in your recipe to pause execution before running it. + - You can also step through the recipe one operation at a time to see what the data looks like at each stage. + - Save and load recipes + - If you come up with an awesome recipe that you know you’ll want to use again, just click save and add it to your local storage. It'll be waiting for you next time you visit CyberChef. + - You can also copy a URL which includes your recipe and input which can be shared with others. + - Search + - If you know the name of the operation you want or a word associated with it, start typing it into the search field and any matching operations will immediately be shown. + - Highlighting + - When you highlight text in the input or output, the offset and length values will be displayed and, if possible, the corresponding data will be highlighted in the output or input respectively (example: [highlight the word 'question' in the input to see where it appears in the output][8]). + - Save to file and load from file + - You can save the output to a file at any time or load a file by dragging and dropping it into the input field (note that files larger than about 500kb may cause your browser to hang or even crash due to the way that browsers handle large amounts of textual data). + - CyberChef is entirely client-side + - It should be noted that none of your input or recipe configuration is ever sent to the CyberChef web server - all processing is carried out within your browser, on your own computer. + - Due to this feature, CyberChef can be compiled into a single HTML file. You can download this file and drop it into a virtual machine, share it with other people, or use it independently on your desktop. + + +## Browser support + +CyberChef works well in modern versions of Google Chrome and Mozilla Firefox. + +To aid in the efficient development of new features and operations, there has been no attempt to maintain support for any version of Microsoft Internet Explorer. + +Microsoft Edge is currently unsupported, but if anyone would like to contribute compatibility fixes, they would be appreciated. + + +## Contributing + +An installation walkthrough, how-to guides for adding new operations, descriptions of the repository structure, available data types and coding conventions can all be found in the project [wiki pages](#### TO BE REPLACED ####). + + - Sign the [GCHQ Contributor Licence Agreement](https://github.com/gchq/Gaffer/wiki/GCHQ-OSS-Contributor-License-Agreement-V1.0) + - Push your changes to your fork. + - Submit a pull request. + + + [1]: https://gchq.github.io/cyberchef + [2]: https://gchq.github.io/cyberchef/?recipe=%5B%7B%22op%22%3A%22From%20Base64%22%2C%22args%22%3A%5B%22A-Za-z0-9%2B%2F%3D%22%2Ctrue%5D%7D%5D&input=VTI4Z2JHOXVaeUJoYm1RZ2RHaGhibXR6SUdadmNpQmhiR3dnZEdobElHWnBjMmd1 + [3]: https://gchq.github.io/cyberchef/?recipe=%5B%7B%22op%22%3A%22Translate%20DateTime%20Format%22%2C%22args%22%3A%5B%22Standard%20date%20and%20time%22%2C%22DD%2FMM%2FYYYY%20HH%3Amm%3Ass%22%2C%22UTC%22%2C%22dddd%20Do%20MMMM%20YYYY%20HH%3Amm%3Ass%20Z%20z%22%2C%22Australia%2FQueensland%22%5D%7D%5D&input=MTUvMDYvMjAxNSAyMDo0NTowMA + [4]: https://gchq.github.io/cyberchef/?recipe=%5B%7B%22op%22%3A%22Parse%20IPv6%20address%22%2C%22args%22%3A%5B%5D%7D%5D&input=MjAwMTowMDAwOjQxMzY6ZTM3ODo4MDAwOjYzYmY6M2ZmZjpmZGQy + [5]: https://gchq.github.io/cyberchef/?recipe=%5B%7B%22op%22%3A%22From%20Hexdump%22%2C%22args%22%3A%5B%5D%7D%2C%7B%22op%22%3A%22Gunzip%22%2C%22args%22%3A%5B%5D%7D%5D&input=MDAwMDAwMDAgIDFmIDhiIDA4IDAwIDEyIGJjIGYzIDU3IDAwIGZmIDBkIGM3IGMxIDA5IDAwIDIwICB8Li4uLi6881cu%2Fy7HwS4uIHwKMDAwMDAwMTAgIDA4IDA1IGQwIDU1IGZlIDA0IDJkIGQzIDA0IDFmIGNhIDhjIDQ0IDIxIDViIGZmICB8Li7QVf4uLdMuLsouRCFb%2F3wKMDAwMDAwMjAgIDYwIGM3IGQ3IDAzIDE2IGJlIDQwIDFmIDc4IDRhIDNmIDA5IDg5IDBiIDlhIDdkICB8YMfXLi6%2BQC54Sj8uLi4ufXwKMDAwMDAwMzAgIDRlIGM4IDRlIDZkIDA1IDFlIDAxIDhiIDRjIDI0IDAwIDAwIDAwICAgICAgICAgICB8TshObS4uLi5MJC4uLnw + [6]: https://gchq.github.io/cyberchef/?recipe=%5B%7B%22op%22%3A%22Fork%22%2C%22args%22%3A%5B%22%5C%5Cn%22%2C%22%5C%5Cn%22%5D%7D%2C%7B%22op%22%3A%22From%20UNIX%20Timestamp%22%2C%22args%22%3A%5B%22Seconds%20(s)%22%5D%7D%5D&input=OTc4MzQ2ODAwCjEwMTI2NTEyMDAKMTA0NjY5NjQwMAoxMDgxMDg3MjAwCjExMTUzMDUyMDAKMTE0OTYwOTYwMA + [7]: https://gchq.github.io/cyberchef/?recipe=%5B%7B%22op%22%3A%22Fork%22%2C%22args%22%3A%5B%22%5C%5Cn%22%2C%22%5C%5Cn%22%5D%7D%2C%7B%22op%22%3A%22Conditional%20Jump%22%2C%22args%22%3A%5B%221%22%2C%222%22%2C%2210%22%5D%7D%2C%7B%22op%22%3A%22To%20Hex%22%2C%22args%22%3A%5B%22Space%22%5D%7D%2C%7B%22op%22%3A%22Return%22%2C%22args%22%3A%5B%5D%7D%2C%7B%22op%22%3A%22To%20Base64%22%2C%22args%22%3A%5B%22A-Za-z0-9%2B%2F%3D%22%5D%7D%5D&input=U29tZSBkYXRhIHdpdGggYSAxIGluIGl0ClNvbWUgZGF0YSB3aXRoIGEgMiBpbiBpdA + [8]: https://gchq.github.io/cyberchef/?recipe=%5B%7B%22op%22%3A%22XOR%22%2C%22args%22%3A%5B%22de%20ad%20be%20ef%22%2C%22Hex%22%2Cfalse%2Cfalse%5D%7D%2C%7B%22op%22%3A%22To%20Hexdump%22%2C%22args%22%3A%5B%2216%22%2Cfalse%2Cfalse%5D%7D%5D&input=VGhlIGFuc3dlciB0byB0aGUgdWx0aW1hdGUgcXVlc3Rpb24gb2YgbGlmZSwgdGhlIFVuaXZlcnNlLCBhbmQgZXZlcnl0aGluZyBpcyA0Mi4 \ No newline at end of file diff --git a/build/prod/.htaccess b/build/prod/.htaccess new file mode 100755 index 00000000..80626724 --- /dev/null +++ b/build/prod/.htaccess @@ -0,0 +1,50 @@ +# Serve up .htm files as binary files rather than text/html. +# This allows cyberchef.htm to be downloaded rather than opened in the browser. +AddType application/octet-stream .htm + +# Fix Apache bug #45023 where "-gzip" is appended to all ETags, preventing 304 responses + + RequestHeader edit "If-None-Match" "^\"(.*)-gzip\"$" "\"$1\"" + Header edit "ETag" "^\"(.*[^g][^z][^i][^p])\"$" "\"$1-gzip\"" + + +# Set gzip compression on all resources that support it + + SetOutputFilter DEFLATE + + +# Set Expires headers on various resources + + ExpiresActive On + + # 10 minutes + ExpiresDefault "access plus 600 seconds" + + # 30 days + ExpiresByType image/x-icon "access plus 2592000 seconds" + ExpiresByType image/jpeg "access plus 2592000 seconds" + ExpiresByType image/png "access plus 2592000 seconds" + ExpiresByType image/gif "access plus 2592000 seconds" + + # 7 days + ExpiresByType text/css "access plus 604800 seconds" + ExpiresByType text/javascript "access plus 604800 seconds" + ExpiresByType application/javascript "access plus 604800 seconds" + ExpiresByType text/html "access plus 604800 seconds" + + +# Set Cache-Control headers on various resources + + + Header set Cache-Control "max-age=2592000, public" + + + Header set Cache-Control "max-age=600, public" + + + Header set Cache-Control "max-age=600, private, must-revalidate" + + + Header set Cache-Control "max-age=600, private, must-revalidate" + + diff --git a/build/prod/cyberchef.htm b/build/prod/cyberchef.htm new file mode 100755 index 00000000..d5e178a1 --- /dev/null +++ b/build/prod/cyberchef.htm @@ -0,0 +1,364 @@ + +CyberChef Edit
Operations
    Recipe
      Input
      Output
      \ No newline at end of file diff --git a/build/prod/images/breakpoint-16x16.png b/build/prod/images/breakpoint-16x16.png new file mode 100755 index 00000000..336df401 Binary files /dev/null and b/build/prod/images/breakpoint-16x16.png differ diff --git a/build/prod/images/bug-16x16.png b/build/prod/images/bug-16x16.png new file mode 100755 index 00000000..8098d345 Binary files /dev/null and b/build/prod/images/bug-16x16.png differ diff --git a/build/prod/images/clean-16x16.png b/build/prod/images/clean-16x16.png new file mode 100755 index 00000000..b61e5668 Binary files /dev/null and b/build/prod/images/clean-16x16.png differ diff --git a/build/prod/images/code-16x16.png b/build/prod/images/code-16x16.png new file mode 100755 index 00000000..a9b8870e Binary files /dev/null and b/build/prod/images/code-16x16.png differ diff --git a/build/prod/images/cook_female-32x32.png b/build/prod/images/cook_female-32x32.png new file mode 100755 index 00000000..0b00aa35 Binary files /dev/null and b/build/prod/images/cook_female-32x32.png differ diff --git a/build/prod/images/cook_male-32x32.png b/build/prod/images/cook_male-32x32.png new file mode 100755 index 00000000..d881c9f8 Binary files /dev/null and b/build/prod/images/cook_male-32x32.png differ diff --git a/build/prod/images/cyberchef-128x128.png b/build/prod/images/cyberchef-128x128.png new file mode 100755 index 00000000..2b8c71a0 Binary files /dev/null and b/build/prod/images/cyberchef-128x128.png differ diff --git a/build/prod/images/cyberchef-16x16.png b/build/prod/images/cyberchef-16x16.png new file mode 100755 index 00000000..b847c10e Binary files /dev/null and b/build/prod/images/cyberchef-16x16.png differ diff --git a/build/prod/images/cyberchef-256x256.png b/build/prod/images/cyberchef-256x256.png new file mode 100755 index 00000000..61835a10 Binary files /dev/null and b/build/prod/images/cyberchef-256x256.png differ diff --git a/build/prod/images/cyberchef-32x32.png b/build/prod/images/cyberchef-32x32.png new file mode 100755 index 00000000..640e4756 Binary files /dev/null and b/build/prod/images/cyberchef-32x32.png differ diff --git a/build/prod/images/cyberchef-512x512.png b/build/prod/images/cyberchef-512x512.png new file mode 100755 index 00000000..f48cd49b Binary files /dev/null and b/build/prod/images/cyberchef-512x512.png differ diff --git a/build/prod/images/cyberchef-64x64.png b/build/prod/images/cyberchef-64x64.png new file mode 100755 index 00000000..5e5a4110 Binary files /dev/null and b/build/prod/images/cyberchef-64x64.png differ diff --git a/build/prod/images/disable_deselected-16x16.png b/build/prod/images/disable_deselected-16x16.png new file mode 100755 index 00000000..0dcaf2b3 Binary files /dev/null and b/build/prod/images/disable_deselected-16x16.png differ diff --git a/build/prod/images/disable_selected-16x16.png b/build/prod/images/disable_selected-16x16.png new file mode 100755 index 00000000..f47a0b95 Binary files /dev/null and b/build/prod/images/disable_selected-16x16.png differ diff --git a/build/prod/images/download-24x24.png b/build/prod/images/download-24x24.png new file mode 100755 index 00000000..058e51b0 Binary files /dev/null and b/build/prod/images/download-24x24.png differ diff --git a/build/prod/images/erase-16x16.png b/build/prod/images/erase-16x16.png new file mode 100755 index 00000000..bc6a3fa4 Binary files /dev/null and b/build/prod/images/erase-16x16.png differ diff --git a/build/prod/images/favicon.ico b/build/prod/images/favicon.ico new file mode 100755 index 00000000..fa2deb03 Binary files /dev/null and b/build/prod/images/favicon.ico differ diff --git a/build/prod/images/favourite-16x16.png b/build/prod/images/favourite-16x16.png new file mode 100755 index 00000000..f6b99459 Binary files /dev/null and b/build/prod/images/favourite-16x16.png differ diff --git a/build/prod/images/favourite-24x24.png b/build/prod/images/favourite-24x24.png new file mode 100755 index 00000000..eb1b91be Binary files /dev/null and b/build/prod/images/favourite-24x24.png differ diff --git a/build/prod/images/help-16x16.png b/build/prod/images/help-16x16.png new file mode 100755 index 00000000..63a7069f Binary files /dev/null and b/build/prod/images/help-16x16.png differ diff --git a/build/prod/images/help-22x22.png b/build/prod/images/help-22x22.png new file mode 100755 index 00000000..ddea036d Binary files /dev/null and b/build/prod/images/help-22x22.png differ diff --git a/build/prod/images/info-16x16.png b/build/prod/images/info-16x16.png new file mode 100755 index 00000000..05f16291 Binary files /dev/null and b/build/prod/images/info-16x16.png differ diff --git a/build/prod/images/layout-16x16.png b/build/prod/images/layout-16x16.png new file mode 100755 index 00000000..3ae4db42 Binary files /dev/null and b/build/prod/images/layout-16x16.png differ diff --git a/build/prod/images/mail-16x16.png b/build/prod/images/mail-16x16.png new file mode 100755 index 00000000..6afab8a8 Binary files /dev/null and b/build/prod/images/mail-16x16.png differ diff --git a/build/prod/images/open_yellow-16x16.png b/build/prod/images/open_yellow-16x16.png new file mode 100755 index 00000000..c849a9e4 Binary files /dev/null and b/build/prod/images/open_yellow-16x16.png differ diff --git a/build/prod/images/open_yellow-24x24.png b/build/prod/images/open_yellow-24x24.png new file mode 100755 index 00000000..7ff52888 Binary files /dev/null and b/build/prod/images/open_yellow-24x24.png differ diff --git a/build/prod/images/recycle-16x16.png b/build/prod/images/recycle-16x16.png new file mode 100755 index 00000000..faff7bf6 Binary files /dev/null and b/build/prod/images/recycle-16x16.png differ diff --git a/build/prod/images/remove-16x16.png b/build/prod/images/remove-16x16.png new file mode 100755 index 00000000..b0cbfb64 Binary files /dev/null and b/build/prod/images/remove-16x16.png differ diff --git a/build/prod/images/save-16x16.png b/build/prod/images/save-16x16.png new file mode 100755 index 00000000..c9df8df6 Binary files /dev/null and b/build/prod/images/save-16x16.png differ diff --git a/build/prod/images/save-22x22.png b/build/prod/images/save-22x22.png new file mode 100755 index 00000000..51183947 Binary files /dev/null and b/build/prod/images/save-22x22.png differ diff --git a/build/prod/images/save_as-16x16.png b/build/prod/images/save_as-16x16.png new file mode 100755 index 00000000..b5d4db8b Binary files /dev/null and b/build/prod/images/save_as-16x16.png differ diff --git a/build/prod/images/settings-22x22.png b/build/prod/images/settings-22x22.png new file mode 100755 index 00000000..89c7bf6a Binary files /dev/null and b/build/prod/images/settings-22x22.png differ diff --git a/build/prod/images/speech-16x16.png b/build/prod/images/speech-16x16.png new file mode 100755 index 00000000..5519c5d7 Binary files /dev/null and b/build/prod/images/speech-16x16.png differ diff --git a/build/prod/images/stats-16x16.png b/build/prod/images/stats-16x16.png new file mode 100755 index 00000000..ebd41ef6 Binary files /dev/null and b/build/prod/images/stats-16x16.png differ diff --git a/build/prod/images/step-16x16.png b/build/prod/images/step-16x16.png new file mode 100755 index 00000000..cea525a3 Binary files /dev/null and b/build/prod/images/step-16x16.png differ diff --git a/build/prod/images/switch-16x16.png b/build/prod/images/switch-16x16.png new file mode 100755 index 00000000..4af699e7 Binary files /dev/null and b/build/prod/images/switch-16x16.png differ diff --git a/build/prod/images/thumb_down-16x16.png b/build/prod/images/thumb_down-16x16.png new file mode 100755 index 00000000..69e6663c Binary files /dev/null and b/build/prod/images/thumb_down-16x16.png differ diff --git a/build/prod/images/thumb_up-16x16.png b/build/prod/images/thumb_up-16x16.png new file mode 100755 index 00000000..0279ee24 Binary files /dev/null and b/build/prod/images/thumb_up-16x16.png differ diff --git a/build/prod/images/undo-16x16.png b/build/prod/images/undo-16x16.png new file mode 100755 index 00000000..a9ba0be9 Binary files /dev/null and b/build/prod/images/undo-16x16.png differ diff --git a/build/prod/index.html b/build/prod/index.html new file mode 100755 index 00000000..b5050adb --- /dev/null +++ b/build/prod/index.html @@ -0,0 +1,21 @@ + +CyberChef Edit
      Operations
        Recipe
          Input
          Output
          \ No newline at end of file diff --git a/build/prod/scripts.js b/build/prod/scripts.js new file mode 100755 index 00000000..bd7fd30e --- /dev/null +++ b/build/prod/scripts.js @@ -0,0 +1,267 @@ +/** + * CyberChef - The Cyber Swiss Army Knife + * + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Copyright 2016 Crown Copyright + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +"use strict";function BigInteger(a,b,c){null!=a&&("number"==typeof a?this.fromNumber(a,b,c):null==b&&"string"!=typeof a?this.fromString(a,256):this.fromString(a,b))}function nbi(){return new BigInteger(null)}function am1(a,b,c,d,e,f){for(;--f>=0;){var g=b*this[a++]+c[d]+e;e=Math.floor(g/67108864),c[d++]=67108863&g}return e}function am2(a,b,c,d,e,f){for(var g=32767&b,h=b>>15;--f>=0;){var i=32767&this[a],j=this[a++]>>15,k=h*i+j*g;i=g*i+((32767&k)<<15)+c[d]+(1073741823&e),e=(i>>>30)+(k>>>15)+h*j+(e>>>30),c[d++]=1073741823&i}return e}function am3(a,b,c,d,e,f){for(var g=16383&b,h=b>>14;--f>=0;){var i=16383&this[a],j=this[a++]>>14,k=h*i+j*g;i=g*i+((16383&k)<<14)+c[d]+e,e=(i>>28)+(k>>14)+h*j,c[d++]=268435455&i}return e}function int2char(a){return BI_RM.charAt(a)}function intAt(a,b){var c=BI_RC[a.charCodeAt(b)];return null==c?-1:c}function bnpCopyTo(a){for(var b=this.t-1;b>=0;--b)a[b]=this[b];a.t=this.t,a.s=this.s}function bnpFromInt(a){this.t=1,this.s=a<0?-1:0,a>0?this[0]=a:a<-1?this[0]=a+this.DV:this.t=0}function nbv(a){var b=nbi();return b.fromInt(a),b}function bnpFromString(a,b){var c;if(16==b)c=4;else if(8==b)c=3;else if(256==b)c=8;else if(2==b)c=1;else if(32==b)c=5;else{if(4!=b)return void this.fromRadix(a,b);c=2}this.t=0,this.s=0;for(var d=a.length,e=!1,f=0;--d>=0;){var g=8==c?255&a[d]:intAt(a,d);g<0?"-"==a.charAt(d)&&(e=!0):(e=!1,0==f?this[this.t++]=g:f+c>this.DB?(this[this.t-1]|=(g&(1<>this.DB-f):this[this.t-1]|=g<=this.DB&&(f-=this.DB))}8==c&&0!=(128&a[0])&&(this.s=-1,f>0&&(this[this.t-1]|=(1<0&&this[this.t-1]==a;)--this.t}function bnToString(a){if(this.s<0)return"-"+this.negate().toString(a);var b;if(16==a)b=4;else if(8==a)b=3;else if(2==a)b=1;else if(32==a)b=5;else{if(4!=a)return this.toRadix(a);b=2}var c,d=(1<0)for(h>h)>0&&(e=!0,f=int2char(c));g>=0;)h>(h+=this.DB-b)):(c=this[g]>>(h-=b)&d,h<=0&&(h+=this.DB,--g)),c>0&&(e=!0),e&&(f+=int2char(c));return e?f:"0"}function bnNegate(){var a=nbi();return BigInteger.ZERO.subTo(this,a),a}function bnAbs(){return this.s<0?this.negate():this}function bnCompareTo(a){var b=this.s-a.s;if(0!=b)return b;var c=this.t;if(b=c-a.t,0!=b)return this.s<0?-b:b;for(;--c>=0;)if(0!=(b=this[c]-a[c]))return b;return 0}function nbits(a){var b,c=1;return 0!=(b=a>>>16)&&(a=b,c+=16),0!=(b=a>>8)&&(a=b,c+=8),0!=(b=a>>4)&&(a=b,c+=4),0!=(b=a>>2)&&(a=b,c+=2),0!=(b=a>>1)&&(a=b,c+=1),c}function bnBitLength(){return this.t<=0?0:this.DB*(this.t-1)+nbits(this[this.t-1]^this.s&this.DM)}function bnpDLShiftTo(a,b){var c;for(c=this.t-1;c>=0;--c)b[c+a]=this[c];for(c=a-1;c>=0;--c)b[c]=0;b.t=this.t+a,b.s=this.s}function bnpDRShiftTo(a,b){for(var c=a;c=0;--c)b[c+g+1]=this[c]>>e|h,h=(this[c]&f)<=0;--c)b[c]=0;b[g]=h,b.t=this.t+g+1,b.s=this.s,b.clamp()}function bnpRShiftTo(a,b){b.s=this.s;var c=Math.floor(a/this.DB);if(c>=this.t)return void(b.t=0);var d=a%this.DB,e=this.DB-d,f=(1<>d;for(var g=c+1;g>d;d>0&&(b[this.t-c-1]|=(this.s&f)<>=this.DB;if(a.t>=this.DB;d+=this.s}else{for(d+=this.s;c>=this.DB;d-=a.s}b.s=d<0?-1:0,d<-1?b[c++]=this.DV+d:d>0&&(b[c++]=d),b.t=c,b.clamp()}function bnpMultiplyTo(a,b){var c=this.abs(),d=a.abs(),e=c.t;for(b.t=e+d.t;--e>=0;)b[e]=0;for(e=0;e=0;)a[c]=0;for(c=0;c=b.DV&&(a[c+b.t]-=b.DV,a[c+b.t+1]=1)}a.t>0&&(a[a.t-1]+=b.am(c,b[c],a,2*c,0,1)),a.s=0,a.clamp()}function bnpDivRemTo(a,b,c){var d=a.abs();if(!(d.t<=0)){var e=this.abs();if(e.t0?(d.lShiftTo(i,f),e.lShiftTo(i,c)):(d.copyTo(f),e.copyTo(c));var j=f.t,k=f[j-1];if(0!=k){var l=k*(1<1?f[j-2]>>this.F2:0),m=this.FV/l,n=(1<=0&&(c[c.t++]=1,c.subTo(r,c)),BigInteger.ONE.dlShiftTo(j,r),r.subTo(f,f);f.t=0;){var s=c[--p]==k?this.DM:Math.floor(c[p]*m+(c[p-1]+o)*n);if((c[p]+=f.am(0,s,c,q,0,j))0&&c.rShiftTo(i,c),g<0&&BigInteger.ZERO.subTo(c,c)}}}function bnMod(a){var b=nbi();return this.abs().divRemTo(a,null,b),this.s<0&&b.compareTo(BigInteger.ZERO)>0&&a.subTo(b,b),b}function Classic(a){this.m=a}function cConvert(a){return a.s<0||a.compareTo(this.m)>=0?a.mod(this.m):a}function cRevert(a){return a}function cReduce(a){a.divRemTo(this.m,null,a)}function cMulTo(a,b,c){a.multiplyTo(b,c),this.reduce(c)}function cSqrTo(a,b){a.squareTo(b),this.reduce(b)}function bnpInvDigit(){if(this.t<1)return 0;var a=this[0];if(0==(1&a))return 0;var b=3&a;return b=b*(2-(15&a)*b)&15,b=b*(2-(255&a)*b)&255,b=b*(2-((65535&a)*b&65535))&65535,b=b*(2-a*b%this.DV)%this.DV,b>0?this.DV-b:-b}function Montgomery(a){this.m=a,this.mp=a.invDigit(),this.mpl=32767&this.mp,this.mph=this.mp>>15,this.um=(1<0&&this.m.subTo(b,b),b}function montRevert(a){var b=nbi();return a.copyTo(b),this.reduce(b),b}function montReduce(a){for(;a.t<=this.mt2;)a[a.t++]=0;for(var b=0;b>15)*this.mpl&this.um)<<15)&a.DM;for(c=b+this.m.t,a[c]+=this.m.am(0,d,a,b,0,this.m.t);a[c]>=a.DV;)a[c]-=a.DV,a[++c]++}a.clamp(),a.drShiftTo(this.m.t,a),a.compareTo(this.m)>=0&&a.subTo(this.m,a)}function montSqrTo(a,b){a.squareTo(b),this.reduce(b)}function montMulTo(a,b,c){a.multiplyTo(b,c),this.reduce(c)}function bnpIsEven(){return 0==(this.t>0?1&this[0]:this.s)}function bnpExp(a,b){if(a>4294967295||a<1)return BigInteger.ONE;var c=nbi(),d=nbi(),e=b.convert(this),f=nbits(a)-1;for(e.copyTo(c);--f>=0;)if(b.sqrTo(c,d),(a&1<0)b.mulTo(d,e,c);else{var g=c;c=d,d=g}return b.revert(c)}function bnModPowInt(a,b){var c;return c=a<256||b.isEven()?new Classic(b):new Montgomery(b),this.exp(a,c)}function bnClone(){var a=nbi();return this.copyTo(a),a}function bnIntValue(){if(this.s<0){if(1==this.t)return this[0]-this.DV;if(0==this.t)return-1}else{if(1==this.t)return this[0];if(0==this.t)return 0}return(this[1]&(1<<32-this.DB)-1)<>24}function bnShortValue(){return 0==this.t?this.s:this[0]<<16>>16}function bnpChunkSize(a){return Math.floor(Math.LN2*this.DB/Math.log(a))}function bnSigNum(){return this.s<0?-1:this.t<=0||1==this.t&&this[0]<=0?0:1}function bnpToRadix(a){if(null==a&&(a=10),0==this.signum()||a<2||a>36)return"0";var b=this.chunkSize(a),c=Math.pow(a,b),d=nbv(c),e=nbi(),f=nbi(),g="";for(this.divRemTo(d,e,f);e.signum()>0;)g=(c+f.intValue()).toString(a).substr(1)+g,e.divRemTo(d,e,f);return f.intValue().toString(a)+g}function bnpFromRadix(a,b){this.fromInt(0),null==b&&(b=10);for(var c=this.chunkSize(b),d=Math.pow(b,c),e=!1,f=0,g=0,h=0;h=c&&(this.dMultiply(d),this.dAddOffset(g,0),f=0,g=0))}f>0&&(this.dMultiply(Math.pow(b,f)),this.dAddOffset(g,0)),e&&BigInteger.ZERO.subTo(this,this)}function bnpFromNumber(a,b,c){if("number"==typeof b)if(a<2)this.fromInt(1);else for(this.fromNumber(a,c),this.testBit(a-1)||this.bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this),this.isEven()&&this.dAddOffset(1,0);!this.isProbablePrime(b);)this.dAddOffset(2,0),this.bitLength()>a&&this.subTo(BigInteger.ONE.shiftLeft(a-1),this);else{var d=new Array,e=7&a;d.length=(a>>3)+1,b.nextBytes(d),e>0?d[0]&=(1<0)for(d>d)!=(this.s&this.DM)>>d&&(b[e++]=c|this.s<=0;)d<8?(c=(this[a]&(1<>(d+=this.DB-8)):(c=this[a]>>(d-=8)&255,d<=0&&(d+=this.DB,--a)),0!=(128&c)&&(c|=-256),0==e&&(128&this.s)!=(128&c)&&++e,(e>0||c!=this.s)&&(b[e++]=c);return b}function bnEquals(a){return 0==this.compareTo(a)}function bnMin(a){return this.compareTo(a)<0?this:a}function bnMax(a){return this.compareTo(a)>0?this:a}function bnpBitwiseTo(a,b,c){var d,e,f=Math.min(a.t,this.t);for(d=0;d>=16,b+=16),0==(255&a)&&(a>>=8,b+=8),0==(15&a)&&(a>>=4,b+=4),0==(3&a)&&(a>>=2,b+=2),0==(1&a)&&++b,b}function bnGetLowestSetBit(){for(var a=0;a=this.t?0!=this.s:0!=(this[b]&1<>=this.DB;if(a.t>=this.DB;d+=this.s}else{for(d+=this.s;c>=this.DB;d+=a.s}b.s=d<0?-1:0,d>0?b[c++]=d:d<-1&&(b[c++]=this.DV+d),b.t=c,b.clamp()}function bnAdd(a){var b=nbi();return this.addTo(a,b),b}function bnSubtract(a){var b=nbi();return this.subTo(a,b),b}function bnMultiply(a){var b=nbi();return this.multiplyTo(a,b),b}function bnSquare(){var a=nbi();return this.squareTo(a),a}function bnDivide(a){var b=nbi();return this.divRemTo(a,b,null),b}function bnRemainder(a){var b=nbi();return this.divRemTo(a,null,b),b}function bnDivideAndRemainder(a){var b=nbi(),c=nbi();return this.divRemTo(a,b,c),new Array(b,c)}function bnpDMultiply(a){this[this.t]=this.am(0,a-1,this,0,0,this.t),++this.t,this.clamp()}function bnpDAddOffset(a,b){if(0!=a){for(;this.t<=b;)this[this.t++]=0;for(this[b]+=a;this[b]>=this.DV;)this[b]-=this.DV,++b>=this.t&&(this[this.t++]=0),++this[b]}}function NullExp(){}function nNop(a){return a}function nMulTo(a,b,c){a.multiplyTo(b,c)}function nSqrTo(a,b){a.squareTo(b)}function bnPow(a){return this.exp(a,new NullExp)}function bnpMultiplyLowerTo(a,b,c){var d=Math.min(this.t+a.t,b);for(c.s=0,c.t=d;d>0;)c[--d]=0;var e;for(e=c.t-this.t;d=0;)c[d]=0;for(d=Math.max(b-this.t,0);d2*this.m.t)return a.mod(this.m);if(a.compareTo(this.m)<0)return a;var b=nbi();return a.copyTo(b),this.reduce(b),b}function barrettRevert(a){return a}function barrettReduce(a){for(a.drShiftTo(this.m.t-1,this.r2),a.t>this.m.t+1&&(a.t=this.m.t+1,a.clamp()),this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3),this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2);a.compareTo(this.r2)<0;)a.dAddOffset(1,this.m.t+1);for(a.subTo(this.r2,a);a.compareTo(this.m)>=0;)a.subTo(this.m,a)}function barrettSqrTo(a,b){a.squareTo(b),this.reduce(b)}function barrettMulTo(a,b,c){a.multiplyTo(b,c),this.reduce(c)}function bnModPow(a,b){var c,d,e=a.bitLength(),f=nbv(1);if(e<=0)return f;c=e<18?1:e<48?3:e<144?4:e<768?5:6,d=e<8?new Classic(b):b.isEven()?new Barrett(b):new Montgomery(b);var g=new Array,h=3,i=c-1,j=(1<1){var k=nbi();for(d.sqrTo(g[1],k);h<=j;)g[h]=nbi(),d.mulTo(k,g[h-2],g[h]),h+=2}var l,m,n=a.t-1,o=!0,p=nbi();for(e=nbits(a[n])-1;n>=0;){for(e>=i?l=a[n]>>e-i&j:(l=(a[n]&(1<0&&(l|=a[n-1]>>this.DB+e-i)),h=c;0==(1&l);)l>>=1,--h;if((e-=h)<0&&(e+=this.DB,--n),o)g[l].copyTo(f),o=!1;else{for(;h>1;)d.sqrTo(f,p),d.sqrTo(p,f),h-=2;h>0?d.sqrTo(f,p):(m=f,f=p,p=m),d.mulTo(p,g[l],f)}for(;n>=0&&0==(a[n]&1<0&&(b.rShiftTo(f,b),c.rShiftTo(f,c));b.signum()>0;)(e=b.getLowestSetBit())>0&&b.rShiftTo(e,b),(e=c.getLowestSetBit())>0&&c.rShiftTo(e,c),b.compareTo(c)>=0?(b.subTo(c,b),b.rShiftTo(1,b)):(c.subTo(b,c),c.rShiftTo(1,c));return f>0&&c.lShiftTo(f,c),c}function bnpModInt(a){if(a<=0)return 0;var b=this.DV%a,c=this.s<0?a-1:0;if(this.t>0)if(0==b)c=this[0]%a;else for(var d=this.t-1;d>=0;--d)c=(b*c+this[d])%a;return c}function bnModInverse(a){var b=a.isEven();if(this.isEven()&&b||0==a.signum())return BigInteger.ZERO;for(var c=a.clone(),d=this.clone(),e=nbv(1),f=nbv(0),g=nbv(0),h=nbv(1);0!=c.signum();){for(;c.isEven();)c.rShiftTo(1,c),b?(e.isEven()&&f.isEven()||(e.addTo(this,e),f.subTo(a,f)),e.rShiftTo(1,e)):f.isEven()||f.subTo(a,f),f.rShiftTo(1,f);for(;d.isEven();)d.rShiftTo(1,d),b?(g.isEven()&&h.isEven()||(g.addTo(this,g),h.subTo(a,h)),g.rShiftTo(1,g)):h.isEven()||h.subTo(a,h),h.rShiftTo(1,h);c.compareTo(d)>=0?(c.subTo(d,c),b&&e.subTo(g,e),f.subTo(h,f)):(d.subTo(c,d),b&&g.subTo(e,g),h.subTo(f,h))}return 0!=d.compareTo(BigInteger.ONE)?BigInteger.ZERO:h.compareTo(a)>=0?h.subtract(a):h.signum()<0?(h.addTo(a,h),h.signum()<0?h.add(a):h):h}function bnIsProbablePrime(a){var b,c=this.abs();if(1==c.t&&c[0]<=lowprimes[lowprimes.length-1]){for(b=0;b>1,a>lowprimes.length&&(a=lowprimes.length);for(var e=nbi(),f=0;f>6)+b64map.charAt(63&c);for(b+1==a.length?(c=parseInt(a.substring(b,b+1),16),d+=b64map.charAt(c<<2)):b+2==a.length&&(c=parseInt(a.substring(b,b+2),16),d+=b64map.charAt(c>>2)+b64map.charAt((3&c)<<4));(3&d.length)>0;)d+=b64padchar;return d}function b64tohex(a){var b,c,d="",e=0;for(b=0;b>2),c=3&f,e=1):1==e?(d+=int2char(c<<2|f>>4),c=15&f,e=2):2==e?(d+=int2char(c),d+=int2char(f>>2),c=3&f,e=3):(d+=int2char(c<<2|f>>4),d+=int2char(15&f),e=0))}return 1==e&&(d+=int2char(c<<2)),d}function b64toBA(a){var b,c=b64tohex(a),d=new Array;for(b=0;2*b0;--b){f=f.twice();var g=d.testBit(b),h=c.testBit(b);g!=h&&(f=f.add(g?this:e))}return f}function pointFpMultiplyTwo(a,b,c){var d;d=a.bitLength()>c.bitLength()?a.bitLength()-1:c.bitLength()-1;for(var e=this.curve.getInfinity(),f=this.add(b);d>=0;)e=e.twice(),a.testBit(d)?e=c.testBit(d)?e.add(f):e.add(this):c.testBit(d)&&(e=e.add(b)),--d;return e}function ECCurveFp(a,b,c){this.q=a,this.a=this.fromBigInteger(b),this.b=this.fromBigInteger(c),this.infinity=new ECPointFp(this,null,null),this.reducer=new Barrett(this.q)}function curveFpGetQ(){return this.q}function curveFpGetA(){return this.a}function curveFpGetB(){return this.b}function curveFpEquals(a){return a==this||this.q.equals(a.q)&&this.a.equals(a.a)&&this.b.equals(a.b)}function curveFpGetInfinity(){return this.infinity}function curveFpFromBigInteger(a){return new ECFieldElementFp(this.q,a)}function curveReduce(a){this.reducer.reduce(a)}function curveFpDecodePointHex(a){switch(parseInt(a.substr(0,2),16)){case 0:return this.infinity;case 2:case 3:return null;case 4:case 6:case 7:var b=(a.length-2)/2,c=a.substr(2,b),d=a.substr(b+2,b);return new ECPointFp(this,this.fromBigInteger(new BigInteger(c,16)),this.fromBigInteger(new BigInteger(d,16)));default:return null}}function curveFpEncodePointHex(a){if(a.isInfinity())return"00";var b=a.getX().toBigInteger().toString(16),c=a.getY().toBigInteger().toString(16),d=this.getQ().toString(16).length;for(d%2!=0&&d++;b.length>8&255,rng_pptr>=rng_psize&&(rng_pptr-=rng_psize)}function rng_seed_time(){rng_seed_int((new Date).getTime())}function rng_get_byte(){if(null==rng_state){for(rng_seed_time(),rng_state=prng_newstate(),rng_state.init(rng_pool),rng_pptr=0;rng_pptr=0&&b>0;){var e=a.charCodeAt(d--);e<128?c[--b]=e:e>127&&e<2048?(c[--b]=63&e|128,c[--b]=e>>6|192):(c[--b]=63&e|128,c[--b]=e>>6&63|128,c[--b]=e>>12|224)}c[--b]=0;for(var f=new SecureRandom,g=new Array;b>2;){for(g[0]=0;0==g[0];)f.nextBytes(g);c[--b]=g[0]}return c[--b]=2,c[--b]=0,new BigInteger(c)}function RSAKey(){this.n=null,this.e=0,this.d=null,this.p=null,this.q=null,this.dmp1=null,this.dmq1=null,this.coeff=null}function RSASetPublic(a,b){null!=a&&null!=b&&a.length>0&&b.length>0&&(this.n=parseBigInt(a,16),this.e=parseInt(b,16))}function RSADoPublic(a){return a.modPowInt(this.e,this.n)}function RSAEncrypt(a){var b=pkcs1pad2(a,this.n.bitLength()+7>>3);if(null==b)return null;var c=this.doPublic(b);if(null==c)return null;var d=c.toString(16);return 0==(1&d.length)?d:"0"+d}function X9ECParameters(a,b,c,d){this.curve=a,this.g=b,this.n=c,this.h=d}function x9getCurve(){return this.curve}function x9getG(){return this.g}function x9getN(){return this.n}function x9getH(){return this.h}function fromHex(a){return new BigInteger(a,16)}function secp128r1(){var a=fromHex("FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF"),b=fromHex("FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC"),c=fromHex("E87579C11079F43DD824993C2CEE5ED3"),d=fromHex("FFFFFFFE0000000075A30D1B9038A115"),e=BigInteger.ONE,f=new ECCurveFp(a,b,c),g=f.decodePointHex("04161FF7528B899B2D0C28607CA52C5B86CF5AC8395BAFEB13C02DA292DDED7A83");return new X9ECParameters(f,g,d,e)}function secp160k1(){var a=fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73"),b=BigInteger.ZERO,c=fromHex("7"),d=fromHex("0100000000000000000001B8FA16DFAB9ACA16B6B3"),e=BigInteger.ONE,f=new ECCurveFp(a,b,c),g=f.decodePointHex("043B4C382CE37AA192A4019E763036F4F5DD4D7EBB938CF935318FDCED6BC28286531733C3F03C4FEE");return new X9ECParameters(f,g,d,e)}function secp160r1(){var a=fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF"),b=fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC"),c=fromHex("1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45"),d=fromHex("0100000000000000000001F4C8F927AED3CA752257"),e=BigInteger.ONE,f=new ECCurveFp(a,b,c),g=f.decodePointHex("044A96B5688EF573284664698968C38BB913CBFC8223A628553168947D59DCC912042351377AC5FB32");return new X9ECParameters(f,g,d,e)}function secp192k1(){var a=fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37"),b=BigInteger.ZERO,c=fromHex("3"),d=fromHex("FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D"),e=BigInteger.ONE,f=new ECCurveFp(a,b,c),g=f.decodePointHex("04DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D");return new X9ECParameters(f,g,d,e)}function secp192r1(){var a=fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF"),b=fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC"),c=fromHex("64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1"),d=fromHex("FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831"),e=BigInteger.ONE,f=new ECCurveFp(a,b,c),g=f.decodePointHex("04188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF101207192B95FFC8DA78631011ED6B24CDD573F977A11E794811");return new X9ECParameters(f,g,d,e)}function secp224r1(){var a=fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001"),b=fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE"),c=fromHex("B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4"),d=fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D"),e=BigInteger.ONE,f=new ECCurveFp(a,b,c),g=f.decodePointHex("04B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34");return new X9ECParameters(f,g,d,e)}function secp256r1(){var a=fromHex("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF"),b=fromHex("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC"),c=fromHex("5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B"),d=fromHex("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551"),e=BigInteger.ONE,f=new ECCurveFp(a,b,c),g=f.decodePointHex("046B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C2964FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5");return new X9ECParameters(f,g,d,e)}function getSECCurveByName(a){return"secp128r1"==a?secp128r1():"secp160k1"==a?secp160k1():"secp160r1"==a?secp160r1():"secp192k1"==a?secp192k1():"secp192r1"==a?secp192r1():"secp224r1"==a?secp224r1():"secp256r1"==a?secp256r1():null}function Base64x(){}function stoBA(a){for(var b=new Array,c=0;c0&&b-1 in a))}function d(a,b,c){if(_.isFunction(b))return _.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return _.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(ha.test(b))return _.filter(b,a,c);b=_.filter(b,a)}return _.grep(a,function(a){return U.call(b,a)>=0!==c})}function e(a,b){for(;(a=a[b])&&1!==a.nodeType;);return a}function f(a){var b=oa[a]={};return _.each(a.match(na)||[],function(a,c){b[c]=!0}),b}function g(){Z.removeEventListener("DOMContentLoaded",g,!1),a.removeEventListener("load",g,!1),_.ready()}function h(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=_.expando+Math.random()}function i(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(ua,"-$1").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c||"false"!==c&&("null"===c?null:+c+""===c?+c:ta.test(c)?_.parseJSON(c):c)}catch(a){}sa.set(a,b,c)}else c=void 0;return c}function j(){return!0}function k(){return!1}function l(){try{return Z.activeElement}catch(a){}}function m(a,b){return _.nodeName(a,"table")&&_.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function n(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function o(a){var b=Ka.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function p(a,b){for(var c=0,d=a.length;c")).appendTo(b.documentElement),b=Na[0].contentDocument,b.write(),b.close(),c=t(a,b),Na.detach()),Oa[a]=c),c}function v(a,b,c){var d,e,f,g,h=a.style;return c=c||Ra(a),c&&(g=c.getPropertyValue(b)||c[b]),c&&(""!==g||_.contains(a.ownerDocument,a)||(g=_.style(a,b)),Qa.test(g)&&Pa.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f)),void 0!==g?g+"":g}function w(a,b){return{get:function(){return a()?void delete this.get:(this.get=b).apply(this,arguments)}}}function x(a,b){if(b in a)return b;for(var c=b[0].toUpperCase()+b.slice(1),d=b,e=Xa.length;e--;)if(b=Xa[e]+c,b in a)return b;return d}function y(a,b,c){var d=Ta.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function z(a,b,c,d,e){for(var f=c===(d?"border":"content")?4:"width"===b?1:0,g=0;f<4;f+=2)"margin"===c&&(g+=_.css(a,c+wa[f],!0,e)),d?("content"===c&&(g-=_.css(a,"padding"+wa[f],!0,e)),"margin"!==c&&(g-=_.css(a,"border"+wa[f]+"Width",!0,e))):(g+=_.css(a,"padding"+wa[f],!0,e),"padding"!==c&&(g+=_.css(a,"border"+wa[f]+"Width",!0,e)));return g}function A(a,b,c){var d=!0,e="width"===b?a.offsetWidth:a.offsetHeight,f=Ra(a),g="border-box"===_.css(a,"boxSizing",!1,f);if(e<=0||null==e){if(e=v(a,b,f),(e<0||null==e)&&(e=a.style[b]),Qa.test(e))return e;d=g&&(Y.boxSizingReliable()||e===a.style[b]),e=parseFloat(e)||0}return e+z(a,b,c||(g?"border":"content"),d,f)+"px"}function B(a,b){for(var c,d,e,f=[],g=0,h=a.length;g=0&&c=0},isPlainObject:function(a){return"object"===_.type(a)&&!a.nodeType&&!_.isWindow(a)&&!(a.constructor&&!X.call(a.constructor.prototype,"isPrototypeOf"))},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?V[W.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=_.trim(a),a&&(1===a.indexOf("use strict")?(b=Z.createElement("script"),b.text=a,Z.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(ba,"ms-").replace(ca,da)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,d){var e,f=0,g=a.length,h=c(a);if(d){if(h)for(;fw.cacheLength&&delete a[b.shift()],a[c+" "]=d}var b=[];return a}function d(a){return a[N]=!0,a}function e(a){var b=G.createElement("div");try{return!!a(b)}catch(a){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function f(a,b){for(var c=a.split("|"),d=a.length;d--;)w.attrHandle[c[d]]=b}function g(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||W)-(~a.sourceIndex||W);if(d)return d;if(c)for(;c=c.nextSibling;)if(c===b)return-1;return a?1:-1}function h(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function i(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function j(a){return d(function(b){return b=+b,d(function(c,d){for(var e,f=a([],c.length,b),g=f.length;g--;)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function k(a){return a&&typeof a.getElementsByTagName!==V&&a}function l(){}function m(a){for(var b=0,c=a.length,d="";b1?function(b,c,d){for(var e=a.length;e--;)if(!a[e](b,c,d))return!1;return!0}:a[0]}function p(a,c,d){for(var e=0,f=c.length;e-1&&(d[j]=!(g[j]=l))}}else t=q(t===g?t.splice(o,t.length):t),f?f(null,g,t,i):_.apply(g,t)})}function s(a){for(var b,c,d,e=a.length,f=w.relative[a[0].type],g=f||w.relative[" "],h=f?1:0,i=n(function(a){return a===b},g,!0),j=n(function(a){return ba.call(b,a)>-1},g,!0),k=[function(a,c,d){return!f&&(d||c!==C)||((b=c).nodeType?i(a,c,d):j(a,c,d))}];h1&&o(k),h>1&&m(a.slice(0,h-1).concat({value:" "===a[h-2].type?"*":""})).replace(ia,"$1"),c,h0,f=a.length>0,g=function(d,g,h,i,j){var k,l,m,n=0,o="0",p=d&&[],r=[],s=C,t=d||f&&w.find.TAG("*",j),u=P+=null==s?1:Math.random()||.1,v=t.length;for(j&&(C=g!==G&&g);o!==v&&null!=(k=t[o]);o++){if(f&&k){for(l=0;m=a[l++];)if(m(k,g,h)){i.push(k);break}j&&(P=u)}e&&((k=!m&&k)&&n--,d&&p.push(k))}if(n+=o,e&&o!==n){for(l=0;m=c[l++];)m(p,r,g,h);if(d){if(n>0)for(;o--;)p[o]||r[o]||(r[o]=Z.call(i));r=q(r)}_.apply(i,r),j&&!d&&r.length>0&&n+c.length>1&&b.uniqueSort(i)}return j&&(P=u,C=s),p};return e?d(g):g}var u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N="sizzle"+-new Date,O=a.document,P=0,Q=0,R=c(),S=c(),T=c(),U=function(a,b){return a===b&&(E=!0),0},V="undefined",W=1<<31,X={}.hasOwnProperty,Y=[],Z=Y.pop,$=Y.push,_=Y.push,aa=Y.slice,ba=Y.indexOf||function(a){for(var b=0,c=this.length;b+~]|"+da+")"+da+"*"),la=new RegExp("="+da+"*([^\\]'\"]*?)"+da+"*\\]","g"),ma=new RegExp(ha),na=new RegExp("^"+fa+"$"),oa={ID:new RegExp("^#("+ea+")"),CLASS:new RegExp("^\\.("+ea+")"),TAG:new RegExp("^("+ea.replace("w","w*")+")"),ATTR:new RegExp("^"+ga),PSEUDO:new RegExp("^"+ha),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+da+"*(even|odd|(([+-]|)(\\d*)n|)"+da+"*(?:([+-]|)"+da+"*(\\d+)|))"+da+"*\\)|)","i"),bool:new RegExp("^(?:"+ca+")$","i"),needsContext:new RegExp("^"+da+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+da+"*((?:-\\d)?\\d*)"+da+"*\\)|)(?=[^-]|$)","i")},pa=/^(?:input|select|textarea|button)$/i,qa=/^h\d$/i,ra=/^[^{]+\{\s*\[native \w/,sa=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ta=/[+~]/,ua=/'|\\/g,va=new RegExp("\\\\([\\da-f]{1,6}"+da+"?|("+da+")|.)","ig"),wa=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:d<0?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)};try{_.apply(Y=aa.call(O.childNodes),O.childNodes),Y[O.childNodes.length].nodeType}catch(a){_={apply:Y.length?function(a,b){$.apply(a,aa.call(b))}:function(a,b){for(var c=a.length,d=0;a[c++]=b[d++];);a.length=c-1}}}v=b.support={},y=b.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return!!b&&"HTML"!==b.nodeName},F=b.setDocument=function(a){var b,c=a?a.ownerDocument||a:O,d=c.defaultView;return c!==G&&9===c.nodeType&&c.documentElement?(G=c,H=c.documentElement,I=!y(c),d&&d!==d.top&&(d.addEventListener?d.addEventListener("unload",function(){F()},!1):d.attachEvent&&d.attachEvent("onunload",function(){F()})),v.attributes=e(function(a){return a.className="i",!a.getAttribute("className")}),v.getElementsByTagName=e(function(a){return a.appendChild(c.createComment("")),!a.getElementsByTagName("*").length}),v.getElementsByClassName=ra.test(c.getElementsByClassName)&&e(function(a){return a.innerHTML="
          ",a.firstChild.className="i",2===a.getElementsByClassName("i").length}),v.getById=e(function(a){return H.appendChild(a).id=N,!c.getElementsByName||!c.getElementsByName(N).length}),v.getById?(w.find.ID=function(a,b){if(typeof b.getElementById!==V&&I){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},w.filter.ID=function(a){var b=a.replace(va,wa);return function(a){return a.getAttribute("id")===b}}):(delete w.find.ID,w.filter.ID=function(a){var b=a.replace(va,wa);return function(a){var c=typeof a.getAttributeNode!==V&&a.getAttributeNode("id");return c&&c.value===b}}),w.find.TAG=v.getElementsByTagName?function(a,b){if(typeof b.getElementsByTagName!==V)return b.getElementsByTagName(a)}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){for(;c=f[e++];)1===c.nodeType&&d.push(c);return d}return f},w.find.CLASS=v.getElementsByClassName&&function(a,b){if(typeof b.getElementsByClassName!==V&&I)return b.getElementsByClassName(a)},K=[],J=[],(v.qsa=ra.test(c.querySelectorAll))&&(e(function(a){a.innerHTML="",a.querySelectorAll("[msallowclip^='']").length&&J.push("[*^$]="+da+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||J.push("\\["+da+"*(?:value|"+ca+")"),a.querySelectorAll(":checked").length||J.push(":checked")}),e(function(a){var b=c.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&J.push("name"+da+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||J.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),J.push(",.*:")})),(v.matchesSelector=ra.test(L=H.matches||H.webkitMatchesSelector||H.mozMatchesSelector||H.oMatchesSelector||H.msMatchesSelector))&&e(function(a){v.disconnectedMatch=L.call(a,"div"),L.call(a,"[s!='']:x"),K.push("!=",ha)}),J=J.length&&new RegExp(J.join("|")),K=K.length&&new RegExp(K.join("|")),b=ra.test(H.compareDocumentPosition),M=b||ra.test(H.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)for(;b=b.parentNode;)if(b===a)return!0;return!1},U=b?function(a,b){if(a===b)return E=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!v.sortDetached&&b.compareDocumentPosition(a)===d?a===c||a.ownerDocument===O&&M(O,a)?-1:b===c||b.ownerDocument===O&&M(O,b)?1:D?ba.call(D,a)-ba.call(D,b):0:4&d?-1:1)}:function(a,b){if(a===b)return E=!0,0;var d,e=0,f=a.parentNode,h=b.parentNode,i=[a],j=[b];if(!f||!h)return a===c?-1:b===c?1:f?-1:h?1:D?ba.call(D,a)-ba.call(D,b):0;if(f===h)return g(a,b);for(d=a;d=d.parentNode;)i.unshift(d);for(d=b;d=d.parentNode;)j.unshift(d);for(;i[e]===j[e];)e++;return e?g(i[e],j[e]):i[e]===O?-1:j[e]===O?1:0},c):G},b.matches=function(a,c){return b(a,null,null,c)},b.matchesSelector=function(a,c){if((a.ownerDocument||a)!==G&&F(a),c=c.replace(la,"='$1']"),v.matchesSelector&&I&&(!K||!K.test(c))&&(!J||!J.test(c)))try{var d=L.call(a,c);if(d||v.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(a){}return b(c,G,null,[a]).length>0},b.contains=function(a,b){return(a.ownerDocument||a)!==G&&F(a),M(a,b)},b.attr=function(a,b){(a.ownerDocument||a)!==G&&F(a);var c=w.attrHandle[b.toLowerCase()],d=c&&X.call(w.attrHandle,b.toLowerCase())?c(a,b,!I):void 0;return void 0!==d?d:v.attributes||!I?a.getAttribute(b):(d=a.getAttributeNode(b))&&d.specified?d.value:null},b.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},b.uniqueSort=function(a){var b,c=[],d=0,e=0;if(E=!v.detectDuplicates,D=!v.sortStable&&a.slice(0),a.sort(U),E){for(;b=a[e++];)b===a[e]&&(d=c.push(e));for(;d--;)a.splice(c[d],1)}return D=null,a},x=b.getText=function(a){var b,c="",d=0,e=a.nodeType;if(e){if(1===e||9===e||11===e){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=x(a)}else if(3===e||4===e)return a.nodeValue}else for(;b=a[d++];)c+=x(b);return c},w=b.selectors={cacheLength:50,createPseudo:d,match:oa,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(va,wa),a[3]=(a[3]||a[4]||a[5]||"").replace(va,wa),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||b.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&b.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return oa.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&ma.test(c)&&(b=z(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(va,wa).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=R[a+" "];return b||(b=new RegExp("(^|"+da+")"+a+"("+da+"|$)"))&&R(a,function(a){return b.test("string"==typeof a.className&&a.className||typeof a.getAttribute!==V&&a.getAttribute("class")||"")})},ATTR:function(a,c,d){return function(e){var f=b.attr(e,a);return null==f?"!="===c:!c||(f+="","="===c?f===d:"!="===c?f!==d:"^="===c?d&&0===f.indexOf(d):"*="===c?d&&f.indexOf(d)>-1:"$="===c?d&&f.slice(-d.length)===d:"~="===c?(" "+f+" ").indexOf(d)>-1:"|="===c&&(f===d||f.slice(0,d.length+1)===d+"-"))}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){for(;p;){for(l=b;l=l[p];)if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){for(k=q[N]||(q[N]={}),j=k[a]||[],n=j[0]===P&&j[1],m=j[0]===P&&j[2],l=n&&q.childNodes[n];l=++n&&l&&l[p]||(m=n=0)||o.pop();)if(1===l.nodeType&&++m&&l===b){k[a]=[P,n,m];break}}else if(s&&(j=(b[N]||(b[N]={}))[a])&&j[0]===P)m=j[1];else for(;(l=++n&&l&&l[p]||(m=n=0)||o.pop())&&((h?l.nodeName.toLowerCase()!==r:1!==l.nodeType)||!++m||(s&&((l[N]||(l[N]={}))[a]=[P,m]),l!==b)););return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,c){var e,f=w.pseudos[a]||w.setFilters[a.toLowerCase()]||b.error("unsupported pseudo: "+a);return f[N]?f(c):f.length>1?(e=[a,a,"",c],w.setFilters.hasOwnProperty(a.toLowerCase())?d(function(a,b){for(var d,e=f(a,c),g=e.length;g--;)d=ba.call(a,e[g]),a[d]=!(b[d]=e[g])}):function(a){return f(a,0,e)}):f}},pseudos:{not:d(function(a){var b=[],c=[],e=A(a.replace(ia,"$1"));return e[N]?d(function(a,b,c,d){for(var f,g=e(a,null,d,[]),h=a.length;h--;)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,d,f){return b[0]=a,e(b,null,f,c),!c.pop()}}),has:d(function(a){return function(c){return b(a,c).length>0}}),contains:d(function(a){return function(b){return(b.textContent||b.innerText||x(b)).indexOf(a)>-1}}),lang:d(function(a){return na.test(a||"")||b.error("unsupported lang: "+a),a=a.replace(va,wa).toLowerCase(),function(b){var c;do if(c=I?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===H},focus:function(a){return a===G.activeElement&&(!G.hasFocus||G.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!w.pseudos.empty(a)},header:function(a){return qa.test(a.nodeName)},input:function(a){return pa.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:j(function(){return[0]}),last:j(function(a,b){return[b-1]}),eq:j(function(a,b,c){return[c<0?c+b:c]}),even:j(function(a,b){for(var c=0;c=0;)a.push(d);return a}),gt:j(function(a,b,c){for(var d=c<0?c+b:c;++d2&&"ID"===(g=f[0]).type&&v.getById&&9===b.nodeType&&I&&w.relative[f[1].type]){if(b=(w.find.ID(g.matches[0].replace(va,wa),b)||[])[0],!b)return c;j&&(b=b.parentNode),a=a.slice(f.shift().value.length)}for(e=oa.needsContext.test(a)?0:f.length;e--&&(g=f[e],!w.relative[h=g.type]);)if((i=w.find[h])&&(d=i(g.matches[0].replace(va,wa),ta.test(f[0].type)&&k(b.parentNode)||b))){if(f.splice(e,1),a=d.length&&m(f),!a)return _.apply(c,d),c;break}}return(j||A(a,l))(d,b,!I,c,ta.test(a)&&k(b.parentNode)||b),c},v.sortStable=N.split("").sort(U).join("")===N,v.detectDuplicates=!!E,F(),v.sortDetached=e(function(a){return 1&a.compareDocumentPosition(G.createElement("div"))}),e(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||f("type|href|height|width",function(a,b,c){if(!c)return a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),v.attributes&&e(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||f("value",function(a,b,c){if(!c&&"input"===a.nodeName.toLowerCase())return a.defaultValue}),e(function(a){return null==a.getAttribute("disabled")})||f(ca,function(a,b,c){var d;if(!c)return a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),b}(a);_.find=ea,_.expr=ea.selectors,_.expr[":"]=_.expr.pseudos,_.unique=ea.uniqueSort,_.text=ea.getText,_.isXMLDoc=ea.isXML,_.contains=ea.contains;var fa=_.expr.match.needsContext,ga=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,ha=/^.[^:#\[\.,]*$/;_.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?_.find.matchesSelector(d,a)?[d]:[]:_.find.matches(a,_.grep(b,function(a){return 1===a.nodeType}))},_.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if("string"!=typeof a)return this.pushStack(_(a).filter(function(){for(b=0;b1?_.unique(d):d),d.selector=this.selector?this.selector+" "+a:a,d},filter:function(a){return this.pushStack(d(this,a||[],!1))},not:function(a){return this.pushStack(d(this,a||[],!0))},is:function(a){return!!d(this,"string"==typeof a&&fa.test(a)?_(a):a||[],!1).length}});var ia,ja=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,ka=_.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:ja.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||ia).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof _?b[0]:b,_.merge(this,_.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:Z,!0)),ga.test(c[1])&&_.isPlainObject(b))for(c in b)_.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}return d=Z.getElementById(c[2]),d&&d.parentNode&&(this.length=1,this[0]=d),this.context=Z,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):_.isFunction(a)?"undefined"!=typeof ia.ready?ia.ready(a):a(_):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),_.makeArray(a,this))};ka.prototype=_.fn,ia=_(Z);var la=/^(?:parents|prev(?:Until|All))/,ma={children:!0,contents:!0,next:!0,prev:!0};_.extend({dir:function(a,b,c){for(var d=[],e=void 0!==c;(a=a[b])&&9!==a.nodeType;)if(1===a.nodeType){if(e&&_(a).is(c))break;d.push(a)}return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),_.fn.extend({has:function(a){var b=_(a,this),c=b.length;return this.filter(function(){for(var a=0;a-1:1===c.nodeType&&_.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?_.unique(f):f)},index:function(a){return a?"string"==typeof a?U.call(_(a),this[0]):U.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(_.unique(_.merge(this.get(),_(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}}),_.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return _.dir(a,"parentNode")},parentsUntil:function(a,b,c){return _.dir(a,"parentNode",c)},next:function(a){return e(a,"nextSibling")},prev:function(a){return e(a,"previousSibling")},nextAll:function(a){return _.dir(a,"nextSibling")},prevAll:function(a){return _.dir(a,"previousSibling")},nextUntil:function(a,b,c){return _.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return _.dir(a,"previousSibling",c)},siblings:function(a){return _.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return _.sibling(a.firstChild)},contents:function(a){return a.contentDocument||_.merge([],a.childNodes)}},function(a,b){_.fn[a]=function(c,d){var e=_.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=_.filter(d,e)),this.length>1&&(ma[a]||_.unique(e),la.test(a)&&e.reverse()),this.pushStack(e)}});var na=/\S+/g,oa={};_.Callbacks=function(a){a="string"==typeof a?oa[a]||f(a):_.extend({},a);var b,c,d,e,g,h,i=[],j=!a.once&&[],k=function(f){for(b=a.memory&&f,c=!0,h=e||0,e=0,g=i.length,d=!0;i&&h-1;)i.splice(c,1),d&&(c<=g&&g--,c<=h&&h--)}),this},has:function(a){return a?_.inArray(a,i)>-1:!(!i||!i.length)},empty:function(){return i=[],g=0,this},disable:function(){return i=j=b=void 0,this},disabled:function(){return!i},lock:function(){return j=void 0,b||l.disable(),this},locked:function(){return!j},fireWith:function(a,b){return!i||c&&!j||(b=b||[],b=[a,b.slice?b.slice():b],d?j.push(b):k(b)),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!c}};return l},_.extend({Deferred:function(a){var b=[["resolve","done",_.Callbacks("once memory"),"resolved"],["reject","fail",_.Callbacks("once memory"),"rejected"],["notify","progress",_.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return _.Deferred(function(c){_.each(b,function(b,f){var g=_.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&_.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?_.extend(a,d):d}},e={};return d.pipe=d.then,_.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b,c,d,e=0,f=R.call(arguments),g=f.length,h=1!==g||a&&_.isFunction(a.promise)?g:0,i=1===h?a:_.Deferred(),j=function(a,c,d){return function(e){c[a]=this,d[a]=arguments.length>1?R.call(arguments):e,d===b?i.notifyWith(c,d):--h||i.resolveWith(c,d)}};if(g>1)for(b=new Array(g),c=new Array(g),d=new Array(g);e0||(pa.resolveWith(Z,[_]),_.fn.triggerHandler&&(_(Z).triggerHandler("ready"),_(Z).off("ready"))))}}),_.ready.promise=function(b){return pa||(pa=_.Deferred(),"complete"===Z.readyState?setTimeout(_.ready):(Z.addEventListener("DOMContentLoaded",g,!1),a.addEventListener("load",g,!1))),pa.promise(b)},_.ready.promise();var qa=_.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===_.type(c)){e=!0;for(h in c)_.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,_.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(_(a),c)})),b))for(;h1,null,!0)},removeData:function(a){return this.each(function(){sa.remove(this,a)})}}),_.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=ra.get(a,b),c&&(!d||_.isArray(c)?d=ra.access(a,b,_.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=_.queue(a,b),d=c.length,e=c.shift(),f=_._queueHooks(a,b),g=function(){_.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return ra.get(a,c)||ra.access(a,c,{empty:_.Callbacks("once memory").add(function(){ra.remove(a,[b+"queue",c])})})}}),_.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthx",Y.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var za="undefined";Y.focusinBubbles="onfocusin"in a;var Aa=/^key/,Ba=/^(?:mouse|pointer|contextmenu)|click/,Ca=/^(?:focusinfocus|focusoutblur)$/,Da=/^([^.]*)(?:\.(.+)|)$/;_.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=ra.get(a);if(q)for(c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=_.guid++),(i=q.events)||(i=q.events={}),(g=q.handle)||(g=q.handle=function(b){return typeof _!==za&&_.event.triggered!==b.type?_.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(na)||[""],j=b.length;j--;)h=Da.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n&&(l=_.event.special[n]||{},n=(e?l.delegateType:l.bindType)||n,l=_.event.special[n]||{},k=_.extend({type:n,origType:p,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&_.expr.match.needsContext.test(e),namespace:o.join(".")},f),(m=i[n])||(m=i[n]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,o,g)!==!1||a.addEventListener&&a.addEventListener(n,g,!1)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),_.event.global[n]=!0)},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=ra.hasData(a)&&ra.get(a);if(q&&(i=q.events)){for(b=(b||"").match(na)||[""],j=b.length;j--;)if(h=Da.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n){for(l=_.event.special[n]||{},n=(d?l.delegateType:l.bindType)||n,m=i[n]||[],h=h[2]&&new RegExp("(^|\\.)"+o.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;f--;)k=m[f],!e&&p!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,o,q.handle)!==!1||_.removeEvent(a,n,q.handle),delete i[n])}else for(n in i)_.event.remove(a,n+b[j],c,d,!0);_.isEmptyObject(i)&&(delete q.handle,ra.remove(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,j,k,l,m=[d||Z],n=X.call(b,"type")?b.type:b,o=X.call(b,"namespace")?b.namespace.split("."):[];if(g=h=d=d||Z,3!==d.nodeType&&8!==d.nodeType&&!Ca.test(n+_.event.triggered)&&(n.indexOf(".")>=0&&(o=n.split("."),n=o.shift(),o.sort()),j=n.indexOf(":")<0&&"on"+n,b=b[_.expando]?b:new _.Event(n,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=o.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+o.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:_.makeArray(c,[b]),l=_.event.special[n]||{},e||!l.trigger||l.trigger.apply(d,c)!==!1)){if(!e&&!l.noBubble&&!_.isWindow(d)){for(i=l.delegateType||n,Ca.test(i+n)||(g=g.parentNode);g;g=g.parentNode)m.push(g),h=g;h===(d.ownerDocument||Z)&&m.push(h.defaultView||h.parentWindow||a)}for(f=0;(g=m[f++])&&!b.isPropagationStopped();)b.type=f>1?i:l.bindType||n,k=(ra.get(g,"events")||{})[b.type]&&ra.get(g,"handle"),k&&k.apply(g,c),k=j&&g[j],k&&k.apply&&_.acceptData(g)&&(b.result=k.apply(g,c),b.result===!1&&b.preventDefault());return b.type=n,e||b.isDefaultPrevented()||l._default&&l._default.apply(m.pop(),c)!==!1||!_.acceptData(d)||j&&_.isFunction(d[n])&&!_.isWindow(d)&&(h=d[j],h&&(d[j]=null),_.event.triggered=n,d[n](),_.event.triggered=void 0,h&&(d[j]=h)),b.result}},dispatch:function(a){a=_.event.fix(a);var b,c,d,e,f,g=[],h=R.call(arguments),i=(ra.get(this,"events")||{})[a.type]||[],j=_.event.special[a.type]||{};if(h[0]=a,a.delegateTarget=this,!j.preDispatch||j.preDispatch.call(this,a)!==!1){for(g=_.event.handlers.call(this,a,i),b=0;(e=g[b++])&&!a.isPropagationStopped();)for(a.currentTarget=e.elem,c=0;(f=e.handlers[c++])&&!a.isImmediatePropagationStopped();)a.namespace_re&&!a.namespace_re.test(f.namespace)||(a.handleObj=f,a.data=f.data,d=((_.event.special[f.origType]||{}).handle||f.handler).apply(e.elem,h),void 0!==d&&(a.result=d)===!1&&(a.preventDefault(),a.stopPropagation()));return j.postDispatch&&j.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!==this;i=i.parentNode||this)if(i.disabled!==!0||"click"!==a.type){for(d=[],c=0;c=0:_.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h]*)\/>/gi,Fa=/<([\w:]+)/,Ga=/<|&#?\w+;/,Ha=/<(?:script|style|link)/i,Ia=/checked\s*(?:[^=]|=\s*.checked.)/i,Ja=/^$|\/(?:java|ecma)script/i,Ka=/^true\/(.*)/,La=/^\s*\s*$/g,Ma={option:[1,""],thead:[1,"","
          "],col:[2,"","
          "],tr:[2,"","
          "],td:[3,"","
          "],_default:[0,"",""]};Ma.optgroup=Ma.option,Ma.tbody=Ma.tfoot=Ma.colgroup=Ma.caption=Ma.thead,Ma.th=Ma.td,_.extend({clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=_.contains(a.ownerDocument,a);if(!(Y.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||_.isXMLDoc(a)))for(g=r(h),f=r(a),d=0,e=f.length;d0&&p(g,!i&&r(a,"script")),h},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k=b.createDocumentFragment(),l=[],m=0,n=a.length;m")+h[2],j=h[0];j--;)f=f.lastChild;_.merge(l,f.childNodes),f=k.firstChild,f.textContent=""}else l.push(b.createTextNode(e));for(k.textContent="",m=0;e=l[m++];)if((!d||_.inArray(e,d)===-1)&&(i=_.contains(e.ownerDocument,e),f=r(k.appendChild(e),"script"),i&&p(f),c))for(j=0;e=f[j++];)Ja.test(e.type||"")&&c.push(e);return k},cleanData:function(a){for(var b,c,d,e,f=_.event.special,g=0;void 0!==(c=a[g]);g++){if(_.acceptData(c)&&(e=c[ra.expando],e&&(b=ra.cache[e]))){if(b.events)for(d in b.events)f[d]?_.event.remove(c,d):_.removeEvent(c,d,b.handle);ra.cache[e]&&delete ra.cache[e]}delete sa.cache[c[sa.expando]]}}}),_.fn.extend({text:function(a){return qa(this,function(a){return void 0===a?_.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=a)})},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=m(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=m(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?_.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||_.cleanData(r(c)),c.parentNode&&(b&&_.contains(c.ownerDocument,c)&&p(r(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(_.cleanData(r(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null!=a&&a,b=null==b?a:b,this.map(function(){return _.clone(this,a,b)})},html:function(a){return qa(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!Ha.test(a)&&!Ma[(Fa.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ea,"<$1>");try{for(;c1&&"string"==typeof m&&!Y.checkClone&&Ia.test(m))return this.each(function(c){var d=k.eq(c);p&&(a[0]=m.call(this,c,d.html())),d.domManip(a,b)});if(j&&(c=_.buildFragment(a,this[0].ownerDocument,!1,this),d=c.firstChild,1===c.childNodes.length&&(c=d),d)){for(e=_.map(r(c,"script"),n),f=e.length;i1)},show:function(){return B(this,!0)},hide:function(){return B(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){xa(this)?_(this).show():_(this).hide()})}}),_.Tween=C,C.prototype={constructor:C,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||(_.cssNumber[c]?"":"px")},cur:function(){var a=C.propHooks[this.prop];return a&&a.get?a.get(this):C.propHooks._default.get(this)},run:function(a){var b,c=C.propHooks[this.prop];return this.options.duration?this.pos=b=_.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,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):C.propHooks._default.set(this),this}},C.prototype.init.prototype=C.prototype,C.propHooks={_default:{get:function(a){var b;return null==a.elem[a.prop]||a.elem.style&&null!=a.elem.style[a.prop]?(b=_.css(a.elem,a.prop,""),b&&"auto"!==b?b:0):a.elem[a.prop]},set:function(a){_.fx.step[a.prop]?_.fx.step[a.prop](a):a.elem.style&&(null!=a.elem.style[_.cssProps[a.prop]]||_.cssHooks[a.prop])?_.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},C.propHooks.scrollTop=C.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},_.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},_.fx=C.prototype.init,_.fx.step={};var Ya,Za,$a=/^(?:toggle|show|hide)$/,_a=new RegExp("^(?:([+-])=|)("+va+")([a-z%]*)$","i"),ab=/queueHooks$/,bb=[G],cb={"*":[function(a,b){var c=this.createTween(a,b),d=c.cur(),e=_a.exec(b),f=e&&e[3]||(_.cssNumber[a]?"":"px"),g=(_.cssNumber[a]||"px"!==f&&+d)&&_a.exec(_.css(c.elem,a)),h=1,i=20;if(g&&g[3]!==f){f=f||g[3],e=e||[],g=+d||1;do h=h||".5",g/=h,_.style(c.elem,a,g+f);while(h!==(h=c.cur()/d)&&1!==h&&--i)}return e&&(g=c.start=+g||+d||0,c.unit=f,c.end=e[1]?g+(e[1]+1)*e[2]:+e[2]),c}]};_.Animation=_.extend(I,{tweener:function(a,b){_.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");for(var c,d=0,e=a.length;d1)},removeAttr:function(a){return this.each(function(){_.removeAttr(this,a)})}}),_.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(a&&3!==f&&8!==f&&2!==f)return typeof a.getAttribute===za?_.prop(a,b,c):(1===f&&_.isXMLDoc(a)||(b=b.toLowerCase(),d=_.attrHooks[b]||(_.expr.match.bool.test(b)?eb:db)),void 0===c?d&&"get"in d&&null!==(e=d.get(a,b))?e:(e=_.find.attr(a,b),null==e?void 0:e):null!==c?d&&"set"in d&&void 0!==(e=d.set(a,c,b))?e:(a.setAttribute(b,c+""),c):void _.removeAttr(a,b))},removeAttr:function(a,b){var c,d,e=0,f=b&&b.match(na);if(f&&1===a.nodeType)for(;c=f[e++];)d=_.propFix[c]||c,_.expr.match.bool.test(c)&&(a[d]=!1),a.removeAttribute(c)},attrHooks:{type:{set:function(a,b){if(!Y.radioValue&&"radio"===b&&_.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}}}),eb={set:function(a,b,c){return b===!1?_.removeAttr(a,c):a.setAttribute(c,c),c}},_.each(_.expr.match.bool.source.match(/\w+/g),function(a,b){var c=fb[b]||_.find.attr;fb[b]=function(a,b,d){var e,f;return d||(f=fb[b],fb[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,fb[b]=f),e}});var gb=/^(?:input|select|textarea|button)$/i;_.fn.extend({prop:function(a,b){return qa(this,_.prop,a,b,arguments.length>1)},removeProp:function(a){return this.each(function(){delete this[_.propFix[a]||a]})}}),_.extend({propFix:{for:"htmlFor",class:"className"},prop:function(a,b,c){var d,e,f,g=a.nodeType;if(a&&3!==g&&8!==g&&2!==g)return f=1!==g||!_.isXMLDoc(a),f&&(b=_.propFix[b]||b,e=_.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){return a.hasAttribute("tabindex")||gb.test(a.nodeName)||a.href?a.tabIndex:-1}}}}),Y.optSelected||(_.propHooks.selected={get:function(a){var b=a.parentNode;return b&&b.parentNode&&b.parentNode.selectedIndex,null}}),_.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){_.propFix[this.toLowerCase()]=this});var hb=/[\t\r\n\f]/g;_.fn.extend({addClass:function(a){var b,c,d,e,f,g,h="string"==typeof a&&a,i=0,j=this.length;if(_.isFunction(a))return this.each(function(b){_(this).addClass(a.call(this,b,this.className))});if(h)for(b=(a||"").match(na)||[];i=0;)d=d.replace(" "+e+" "," ");g=a?_.trim(d):"",c.className!==g&&(c.className=g)}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):_.isFunction(a)?this.each(function(c){_(this).toggleClass(a.call(this,c,this.className,b),b)}):this.each(function(){if("string"===c)for(var b,d=0,e=_(this),f=a.match(na)||[];b=f[d++];)e.hasClass(b)?e.removeClass(b):e.addClass(b);else c!==za&&"boolean"!==c||(this.className&&ra.set(this,"__className__",this.className),this.className=this.className||a===!1?"":ra.get(this,"__className__")||"")})},hasClass:function(a){for(var b=" "+a+" ",c=0,d=this.length;c=0)return!0;return!1}});var ib=/\r/g;_.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=_.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,_(this).val()):a,null==e?e="":"number"==typeof e?e+="":_.isArray(e)&&(e=_.map(e,function(a){return null==a?"":a+""})),b=_.valHooks[this.type]||_.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=_.valHooks[e.type]||_.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(ib,""):null==c?"":c)}}}),_.extend({valHooks:{option:{get:function(a){var b=_.find.attr(a,"value");return null!=b?b:_.trim(_.text(a))}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type||e<0,g=f?null:[],h=f?e+1:d.length,i=e<0?h:f?e:0;i=0)&&(c=!0);return c||(a.selectedIndex=-1),f}}}}),_.each(["radio","checkbox"],function(){_.valHooks[this]={set:function(a,b){if(_.isArray(b))return a.checked=_.inArray(_(a).val(),b)>=0}},Y.checkOn||(_.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})}),_.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){_.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),_.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)}});var jb=_.now(),kb=/\?/;_.parseJSON=function(a){return JSON.parse(a+"")},_.parseXML=function(a){var b,c;if(!a||"string"!=typeof a)return null;try{c=new DOMParser,b=c.parseFromString(a,"text/xml")}catch(a){b=void 0}return b&&!b.getElementsByTagName("parsererror").length||_.error("Invalid XML: "+a),b};var lb,mb,nb=/#.*$/,ob=/([?&])_=[^&]*/,pb=/^(.*?):[ \t]*([^\r\n]*)$/gm,qb=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,rb=/^(?:GET|HEAD)$/,sb=/^\/\//,tb=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,ub={},vb={},wb="*/".concat("*");try{mb=location.href}catch(a){mb=Z.createElement("a"),mb.href="",mb=mb.href}lb=tb.exec(mb.toLowerCase())||[],_.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:mb,type:"GET",isLocal:qb.test(lb[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":wb,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":_.parseJSON,"text xml":_.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?L(L(a,_.ajaxSettings),b):L(_.ajaxSettings,a)},ajaxPrefilter:J(ub),ajaxTransport:J(vb),ajax:function(a,b){function c(a,b,c,g){var i,k,r,s,u,w=b;2!==t&&(t=2,h&&clearTimeout(h),d=void 0,f=g||"",v.readyState=a>0?4:0,i=a>=200&&a<300||304===a,c&&(s=M(l,v,c)),s=N(l,s,v,i),i?(l.ifModified&&(u=v.getResponseHeader("Last-Modified"),u&&(_.lastModified[e]=u),u=v.getResponseHeader("etag"),u&&(_.etag[e]=u)),204===a||"HEAD"===l.type?w="nocontent":304===a?w="notmodified":(w=s.state,k=s.data,r=s.error,i=!r)):(r=w,!a&&w||(w="error",a<0&&(a=0))),v.status=a,v.statusText=(b||w)+"",i?o.resolveWith(m,[k,w,v]):o.rejectWith(m,[v,w,r]),v.statusCode(q),q=void 0,j&&n.trigger(i?"ajaxSuccess":"ajaxError",[v,l,i?k:r]),p.fireWith(m,[v,w]),j&&(n.trigger("ajaxComplete",[v,l]),--_.active||_.event.trigger("ajaxStop")))}"object"==typeof a&&(b=a,a=void 0),b=b||{};var d,e,f,g,h,i,j,k,l=_.ajaxSetup({},b),m=l.context||l,n=l.context&&(m.nodeType||m.jquery)?_(m):_.event,o=_.Deferred(),p=_.Callbacks("once memory"),q=l.statusCode||{},r={},s={},t=0,u="canceled",v={readyState:0,getResponseHeader:function(a){var b;if(2===t){if(!g)for(g={};b=pb.exec(f);)g[b[1].toLowerCase()]=b[2];b=g[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===t?f:null},setRequestHeader:function(a,b){var c=a.toLowerCase();return t||(a=s[c]=s[c]||a,r[a]=b),this},overrideMimeType:function(a){return t||(l.mimeType=a),this},statusCode:function(a){var b;if(a)if(t<2)for(b in a)q[b]=[q[b],a[b]];else v.always(a[v.status]);return this},abort:function(a){var b=a||u;return d&&d.abort(b),c(0,b),this}};if(o.promise(v).complete=p.add,v.success=v.done,v.error=v.fail,l.url=((a||l.url||mb)+"").replace(nb,"").replace(sb,lb[1]+"//"),l.type=b.method||b.type||l.method||l.type,l.dataTypes=_.trim(l.dataType||"*").toLowerCase().match(na)||[""],null==l.crossDomain&&(i=tb.exec(l.url.toLowerCase()),l.crossDomain=!(!i||i[1]===lb[1]&&i[2]===lb[2]&&(i[3]||("http:"===i[1]?"80":"443"))===(lb[3]||("http:"===lb[1]?"80":"443")))),l.data&&l.processData&&"string"!=typeof l.data&&(l.data=_.param(l.data,l.traditional)),K(ub,l,b,v),2===t)return v;j=l.global,j&&0===_.active++&&_.event.trigger("ajaxStart"),l.type=l.type.toUpperCase(),l.hasContent=!rb.test(l.type),e=l.url,l.hasContent||(l.data&&(e=l.url+=(kb.test(e)?"&":"?")+l.data,delete l.data),l.cache===!1&&(l.url=ob.test(e)?e.replace(ob,"$1_="+jb++):e+(kb.test(e)?"&":"?")+"_="+jb++)),l.ifModified&&(_.lastModified[e]&&v.setRequestHeader("If-Modified-Since",_.lastModified[e]),_.etag[e]&&v.setRequestHeader("If-None-Match",_.etag[e])),(l.data&&l.hasContent&&l.contentType!==!1||b.contentType)&&v.setRequestHeader("Content-Type",l.contentType),v.setRequestHeader("Accept",l.dataTypes[0]&&l.accepts[l.dataTypes[0]]?l.accepts[l.dataTypes[0]]+("*"!==l.dataTypes[0]?", "+wb+"; q=0.01":""):l.accepts["*"]);for(k in l.headers)v.setRequestHeader(k,l.headers[k]);if(l.beforeSend&&(l.beforeSend.call(m,v,l)===!1||2===t))return v.abort();u="abort";for(k in{success:1,error:1,complete:1})v[k](l[k]);if(d=K(vb,l,b,v)){v.readyState=1,j&&n.trigger("ajaxSend",[v,l]),l.async&&l.timeout>0&&(h=setTimeout(function(){v.abort("timeout")},l.timeout));try{t=1,d.send(r,c)}catch(a){if(!(t<2))throw a;c(-1,a)}}else c(-1,"No Transport");return v},getJSON:function(a,b,c){return _.get(a,b,c,"json")},getScript:function(a,b){return _.get(a,void 0,b,"script")}}),_.each(["get","post"],function(a,b){_[b]=function(a,c,d,e){return _.isFunction(c)&&(e=e||d,d=c,c=void 0),_.ajax({url:a,type:b,dataType:e,data:c,success:d})}}),_.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){_.fn[b]=function(a){return this.on(b,a)}}),_._evalUrl=function(a){return _.ajax({url:a,type:"GET",dataType:"script",async:!1,global:!1,throws:!0})},_.fn.extend({wrapAll:function(a){var b;return _.isFunction(a)?this.each(function(b){_(this).wrapAll(a.call(this,b))}):(this[0]&&(b=_(a,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){for(var a=this;a.firstElementChild;)a=a.firstElementChild;return a}).append(this)),this)},wrapInner:function(a){return _.isFunction(a)?this.each(function(b){_(this).wrapInner(a.call(this,b))}):this.each(function(){var b=_(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=_.isFunction(a);return this.each(function(c){_(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){_.nodeName(this,"body")||_(this).replaceWith(this.childNodes)}).end()}}),_.expr.filters.hidden=function(a){return a.offsetWidth<=0&&a.offsetHeight<=0},_.expr.filters.visible=function(a){return!_.expr.filters.hidden(a)};var xb=/%20/g,yb=/\[\]$/,zb=/\r?\n/g,Ab=/^(?:submit|button|image|reset|file)$/i,Bb=/^(?:input|select|textarea|keygen)/i;_.param=function(a,b){var c,d=[],e=function(a,b){b=_.isFunction(b)?b():null==b?"":b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};if(void 0===b&&(b=_.ajaxSettings&&_.ajaxSettings.traditional),_.isArray(a)||a.jquery&&!_.isPlainObject(a))_.each(a,function(){e(this.name,this.value)});else for(c in a)O(c,a[c],b,e);return d.join("&").replace(xb,"+")},_.fn.extend({serialize:function(){return _.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=_.prop(this,"elements");return a?_.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!_(this).is(":disabled")&&Bb.test(this.nodeName)&&!Ab.test(a)&&(this.checked||!ya.test(a))}).map(function(a,b){var c=_(this).val();return null==c?null:_.isArray(c)?_.map(c,function(a){return{name:b.name,value:a.replace(zb,"\r\n")}}):{name:b.name,value:c.replace(zb,"\r\n")}}).get()}}),_.ajaxSettings.xhr=function(){try{return new XMLHttpRequest}catch(a){}};var Cb=0,Db={},Eb={0:200,1223:204},Fb=_.ajaxSettings.xhr();a.ActiveXObject&&_(a).on("unload",function(){for(var a in Db)Db[a]()}),Y.cors=!!Fb&&"withCredentials"in Fb,Y.ajax=Fb=!!Fb,_.ajaxTransport(function(a){var b;if(Y.cors||Fb&&!a.crossDomain)return{send:function(c,d){var e,f=a.xhr(),g=++Cb;if(f.open(a.type,a.url,a.async,a.username,a.password),a.xhrFields)for(e in a.xhrFields)f[e]=a.xhrFields[e];a.mimeType&&f.overrideMimeType&&f.overrideMimeType(a.mimeType),a.crossDomain||c["X-Requested-With"]||(c["X-Requested-With"]="XMLHttpRequest");for(e in c)f.setRequestHeader(e,c[e]);b=function(a){return function(){b&&(delete Db[g],b=f.onload=f.onerror=null,"abort"===a?f.abort():"error"===a?d(f.status,f.statusText):d(Eb[f.status]||f.status,f.statusText,"string"==typeof f.responseText?{text:f.responseText}:void 0,f.getAllResponseHeaders()))}},f.onload=b(),f.onerror=b("error"),b=Db[g]=b("abort");try{f.send(a.hasContent&&a.data||null)}catch(a){if(b)throw a}},abort:function(){b&&b()}}}),_.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(a){return _.globalEval(a),a}}}),_.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET")}),_.ajaxTransport("script",function(a){if(a.crossDomain){var b,c;return{send:function(d,e){b=_(" + + + + + +
          +
          +
          Operations
          + +
            +
            +
            + +
            +
            Recipe
            +
              + +
              +
              +
              + + +
              + +
              + + +
              +
              + +
              + + + +
              +
              +
              + +
              +
              +
              + Input +
              + + +
              +
              +
              +
              +
              +
              + +
              +
              + +
              +
              + Output +
              + + + +
              +
              +
              +
              +
              +
              +
              + +
              +
              +
              +
              + + + + + + + + + + + + + + + + + diff --git a/src/js/.jshintrc b/src/js/.jshintrc new file mode 100755 index 00000000..7dc0b5ac --- /dev/null +++ b/src/js/.jshintrc @@ -0,0 +1,38 @@ +{ + "strict": "implied", + "multistr": true, + "browser": true, + "typed": true, + "jquery": true, + "node": true, + "undef": true, + "globals": { + /* core/* */ + "Chef": true, + "Dish": true, + "Recipe": true, + "Ingredient": true, + "Operation": true, + "Utils": true, + + /* config/* */ + "Categories": true, + "OperationConfig": true, + + /* views/html/* */ + "HTMLApp": true, + "HTMLCategory": true, + "HTMLOperation": true, + "HTMLIngredient": true, + "Manager": true, + "ControlsWaiter": true, + "HighlighterWaiter": true, + "InputWaiter": true, + "OperationsWaiter": true, + "OptionsWaiter": true, + "OutputWaiter": true, + "RecipeWaiter": true, + "SeasonalWaiter": true, + "WindowWaiter": true + } +} diff --git a/src/js/config/Categories.js b/src/js/config/Categories.js new file mode 100755 index 00000000..02c2b1f5 --- /dev/null +++ b/src/js/config/Categories.js @@ -0,0 +1,266 @@ +/** + * Type definition for a CatConf. + * + * @typedef {Object} CatConf + * @property {string} name - The display name for the category + * @property {string[]} ops - A list of the operations to be included in this category + */ + + +/** + * Categories of operations. + * + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * @constant + * @type {CatConf[]} + */ +var Categories = [ + { + name: "Favourites", + ops: [] + }, + { + name: "Data format", + ops: [ + "To Hexdump", + "From Hexdump", + "To Hex", + "From Hex", + "To Charcode", + "From Charcode", + "To Decimal", + "From Decimal", + "To Binary", + "From Binary", + "To Base64", + "From Base64", + "Show Base64 offsets", + "To Base32", + "From Base32", + "To Base", + "From Base", + "To HTML Entity", + "From HTML Entity", + "URL Encode", + "URL Decode", + "Unescape Unicode Characters", + "To Quoted Printable", + "From Quoted Printable", + "To Punycode", + "From Punycode", + "To Hex Content", + "From Hex Content", + "PEM to Hex", + "Hex to PEM", + "Parse ASN.1 hex string", + "Change IP format", + "Text encoding", + "Swap endianness", + ] + }, + { + name: "Encryption / Encoding", + ops: [ + "AES Encrypt", + "AES Decrypt", + "Blowfish Encrypt", + "Blowfish Decrypt", + "DES Encrypt", + "DES Decrypt", + "Triple DES Encrypt", + "Triple DES Decrypt", + "Rabbit Encrypt", + "Rabbit Decrypt", + "RC4", + "RC4 Drop", + "ROT13", + "XOR", + "XOR Brute Force", + "Derive PBKDF2 key", + "Derive EVP key", + ] + }, + { + name: "Public Key", + ops: [ + "Parse X.509 certificate", + "Parse ASN.1 hex string", + "PEM to Hex", + "Hex to PEM", + "Hex to Object Identifier", + "Object Identifier to Hex", + ] + }, + { + name: "Logical operations", + ops: [ + "XOR", + "XOR Brute Force", + "OR", + "NOT", + "AND", + "ADD", + "SUB", + "Rotate left", + "Rotate right", + "ROT13", + ] + }, + { + name: "Networking", + ops: [ + "Strip HTTP headers", + "Parse User Agent", + "Parse IP range", + "Parse IPv6 address", + "Parse URI", + "URL Encode", + "URL Decode", + "Format MAC addresses", + "Change IP format", + "Group IP addresses", + ] + }, + { + name: "Language", + ops: [ + "Text encoding", + "Unescape Unicode Characters", + ] + }, + { + name: "Utils", + ops: [ + "Diff", + "Remove whitespace", + "Remove null bytes", + "To Upper case", + "To Lower case", + "Add line numbers", + "Remove line numbers", + "Reverse", + "Sort", + "Unique", + "Split", + "Count occurrences", + "Expand alphabet range", + "Parse escaped string", + "Drop bytes", + "Take bytes", + "Pad lines", + "Find / Replace", + "Regular expression", + "Offset checker", + "Convert distance", + "Convert area", + "Convert mass", + "Convert speed", + "Convert data units", + "Parse UNIX file permissions", + "Swap endianness", + "Parse colour code", + ] + }, + { + name: "Date / Time", + ops: [ + "Parse DateTime", + "Translate DateTime Format", + "From UNIX Timestamp", + "To UNIX Timestamp", + "Extract dates", + ] + }, + { + name: "Extractors", + ops: [ + "Strings", + "Extract IP addresses", + "Extract email addresses", + "Extract MAC addresses", + "Extract URLs", + "Extract domains", + "Extract file paths", + "Extract dates", + "Regular expression", + ] + }, + { + name: "Compression", + ops: [ + "Raw Deflate", + "Raw Inflate", + "Zlib Deflate", + "Zlib Inflate", + "Gzip", + "Gunzip", + "Zip", + "Unzip", + "Bzip2 Decompress", + ] + }, + { + name: "Hashing", + ops: [ + "Analyse hash", + "Generate all hashes", + "MD5", + "SHA1", + "SHA224", + "SHA256", + "SHA384", + "SHA512", + "SHA3", + "RIPEMD-160", + "HMAC", + "Fletcher-16 Checksum", + "Adler-32 Checksum", + "CRC-32 Checksum", + "TCP/IP Checksum", + ] + }, + { + name: "Code tidy", + ops: [ + "Syntax highlighter", + "Generic Code Beautify", + "JavaScript Parser", + "JavaScript Beautify", + "JavaScript Minify", + "JSON Beautify", + "JSON Minify", + "XML Beautify", + "XML Minify", + "SQL Beautify", + "SQL Minify", + "CSS Beautify", + "CSS Minify", + "Strip HTML tags", + "Diff", + ] + }, + { + name: "Other", + ops: [ + "Entropy", + "Frequency distribution", + "Detect File Type", + "Scan for Embedded Files", + "Generate UUID", + "Numberwang", + ] + }, + { + name: "Flow control", + ops: [ + "Fork", + "Merge", + "Jump", + "Conditional Jump", + "Return", + ] + }, +]; diff --git a/src/js/config/OperationConfig.js b/src/js/config/OperationConfig.js new file mode 100755 index 00000000..f011a0b2 --- /dev/null +++ b/src/js/config/OperationConfig.js @@ -0,0 +1,2786 @@ +/* + * Tell JSHint to ignore "'Object' is not defined" errors in this file, as it references every + * single operation object by definition. + */ +/* jshint -W117 */ + + +/** + * Type definition for an OpConf. + * + * @typedef {Object} OpConf + * @property {html} description - A description of the operation with optional HTML tags + * @property {Function} run - The function which can be called the run the operation + * @property {string} input_type + * @property {string} output_type + * @property {Function|boolean} [highlight] - A function to calculate the highlight offset, or true + * if the offset does not change + * @property {Function|boolean} [highlight_reverse] - A function to calculate the highlight offset + * in reverse, or true if the offset does not change + * @property {boolean} [flow_control] - True if the operation is for Flow Control + * @property {ArgConf[]} [args] - A list of configuration objects for the arguments + */ + + +/** + * Type definition for an ArgConf. + * + * @typedef {Object} ArgConf + * @property {string} name - The display name of the argument + * @property {string} type - The data type of the argument + * @property {*} value + * @property {number[]} [disable_args] - A list of the indices of the operation's arguments which + * should be toggled on or off when this argument is changed + * @property {boolean} [disabled] - Whether or not this argument starts off disabled + */ + + +/** + * Operation configuration objects. + * + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * @constant + * @type {Object.} + */ +var OperationConfig = { + "Fork": { + description: "Split the input data up based on the specified delimiter and run all subsequent operations on each branch separately.

              For example, to decode multiple Base64 strings, enter them all on separate lines then add the 'Fork' and 'From Base64' operations to the recipe. Each string will be decoded separately.", + run: FlowControl.run_fork, + input_type: "string", + output_type: "string", + flow_control: true, + args: [ + { + name: "Split delimiter", + type: "binary_short_string", + value: FlowControl.FORK_DELIM + }, + { + name: "Merge delimiter", + type: "binary_short_string", + value: FlowControl.MERGE_DELIM + } + ] + }, + "Merge": { + description: "Consolidate all branches back into a single trunk. The opposite of Fork.", + run: FlowControl.run_merge, + input_type: "string", + output_type: "string", + flow_control: true, + args: [] + }, + "Jump": { + description: "Jump forwards or backwards over the specified number of operations.", + run: FlowControl.run_jump, + input_type: "string", + output_type: "string", + flow_control: true, + args: [ + { + name: "Number of operations to jump over", + type: "number", + value: FlowControl.JUMP_NUM + }, + { + name: "Maximum jumps (if jumping backwards)", + type: "number", + value: FlowControl.MAX_JUMPS + } + ] + }, + "Conditional Jump": { + description: "Conditionally jump forwards or backwards over the specified number of operations based on whether the data matches the specified regular expression.", + run: FlowControl.run_cond_jump, + input_type: "string", + output_type: "string", + flow_control: true, + args: [ + { + name: "Match (regex)", + type: "string", + value: "" + }, + { + name: "Number of operations to jump over if match found", + type: "number", + value: FlowControl.JUMP_NUM + }, + { + name: "Maximum jumps (if jumping backwards)", + type: "number", + value: FlowControl.MAX_JUMPS + } + ] + }, + "Return": { + description: "End execution of operations at this point in the recipe.", + run: FlowControl.run_return, + input_type: "string", + output_type: "string", + flow_control: true, + args: [] + }, + "From Base64": { + description: "Base64 is a notation for encoding arbitrary byte data using a restricted set of symbols that can be conveniently used by humans and processed by computers.

              This operation decodes data from an ASCII Base64 string back into its raw format.

              e.g. aGVsbG8= becomes hello", + run: Base64.run_from, + highlight: Base64.highlight_from, + highlight_reverse: Base64.highlight_to, + input_type: "string", + output_type: "byte_array", + args: [ + { + name: "Alphabet", + type: "editable_option", + value: Base64.ALPHABET_OPTIONS + }, + { + name: "Remove non‑alphabet chars", + type: "boolean", + value: Base64.REMOVE_NON_ALPH_CHARS + } + ] + }, + "To Base64": { + description: "Base64 is a notation for encoding arbitrary byte data using a restricted set of symbols that can be conveniently used by humans and processed by computers.

              This operation encodes data in an ASCII Base64 string.

              e.g. hello becomes aGVsbG8=", + run: Base64.run_to, + highlight: Base64.highlight_to, + highlight_reverse: Base64.highlight_from, + input_type: "byte_array", + output_type: "string", + args: [ + { + name: "Alphabet", + type: "editable_option", + value: Base64.ALPHABET_OPTIONS + }, + ] + }, + "From Base32": { + description: "Base32 is a notation for encoding arbitrary byte data using a restricted set of symbols that can be conveniently used by humans and processed by computers. It uses a smaller set of characters than Base64, usually the uppercase alphabet and the numbers 2 to 7.", + run: Base64.run_from_32, + input_type: "string", + output_type: "byte_array", + args: [ + { + name: "Alphabet", + type: "binary_string", + value: Base64.BASE32_ALPHABET + }, + { + name: "Remove non‑alphabet chars", + type: "boolean", + value: Base64.REMOVE_NON_ALPH_CHARS + } + ] + }, + "To Base32": { + description: "Base32 is a notation for encoding arbitrary byte data using a restricted set of symbols that can be conveniently used by humans and processed by computers. It uses a smaller set of characters than Base64, usually the uppercase alphabet and the numbers 2 to 7.", + run: Base64.run_to_32, + input_type: "byte_array", + output_type: "string", + args: [ + { + name: "Alphabet", + type: "binary_string", + value: Base64.BASE32_ALPHABET + } + ] + }, + "Show Base64 offsets": { + description: "When a string is within a block of data and the whole block is Base64'd, the string itself could be represented in Base64 in three distinct ways depending on its offset within the block.

              This operation shows all possible offsets for a given string so that each possible encoding can be considered.", + run: Base64.run_offsets, + input_type: "byte_array", + output_type: "html", + args: [ + { + name: "Alphabet", + type: "binary_string", + value: Base64.ALPHABET + }, + { + name: "Show variable chars and padding", + type: "boolean", + value: Base64.OFFSETS_SHOW_VARIABLE + } + ] + }, + "XOR": { + description: "XOR the input with the given key.
              e.g. fe023da5

              Options
              Null preserving: If the current byte is 0x00 or the same as the key, skip it.

              Differential: Set the key to the value of the previously decoded byte.", + run: BitwiseOp.run_xor, + highlight: true, + highlight_reverse: true, + input_type: "byte_array", + output_type: "byte_array", + args: [ + { + name: "Key", + type: "toggle_string", + value: "", + toggle_values: BitwiseOp.KEY_FORMAT + }, + { + name: "Null preserving", + type: "boolean", + value: BitwiseOp.XOR_PRESERVE_NULLS + }, + { + name: "Differential", + type: "boolean", + value: BitwiseOp.XOR_DIFFERENTIAL + } + ] + }, + "XOR Brute Force": { + description: "Enumerate all possible XOR solutions. Current maximum key length is 2 due to browser performance.

              Optionally enter a regex string that you expect to find in the plaintext to filter results (crib).", + run: BitwiseOp.run_xor_brute, + input_type: "byte_array", + output_type: "string", + args: [ + { + name: "Key length", + type: "option", + value: BitwiseOp.XOR_BRUTE_KEY_LENGTH + }, + { + name: "Length of sample", + type: "number", + value: BitwiseOp.XOR_BRUTE_SAMPLE_LENGTH + }, + { + name: "Offset of sample", + type: "number", + value: BitwiseOp.XOR_BRUTE_SAMPLE_OFFSET + }, + { + name: "Null preserving", + type: "boolean", + value: BitwiseOp.XOR_PRESERVE_NULLS + }, + { + name: "Differential", + type: "boolean", + value: BitwiseOp.XOR_DIFFERENTIAL + }, + { + name: "Crib (known plaintext string)", + type: "binary_string", + value: "" + }, + { + name: "Print key", + type: "boolean", + value: BitwiseOp.XOR_BRUTE_PRINT_KEY + }, + { + name: "Output as hex", + type: "boolean", + value: BitwiseOp.XOR_BRUTE_OUTPUT_HEX + } + ] + }, + "NOT": { + description: "Returns the inverse of each byte.", + run: BitwiseOp.run_not, + highlight: true, + highlight_reverse: true, + input_type: "byte_array", + output_type: "byte_array", + args: [] + }, + "AND": { + description: "AND the input with the given key.
              e.g. fe023da5", + run: BitwiseOp.run_and, + highlight: true, + highlight_reverse: true, + input_type: "byte_array", + output_type: "byte_array", + args: [ + { + name: "Key", + type: "toggle_string", + value: "", + toggle_values: BitwiseOp.KEY_FORMAT + } + ] + }, + "OR": { + description: "OR the input with the given key.
              e.g. fe023da5", + run: BitwiseOp.run_or, + highlight: true, + highlight_reverse: true, + input_type: "byte_array", + output_type: "byte_array", + args: [ + { + name: "Key", + type: "toggle_string", + value: "", + toggle_values: BitwiseOp.KEY_FORMAT + } + ] + }, + "ADD": { + description: "ADD the input with the given key (e.g. fe023da5), MOD 255", + run: BitwiseOp.run_add, + highlight: true, + highlight_reverse: true, + input_type: "byte_array", + output_type: "byte_array", + args: [ + { + name: "Key", + type: "toggle_string", + value: "", + toggle_values: BitwiseOp.KEY_FORMAT + } + ] + }, + "SUB": { + description: "SUB the input with the given key (e.g. fe023da5), MOD 255", + run: BitwiseOp.run_sub, + highlight: true, + highlight_reverse: true, + input_type: "byte_array", + output_type: "byte_array", + args: [ + { + name: "Key", + type: "toggle_string", + value: "", + toggle_values: BitwiseOp.KEY_FORMAT + } + ] + }, + "From Hex": { + description: "Converts a hexadecimal byte string back into a its raw value.

              e.g. ce 93 ce b5 ce b9 ce ac 20 cf 83 ce bf cf 85 0a becomes the UTF-8 encoded string Γειά σου", + run: ByteRepr.run_from_hex, + highlight: ByteRepr.highlight_from, + highlight_reverse: ByteRepr.highlight_to, + input_type: "string", + output_type: "byte_array", + args: [ + { + name: "Delimiter", + type: "option", + value: ByteRepr.HEX_DELIM_OPTIONS + } + ] + }, + "To Hex": { + description: "Converts the input string to hexadecimal bytes separated by the specified delimiter.

              e.g. The UTF-8 encoded string Γειά σου becomes ce 93 ce b5 ce b9 ce ac 20 cf 83 ce bf cf 85 0a", + run: ByteRepr.run_to_hex, + highlight: ByteRepr.highlight_to, + highlight_reverse: ByteRepr.highlight_from, + input_type: "byte_array", + output_type: "string", + args: [ + { + name: "Delimiter", + type: "option", + value: ByteRepr.HEX_DELIM_OPTIONS + } + ] + }, + "From Charcode": { + description: "Converts unicode character codes back into text.

              e.g. 0393 03b5 03b9 03ac 20 03c3 03bf 03c5 becomes Γειά σου", + run: ByteRepr.run_from_charcode, + highlight: ByteRepr.highlight_from, + highlight_reverse: ByteRepr.highlight_to, + input_type: "string", + output_type: "byte_array", + args: [ + { + name: "Delimiter", + type: "option", + value: ByteRepr.DELIM_OPTIONS + }, + { + name: "Base", + type: "number", + value: ByteRepr.CHARCODE_BASE + } + ] + }, + "To Charcode": { + description: "Converts text to its unicode character code equivalent.

              e.g. Γειά σου becomes 0393 03b5 03b9 03ac 20 03c3 03bf 03c5", + run: ByteRepr.run_to_charcode, + highlight: ByteRepr.highlight_to, + highlight_reverse: ByteRepr.highlight_from, + input_type: "string", + output_type: "string", + args: [ + { + name: "Delimiter", + type: "option", + value: ByteRepr.DELIM_OPTIONS + }, + { + name: "Base", + type: "number", + value: ByteRepr.CHARCODE_BASE + } + ] + }, + "From Binary": { + description: "Converts a binary string back into its raw form.

              e.g. 01001000 01101001 becomes Hi", + run: ByteRepr.run_from_binary, + highlight: ByteRepr.highlight_from_binary, + highlight_reverse: ByteRepr.highlight_to_binary, + input_type: "string", + output_type: "byte_array", + args: [ + { + name: "Delimiter", + type: "option", + value: ByteRepr.BIN_DELIM_OPTIONS + } + ] + }, + "To Binary": { + description: "Displays the input data as a binary string.

              e.g. Hi becomes 01001000 01101001", + run: ByteRepr.run_to_binary, + highlight: ByteRepr.highlight_to_binary, + highlight_reverse: ByteRepr.highlight_from_binary, + input_type: "byte_array", + output_type: "string", + args: [ + { + name: "Delimiter", + type: "option", + value: ByteRepr.BIN_DELIM_OPTIONS + } + ] + }, + "From Decimal": { + description: "Converts the data from an ordinal integer array back into its raw form.

              e.g. 72 101 108 108 111 becomes Hello", + run: ByteRepr.run_from_decimal, + input_type: "string", + output_type: "byte_array", + args: [ + { + name: "Delimiter", + type: "option", + value: ByteRepr.DELIM_OPTIONS + } + ] + }, + "To Decimal": { + description: "Converts the input data to an ordinal integer array.

              e.g. Hello becomes 72 101 108 108 111", + run: ByteRepr.run_to_decimal, + input_type: "byte_array", + output_type: "string", + args: [ + { + name: "Delimiter", + type: "option", + value: ByteRepr.DELIM_OPTIONS + } + ] + }, + "From Hexdump": { + description: "Attempts to convert a hexdump back into raw data. This operation supports many different hexdump variations, but probably not all. Make sure you verify that the data it gives you is correct before continuing analysis.", + run: Hexdump.run_from, + highlight: Hexdump.highlight_from, + highlight_reverse: Hexdump.highlight_to, + input_type: "string", + output_type: "byte_array", + args: [] + }, + "To Hexdump": { + description: "Creates a hexdump of the input data, displaying both the hexademinal values of each byte and an ASCII representation alongside.", + run: Hexdump.run_to, + highlight: Hexdump.highlight_to, + highlight_reverse: Hexdump.highlight_from, + input_type: "byte_array", + output_type: "string", + args: [ + { + name: "Width", + type: "number", + value: Hexdump.WIDTH + }, + { + name: "Upper case hex", + type: "boolean", + value: Hexdump.UPPER_CASE + }, + { + name: "Include final length", + type: "boolean", + value: Hexdump.INCLUDE_FINAL_LENGTH + } + ] + }, + "From Base": { + description: "Converts a number to decimal from a given numerical base.", + run: Base.run_from, + input_type: "string", + output_type: "number", + args: [ + { + name: "Radix", + type: "number", + value: Base.DEFAULT_RADIX + } + ] + }, + "To Base": { + description: "Converts a decimal number to a given numerical base.", + run: Base.run_to, + input_type: "number", + output_type: "string", + args: [ + { + name: "Radix", + type: "number", + value: Base.DEFAULT_RADIX + } + ] + }, + "From HTML Entity": { + description: "Converts HTML entities back to characters

              e.g. &amp; becomes &", // tags required to stop the browser just printing & + run: HTML.run_from_entity, + input_type: "string", + output_type: "string", + args: [] + }, + "To HTML Entity": { + description: "Converts characters to HTML entities

              e.g. & becomes &amp;", // tags required to stop the browser just printing & + run: HTML.run_to_entity, + input_type: "string", + output_type: "string", + args: [ + { + name: "Convert all characters", + type: "boolean", + value: HTML.CONVERT_ALL + }, + { + name: "Convert to", + type: "option", + value: HTML.CONVERT_OPTIONS + } + ] + }, + "Strip HTML tags": { + description: "Removes all HTML tags from the input.", + run: HTML.run_strip_tags, + input_type: "string", + output_type: "string", + args: [ + { + name: "Remove indentation", + type: "boolean", + value: HTML.REMOVE_INDENTATION + }, + { + name: "Remove excess line breaks", + type: "boolean", + value: HTML.REMOVE_LINE_BREAKS + } + ] + }, + "URL Decode": { + description: "Converts URI/URL percent-encoded characters back to their raw values.

              e.g. %3d becomes =", + run: URL_.run_from, + input_type: "string", + output_type: "string", + args: [] + }, + "URL Encode": { + description: "Encodes problematic characters into percent-encoding, a format supported by URIs/URLs.

              e.g. = becomes %3d", + run: URL_.run_to, + input_type: "string", + output_type: "string", + args: [ + { + name: "Encode all special chars", + type: "boolean", + value: URL_.ENCODE_ALL + } + ] + }, + "Parse URI": { + description: "Pretty prints complicated Uniform Resource Identifier (URI) strings for ease of reading. Particularly useful for Uniform Resource Locators (URLs) with a lot of arguments.", + run: URL_.run_parse, + input_type: "string", + output_type: "string", + args: [] + }, + "Unescape Unicode Characters": { + description: "Converts unicode-escaped character notation back into raw characters.

              Supports the prefixes:
              • \\u
              • %u
              • U+
              e.g. \\u03c3\\u03bf\\u03c5 becomes σου", + run: Unicode.run_unescape, + input_type: "string", + output_type: "string", + args: [ + { + name: "Prefix", + type: "option", + value: Unicode.PREFIXES + } + ] + }, + "From Quoted Printable": { + description: "Converts QP-encoded text back to standard text.", + run: QuotedPrintable.run_from, + input_type: "string", + output_type: "byte_array", + args: [] + }, + "To Quoted Printable": { + description: "Quoted-Printable, or QP encoding, is an encoding using printable ASCII characters (alphanumeric and the equals sign '=') to transmit 8-bit data over a 7-bit data path or, generally, over a medium which is not 8-bit clean. It is defined as a MIME content transfer encoding for use in e-mail.

              QP works by using the equals sign '=' as an escape character. It also limits line length to 76, as some software has limits on line length.", + run: QuotedPrintable.run_to, + input_type: "byte_array", + output_type: "string", + args: [] + }, + "From Punycode": { + description: "Punycode is a way to represent Unicode with the limited character subset of ASCII supported by the Domain Name System.

              e.g. mnchen-3ya decodes to münchen", + run: Punycode.run_to_unicode, + input_type: "string", + output_type: "string", + args: [ + { + name: "Internationalised domain name", + type: "boolean", + value: Punycode.IDN + } + ] + }, + "To Punycode": { + description: "Punycode is a way to represent Unicode with the limited character subset of ASCII supported by the Domain Name System.

              e.g. münchen encodes to mnchen-3ya", + run: Punycode.run_to_ascii, + input_type: "string", + output_type: "string", + args: [ + { + name: "Internationalised domain name", + type: "boolean", + value: Punycode.IDN + } + ] + }, + "From Hex Content": { + description: "Translates hexadecimal bytes in text back to raw bytes.

              e.g. foo|3d|bar becomes foo=bar.", + run: ByteRepr.run_from_hex_content, + input_type: "string", + output_type: "byte_array", + args: [] + }, + "To Hex Content": { + description: "Converts special characters in a string to hexadecimal.

              e.g. foo=bar becomes foo|3d|bar.", + run: ByteRepr.run_to_hex_content, + input_type: "byte_array", + output_type: "string", + args: [ + { + name: "Convert", + type: "option", + value: ByteRepr.HEX_CONTENT_CONVERT_WHICH + }, + { + name: "Print spaces between bytes", + type: "boolean", + value: ByteRepr.HEX_CONTENT_SPACES_BETWEEN_BYTES + }, + ] + }, + "Change IP format": { + description: "Convert an IP address from one format to another, e.g. 172.20.23.54 to ac141736", + run: IP.run_change_ip_format, + input_type: "string", + output_type: "string", + args: [ + { + name: "Input format", + type: "option", + value: IP.IP_FORMAT_LIST + }, + { + name: "Output format", + type: "option", + value: IP.IP_FORMAT_LIST + } + ] + }, + "Parse IP range": { + description: "Given a CIDR range (e.g. 10.0.0.0/24) or a hyphenated range (e.g. 10.0.0.0 - 10.0.1.0), this operation provides network information and enumerates all IP addresses in the range.

              IPv6 is supported but will not be enumerated.", + run: IP.run_parse_ip_range, + input_type: "string", + output_type: "string", + args: [ + { + name: "Include network info", + type: "boolean", + value: IP.INCLUDE_NETWORK_INFO + }, + { + name: "Enumerate IP addresses", + type: "boolean", + value: IP.ENUMERATE_ADDRESSES + }, + { + name: "Allow large queries", + type: "boolean", + value: IP.ALLOW_LARGE_LIST + } + ] + }, + "Group IP addresses": { + description: "Groups a list of IP addresses into subnets. Supports both IPv4 and IPv6 addresses.", + run: IP.run_group_ips, + input_type: "string", + output_type: "string", + args: [ + { + name: "Delimiter", + type: "option", + value: IP.DELIM_OPTIONS + }, + { + name: "Subnet (CIDR)", + type: "number", + value: IP.GROUP_CIDR + }, + { + name: "Only show the subnets", + type: "boolean", + value: IP.GROUP_ONLY_SUBNET + } + ] + }, + "Parse IPv6 address": { + description: "Displays the longhand and shorthand versions of a valid IPv6 address.

              Recognises all reserved ranges and parses encapsulated or tunnelled addresses including Teredo and 6to4.", + run: IP.run_parse_ipv6, + input_type: "string", + output_type: "string", + args: [] + }, + "Text encoding": { + description: "Translates the data between different character encodings.

              Supported charsets are:
              • UTF8
              • UTF16
              • UTF16LE (little-endian)
              • UTF16BE (big-endian)
              • Hex
              • Base64
              • Latin1 (ISO-8859-1)
              • Windows-1251
              ", + run: CharEnc.run, + input_type: "string", + output_type: "string", + args: [ + { + name: "Input type", + type: "option", + value: CharEnc.IO_FORMAT + }, + { + name: "Output type", + type: "option", + value: CharEnc.IO_FORMAT + }, + ] + }, + "AES Decrypt": { + description: "To successfully decrypt AES, you need either:
              • The passphrase
              • Or the key and IV
              The IV should be the first 16 bytes of encrypted material.", + run: Cipher.run_aes_dec, + input_type: "string", + output_type: "string", + args: [ + { + name: "Passphrase/Key", + type: "toggle_string", + value: "", + toggle_values: Cipher.IO_FORMAT2 + }, + { + name: "IV", + type: "toggle_string", + value: "", + toggle_values: Cipher.IO_FORMAT1 + + }, + { + name: "Salt", + type: "toggle_string", + value: "", + toggle_values: Cipher.IO_FORMAT1 + }, + { + name: "Mode", + type: "option", + value: Cipher.MODES + }, + { + name: "Padding", + type: "option", + value: Cipher.PADDING + }, + { + name: "Input format", + type: "option", + value: Cipher.IO_FORMAT1 + }, + { + name: "Output format", + type: "option", + value: Cipher.IO_FORMAT2 + }, + ] + }, + "AES Encrypt": { + description: "Input: Either enter a passphrase (which will be used to derive a key using the OpenSSL KDF) or both the key and IV.

              Advanced Encryption Standard (AES) is a U.S. Federal Information Processing Standard (FIPS). It was selected after a 5-year process where 15 competing designs were evaluated.

              AES-128, AES-192, and AES-256 are supported. The variant will be chosen based on the size of the key passed in. If a passphrase is used, a 256-bit key will be generated.", + run: Cipher.run_aes_enc, + input_type: "string", + output_type: "string", + args: [ + { + name: "Passphrase/Key", + type: "toggle_string", + value: "", + toggle_values: Cipher.IO_FORMAT2 + }, + { + name: "IV", + type: "toggle_string", + value: "", + toggle_values: Cipher.IO_FORMAT1 + + }, + { + name: "Salt", + type: "toggle_string", + value: "", + toggle_values: Cipher.IO_FORMAT1 + }, + { + name: "Mode", + type: "option", + value: Cipher.MODES + }, + { + name: "Padding", + type: "option", + value: Cipher.PADDING + }, + { + name: "Output result", + type: "option", + value: Cipher.RESULT_TYPE + }, + { + name: "Output format", + type: "option", + value: Cipher.IO_FORMAT1 + }, + ] + }, + "DES Decrypt": { + description: "To successfully decrypt DES, you need either:
              • The passphrase
              • Or the key and IV
              The IV should be the first 8 bytes of encrypted material.", + run: Cipher.run_des_dec, + input_type: "string", + output_type: "string", + args: [ + { + name: "Passphrase/Key", + type: "toggle_string", + value: "", + toggle_values: Cipher.IO_FORMAT2 + }, + { + name: "IV", + type: "toggle_string", + value: "", + toggle_values: Cipher.IO_FORMAT1 + + }, + { + name: "Salt", + type: "toggle_string", + value: "", + toggle_values: Cipher.IO_FORMAT1 + }, + { + name: "Mode", + type: "option", + value: Cipher.MODES + }, + { + name: "Padding", + type: "option", + value: Cipher.PADDING + }, + { + name: "Input format", + type: "option", + value: Cipher.IO_FORMAT1 + }, + { + name: "Output format", + type: "option", + value: Cipher.IO_FORMAT2 + }, + ] + }, + "DES Encrypt": { + description: "Input: Either enter a passphrase (which will be used to derive a key using the OpenSSL KDF) or both the key and IV.

              DES is a previously dominant algorithm for encryption, and was published as an official U.S. Federal Information Processing Standard (FIPS). It is now considered to be insecure due to its small key size.", + run: Cipher.run_des_enc, + input_type: "string", + output_type: "string", + args: [ + { + name: "Passphrase/Key", + type: "toggle_string", + value: "", + toggle_values: Cipher.IO_FORMAT2 + }, + { + name: "IV", + type: "toggle_string", + value: "", + toggle_values: Cipher.IO_FORMAT1 + + }, + { + name: "Salt", + type: "toggle_string", + value: "", + toggle_values: Cipher.IO_FORMAT1 + }, + { + name: "Mode", + type: "option", + value: Cipher.MODES + }, + { + name: "Padding", + type: "option", + value: Cipher.PADDING + }, + { + name: "Output result", + type: "option", + value: Cipher.RESULT_TYPE + }, + { + name: "Output format", + type: "option", + value: Cipher.IO_FORMAT1 + }, + ] + }, + "Triple DES Decrypt": { + description: "To successfully decrypt Triple DES, you need either:
              • The passphrase
              • Or the key and IV
              The IV should be the first 8 bytes of encrypted material.", + run: Cipher.run_triple_des_dec, + input_type: "string", + output_type: "string", + args: [ + { + name: "Passphrase/Key", + type: "toggle_string", + value: "", + toggle_values: Cipher.IO_FORMAT2 + }, + { + name: "IV", + type: "toggle_string", + value: "", + toggle_values: Cipher.IO_FORMAT1 + + }, + { + name: "Salt", + type: "toggle_string", + value: "", + toggle_values: Cipher.IO_FORMAT1 + }, + { + name: "Mode", + type: "option", + value: Cipher.MODES + }, + { + name: "Padding", + type: "option", + value: Cipher.PADDING + }, + { + name: "Input format", + type: "option", + value: Cipher.IO_FORMAT1 + }, + { + name: "Output format", + type: "option", + value: Cipher.IO_FORMAT2 + }, + ] + }, + "Triple DES Encrypt": { + description: "Input: Either enter a passphrase (which will be used to derive a key using the OpenSSL KDF) or both the key and IV.

              Triple DES applies DES three times to each block to increase key size.", + run: Cipher.run_triple_des_enc, + input_type: "string", + output_type: "string", + args: [ + { + name: "Passphrase/Key", + type: "toggle_string", + value: "", + toggle_values: Cipher.IO_FORMAT2 + }, + { + name: "IV", + type: "toggle_string", + value: "", + toggle_values: Cipher.IO_FORMAT1 + + }, + { + name: "Salt", + type: "toggle_string", + value: "", + toggle_values: Cipher.IO_FORMAT1 + }, + { + name: "Mode", + type: "option", + value: Cipher.MODES + }, + { + name: "Padding", + type: "option", + value: Cipher.PADDING + }, + { + name: "Output result", + type: "option", + value: Cipher.RESULT_TYPE + }, + { + name: "Output format", + type: "option", + value: Cipher.IO_FORMAT1 + }, + ] + }, + "Blowfish Decrypt": { + description: "Blowfish is a symmetric-key block cipher designed in 1993 by Bruce Schneier and included in a large number of cipher suites and encryption products. AES now receives more attention.", + run: Cipher.run_blowfish_dec, + input_type: "string", + output_type: "string", + args: [ + { + name: "Key", + type: "toggle_string", + value: "", + toggle_values: Cipher.IO_FORMAT2 + }, + { + name: "Mode", + type: "option", + value: Cipher.BLOWFISH_MODES + }, + { + name: "Input format", + type: "option", + value: Cipher.IO_FORMAT3 + }, + ] + }, + "Blowfish Encrypt": { + description: "Blowfish is a symmetric-key block cipher designed in 1993 by Bruce Schneier and included in a large number of cipher suites and encryption products. AES now receives more attention.", + run: Cipher.run_blowfish_enc, + input_type: "string", + output_type: "string", + args: [ + { + name: "Key", + type: "toggle_string", + value: "", + toggle_values: Cipher.IO_FORMAT2 + }, + { + name: "Mode", + type: "option", + value: Cipher.BLOWFISH_MODES + }, + { + name: "Output format", + type: "option", + value: Cipher.IO_FORMAT3 + }, + ] + }, + "Rabbit Decrypt": { + description: "To successfully decrypt Rabbit, you need either:
              • The passphrase
              • Or the key and IV (This is currently broken. You need the key and salt at the moment.)
              The IV should be the first 8 bytes of encrypted material.", + run: Cipher.run_rabbit_dec, + input_type: "string", + output_type: "string", + args: [ + { + name: "Passphrase/Key", + type: "toggle_string", + value: "", + toggle_values: Cipher.IO_FORMAT2 + }, + { + name: "IV", + type: "toggle_string", + value: "", + toggle_values: Cipher.IO_FORMAT1 + + }, + { + name: "Salt", + type: "toggle_string", + value: "", + toggle_values: Cipher.IO_FORMAT1 + }, + { + name: "Mode", + type: "option", + value: Cipher.MODES + }, + { + name: "Padding", + type: "option", + value: Cipher.PADDING + }, + { + name: "Input format", + type: "option", + value: Cipher.IO_FORMAT1 + }, + { + name: "Output format", + type: "option", + value: Cipher.IO_FORMAT2 + }, + ] + }, + "Rabbit Encrypt": { + description: "Input: Either enter a passphrase (which will be used to derive a key using the OpenSSL KDF) or both the key and IV.

              Rabbit is a high-performance stream cipher and a finalist in the eSTREAM Portfolio. It is one of the four designs selected after a 3 1/2 year process where 22 designs were evaluated.", + run: Cipher.run_rabbit_enc, + input_type: "string", + output_type: "string", + args: [ + { + name: "Passphrase/Key", + type: "toggle_string", + value: "", + toggle_values: Cipher.IO_FORMAT2 + }, + { + name: "IV", + type: "toggle_string", + value: "", + toggle_values: Cipher.IO_FORMAT1 + + }, + { + name: "Salt", + type: "toggle_string", + value: "", + toggle_values: Cipher.IO_FORMAT1 + }, + { + name: "Mode", + type: "option", + value: Cipher.MODES + }, + { + name: "Padding", + type: "option", + value: Cipher.PADDING + }, + { + name: "Output result", + type: "option", + value: Cipher.RESULT_TYPE + }, + { + name: "Output format", + type: "option", + value: Cipher.IO_FORMAT1 + }, + ] + }, + "RC4": { + description: "RC4 is a widely-used stream cipher. It is used in popular protocols such as SSL and WEP. Although remarkable for its simplicity and speed, the algorithm's history doesn't inspire confidence in its security.", + run: Cipher.run_rc4, + highlight: true, + highlight_reverse: true, + input_type: "string", + output_type: "string", + args: [ + { + name: "Passphrase", + type: "toggle_string", + value: "", + toggle_values: Cipher.IO_FORMAT2 + }, + { + name: "Input format", + type: "option", + value: Cipher.IO_FORMAT4 + }, + { + name: "Output format", + type: "option", + value: Cipher.IO_FORMAT4 + }, + ] + }, + "RC4 Drop": { + description: "It was discovered that the first few bytes of the RC4 keystream are strongly non-random and leak information about the key. We can defend against this attack by discarding the initial portion of the keystream. This modified algorithm is traditionally called RC4-drop.", + run: Cipher.run_rc4drop, + highlight: true, + highlight_reverse: true, + input_type: "string", + output_type: "string", + args: [ + { + name: "Passphrase", + type: "toggle_string", + value: "", + toggle_values: Cipher.IO_FORMAT2 + }, + { + name: "Input format", + type: "option", + value: Cipher.IO_FORMAT4 + }, + { + name: "Output format", + type: "option", + value: Cipher.IO_FORMAT4 + }, + { + name: "Number of bytes to drop", + type: "number", + value: Cipher.RC4DROP_BYTES + }, + ] + }, + "Derive PBKDF2 key": { + description: "PBKDF2 is a password-based key derivation function. In many applications of cryptography, user security is ultimately dependent on a password, and because a password usually can't be used directly as a cryptographic key, some processing is required.

              A salt provides a large set of keys for any given password, and an iteration count increases the cost of producing keys from a password, thereby also increasing the difficulty of attack.

              Enter your passphrase as the input and then set the relevant options to generate a key.", + run: Cipher.run_pbkdf2, + input_type: "string", + output_type: "string", + args: [ + { + name: "Key size", + type: "number", + value: Cipher.KDF_KEY_SIZE + }, + { + name: "Iterations", + type: "number", + value: Cipher.KDF_ITERATIONS + }, + { + name: "Salt (hex)", + type: "string", + value: "" + }, + { + name: "Input format", + type: "option", + value: Cipher.IO_FORMAT2 + }, + { + name: "Output format", + type: "option", + value: Cipher.IO_FORMAT3 + }, + ] + }, + "Derive EVP key": { + description: "EVP is a password-based key derivation function used extensively in OpenSSL. In many applications of cryptography, user security is ultimately dependent on a password, and because a password usually can't be used directly as a cryptographic key, some processing is required.

              A salt provides a large set of keys for any given password, and an iteration count increases the cost of producing keys from a password, thereby also increasing the difficulty of attack.

              Enter your passphrase as the input and then set the relevant options to generate a key.", + run: Cipher.run_evpkdf, + input_type: "string", + output_type: "string", + args: [ + { + name: "Key size", + type: "number", + value: Cipher.KDF_KEY_SIZE + }, + { + name: "Iterations", + type: "number", + value: Cipher.KDF_ITERATIONS + }, + { + name: "Salt (hex)", + type: "string", + value: "" + }, + { + name: "Input format", + type: "option", + value: Cipher.IO_FORMAT2 + }, + { + name: "Output format", + type: "option", + value: Cipher.IO_FORMAT3 + }, + ] + }, + "Rotate right": { + description: "Rotates each byte to the right by the number of bits specified. Currently only supports 8-bit values.", + run: Rotate.run_rotr, + highlight: true, + highlight_reverse: true, + input_type: "byte_array", + output_type: "byte_array", + args: [ + { + name: "Number of bits", + type: "number", + value: Rotate.ROTATE_AMOUNT + }, + { + name: "Rotate as a whole", + type: "boolean", + value: Rotate.ROTATE_WHOLE + } + ] + }, + "Rotate left": { + description: "Rotates each byte to the left by the number of bits specified. Currently only supports 8-bit values.", + run: Rotate.run_rotl, + highlight: true, + highlight_reverse: true, + input_type: "byte_array", + output_type: "byte_array", + args: [ + { + name: "Number of bits", + type: "number", + value: Rotate.ROTATE_AMOUNT + }, + { + name: "Rotate as a whole", + type: "boolean", + value: Rotate.ROTATE_WHOLE + } + ] + }, + "ROT13": { + description: "A simple caesar substitution cipher which rotates alphabet characters by the specified amount (default 13).", + run: Rotate.run_rot13, + highlight: true, + highlight_reverse: true, + input_type: "byte_array", + output_type: "byte_array", + args: [ + { + name: "Rotate lower case chars", + type: "boolean", + value: Rotate.ROT13_LOWERCASE + }, + { + name: "Rotate upper case chars", + type: "boolean", + value: Rotate.ROT13_UPPERCASE + }, + { + name: "Amount", + type: "number", + value: Rotate.ROT13_AMOUNT + }, + ] + }, + "Strip HTTP headers": { + description: "Removes HTTP headers from a request or response by looking for the first instance of a double newline.", + run: HTTP.run_strip_headers, + input_type: "string", + output_type: "string", + args: [] + }, + "Parse User Agent": { + description: "Attempts to identify and categorise information contained in a user-agent string.", + run: HTTP.run_parse_user_agent, + input_type: "string", + output_type: "string", + args: [] + }, + "Format MAC addresses": { + description: "Displays given MAC addresses in multiple different formats.

              Expects addresses in a list separated by newlines, spaces or commas.

              WARNING: There are no validity checks.", + run: MAC.run_format, + input_type: "string", + output_type: "string", + args: [ + { + name: "Output case", + type: "option", + value: MAC.OUTPUT_CASE + }, + { + name: "No delimiter", + type: "boolean", + value: MAC.NO_DELIM + }, + { + name: "Dash delimiter", + type: "boolean", + value: MAC.DASH_DELIM + }, + { + name: "Colon delimiter", + type: "boolean", + value: MAC.COLON_DELIM + }, + { + name: "Cisco style", + type: "boolean", + value: MAC.CISCO_STYLE + } + ] + }, + "Offset checker": { + description: "Compares multiple inputs (separated by the specified delimiter) and highlights matching characters which appear at the same position in all samples.", + run: StrUtils.run_offset_checker, + input_type: "string", + output_type: "html", + args: [ + { + name: "Sample delimiter", + type: "binary_string", + value: StrUtils.OFF_CHK_SAMPLE_DELIMITER + } + ] + }, + "Remove whitespace": { + description: "Optionally removes all spaces, carriage returns, line feeds, tabs and form feeds from the input data.

              This operation also supports the removal of full stops which are sometimes used to represent non-printable bytes in ASCII output.", + run: Tidy.run_remove_whitespace, + input_type: "string", + output_type: "string", + args: [ + { + name: "Spaces", + type: "boolean", + value: Tidy.REMOVE_SPACES + }, + { + name: "Carriage returns (\\r)", + type: "boolean", + value: Tidy.REMOVE_CARIAGE_RETURNS + }, + { + name: "Line feeds (\\n)", + type: "boolean", + value: Tidy.REMOVE_LINE_FEEDS + }, + { + name: "Tabs", + type: "boolean", + value: Tidy.REMOVE_TABS + }, + { + name: "Form feeds (\\f)", + type: "boolean", + value: Tidy.REMOVE_FORM_FEEDS + }, + { + name: "Full stops", + type: "boolean", + value: Tidy.REMOVE_FULL_STOPS + } + ] + }, + "Remove null bytes": { + description: "Removes all null bytes (0x00) from the input.", + run: Tidy.run_remove_nulls, + input_type: "byte_array", + output_type: "byte_array", + args: [] + }, + "Drop bytes": { + description: "Cuts the specified number of bytes out of the data.", + run: Tidy.run_drop_bytes, + input_type: "byte_array", + output_type: "byte_array", + args: [ + { + name: "Start", + type: "number", + value: Tidy.DROP_START + }, + { + name: "Length", + type: "number", + value: Tidy.DROP_LENGTH + }, + { + name: "Apply to each line", + type: "boolean", + value: Tidy.APPLY_TO_EACH_LINE + } + ] + }, + "Take bytes": { + description: "Takes a slice of the specified number of bytes from the data.", + run: Tidy.run_take_bytes, + input_type: "byte_array", + output_type: "byte_array", + args: [ + { + name: "Start", + type: "number", + value: Tidy.TAKE_START + }, + { + name: "Length", + type: "number", + value: Tidy.TAKE_LENGTH + }, + { + name: "Apply to each line", + type: "boolean", + value: Tidy.APPLY_TO_EACH_LINE + } + ] + }, + "Pad lines": { + description: "Add the specified number of the specified character to the beginning or end of each line", + run: Tidy.run_pad, + input_type: "string", + output_type: "string", + args: [ + { + name: "Position", + type: "option", + value: Tidy.PAD_POSITION + }, + { + name: "Length", + type: "number", + value: Tidy.PAD_LENGTH + }, + { + name: "Character", + type: "binary_short_string", + value: Tidy.PAD_CHAR + } + ] + }, + "Reverse": { + description: "Reverses the input string.", + run: SeqUtils.run_reverse, + input_type: "byte_array", + output_type: "byte_array", + args: [ + { + name: "By", + type: "option", + value: SeqUtils.REVERSE_BY + } + ] + }, + "Sort": { + description: "Alphabetically sorts strings separated by the specified delimiter.

              The IP address option supports IPv4 only.", + run: SeqUtils.run_sort, + input_type: "string", + output_type: "string", + args: [ + { + name: "Delimiter", + type: "option", + value: SeqUtils.DELIMITER_OPTIONS + }, + { + name: "Reverse", + type: "boolean", + value: SeqUtils.SORT_REVERSE + }, + { + name: "Order", + type: "option", + value: SeqUtils.SORT_ORDER + } + ] + }, + "Unique": { + description: "Removes duplicate strings from the input.", + run: SeqUtils.run_unique, + input_type: "string", + output_type: "string", + args: [ + { + name: "Delimiter", + type: "option", + value: SeqUtils.DELIMITER_OPTIONS + } + ] + }, + "Count occurrences": { + description: "Counts the number of times the provided string occurs in the input.", + run: SeqUtils.run_count, + input_type: "string", + output_type: "number", + args: [ + { + name: "Search string", + type: "toggle_string", + value: "", + toggle_values: SeqUtils.SEARCH_TYPE + } + ] + }, + "Add line numbers": { + description: "Adds line numbers to the output.", + run: SeqUtils.run_add_line_numbers, + input_type: "string", + output_type: "string", + args: [] + }, + "Remove line numbers": { + description: "Removes line numbers from the output if they can be trivially detected.", + run: SeqUtils.run_remove_line_numbers, + input_type: "string", + output_type: "string", + args: [] + }, + "Find / Replace": { + description: "Replaces all occurrences of the first string with the second.

              The three match options are only relevant to regex search strings.", + run: StrUtils.run_find_replace, + manual_bake: true, + input_type: "string", + output_type: "string", + args: [ + { + name: "Find", + type: "toggle_string", + value: "", + toggle_values: StrUtils.SEARCH_TYPE + }, + { + name: "Replace", + type: "binary_string", + value: "" + }, + { + name: "Global match", + type: "boolean", + value: StrUtils.FIND_REPLACE_GLOBAL, + }, + { + name: "Case insensitive", + type: "boolean", + value: StrUtils.FIND_REPLACE_CASE, + }, + { + name: "Multiline matching", + type: "boolean", + value: StrUtils.FIND_REPLACE_MULTILINE, + }, + + ] + }, + "To Upper case": { + description: "Converts the input string to upper case, optionally limiting scope to only the first character in each word, sentence or paragraph.", + run: StrUtils.run_upper, + highlight: true, + highlight_reverse: true, + input_type: "string", + output_type: "string", + args: [ + { + name: "Scope", + type: "option", + value: StrUtils.CASE_SCOPE + } + ] + }, + "To Lower case": { + description: "Converts every character in the input to lower case.", + run: StrUtils.run_lower, + highlight: true, + highlight_reverse: true, + input_type: "string", + output_type: "string", + args: [] + }, + "Split": { + description: "Splits a string into sections around a given delimiter.", + run: StrUtils.run_split, + input_type: "string", + output_type: "string", + args: [ + { + name: "Split delimiter", + type: "binary_short_string", + value: StrUtils.SPLIT_DELIM + }, + { + name: "Join delimiter", + type: "option", + value: StrUtils.DELIMITER_OPTIONS + } + ] + }, + "Strings": { + description: "Extracts all strings from the input.", + run: Extract.run_strings, + input_type: "string", + output_type: "string", + args: [ + { + name: "Minimum length", + type: "number", + value: Extract.MIN_STRING_LEN + }, + { + name: "Display total", + type: "boolean", + value: Extract.DISPLAY_TOTAL + } + ] + }, + "Extract IP addresses": { + description: "Extracts all IPv4 and IPv6 addresses.

              Warning: Given a string 710.65.0.456, this will match 10.65.0.45 so always check the original input!", + run: Extract.run_ip, + input_type: "string", + output_type: "string", + args: [ + { + name: "IPv4", + type: "boolean", + value: Extract.INCLUDE_IPV4 + }, + { + name: "IPv6", + type: "boolean", + value: Extract.INCLUDE_IPV6 + }, + { + name: "Remove local IPv4 addresses", + type: "boolean", + value: Extract.REMOVE_LOCAL + }, + { + name: "Display total", + type: "boolean", + value: Extract.DISPLAY_TOTAL + } + ] + }, + "Extract email addresses": { + description: "Extracts all email addresses from the input.", + run: Extract.run_email, + input_type: "string", + output_type: "string", + args: [ + { + name: "Display total", + type: "boolean", + value: Extract.DISPLAY_TOTAL + } + ] + }, + "Extract MAC addresses": { + description: "Extracts all Media Access Control (MAC) addresses from the input.", + run: Extract.run_mac, + input_type: "string", + output_type: "string", + args: [ + { + name: "Display total", + type: "boolean", + value: Extract.DISPLAY_TOTAL + } + ] + }, + "Extract URLs": { + description: "Extracts Uniform Resource Locators (URLs) from the input. The protocol (http, ftp etc.) is required otherwise there will be far too many false positives.", + run: Extract.run_urls, + input_type: "string", + output_type: "string", + args: [ + { + name: "Display total", + type: "boolean", + value: Extract.DISPLAY_TOTAL + } + ] + }, + "Extract domains": { + description: "Extracts domain names with common Top-Level Domains (TLDs).
              Note that this will not include paths. Use Extract URLs to find entire URLs.", + run: Extract.run_domains, + input_type: "string", + output_type: "string", + args: [ + { + name: "Display total", + type: "boolean", + value: Extract.DISPLAY_TOTAL + } + ] + }, + "Extract file paths": { + description: "Extracts anything that looks like a Windows or UNIX file path.

              Note that if UNIX is selected, there will likely be a lot of false positives.", + run: Extract.run_file_paths, + input_type: "string", + output_type: "string", + args: [ + { + name: "Windows", + type: "boolean", + value: Extract.INCLUDE_WIN_PATH + }, + { + name: "UNIX", + type: "boolean", + value: Extract.INCLUDE_UNIX_PATH + }, + { + name: "Display total", + type: "boolean", + value: Extract.DISPLAY_TOTAL + } + ] + }, + "Extract dates": { + description: "Extracts dates in the following formats
              • yyyy-mm-dd
              • dd/mm/yyyy
              • mm/dd/yyyy
              Dividers can be any of /, -, . or space", + run: Extract.run_dates, + input_type: "string", + output_type: "string", + args: [ + { + name: "Display total", + type: "boolean", + value: Extract.DISPLAY_TOTAL + } + ] + }, + "Regular expression": { + description: "Define your own regular expression to search the input data with, optionally choosing from a list of pre-defined patterns.", + run: StrUtils.run_regex, + manual_bake: true, + input_type: "string", + output_type: "html", + args: [ + { + name: "Built in regexes", + type: "populate_option", + value: StrUtils.REGEX_PRE_POPULATE, + target: 1, + }, + { + name: "Regex", + type: "text", + value: "" + }, + { + name: "Case insensitive", + type: "boolean", + value: StrUtils.REGEX_CASE_INSENSITIVE + }, + { + name: "Multiline matching", + type: "boolean", + value: StrUtils.REGEX_MULTILINE_MATCHING + }, + { + name: "Display total", + type: "boolean", + value: StrUtils.DISPLAY_TOTAL + }, + { + name: "Output format", + type: "option", + value: StrUtils.OUTPUT_FORMAT + }, + ] + }, + "From UNIX Timestamp": { + description: "Converts a UNIX timestamp to a datetime string.

              e.g. 978346800 becomes Mon 1 January 2001 11:00:00 UTC", + run: DateTime.run_from_unix_timestamp, + input_type: "number", + output_type: "string", + args: [ + { + name: "Units", + type: "option", + value: DateTime.UNITS + } + ] + }, + "To UNIX Timestamp": { + description: "Parses a datetime string and returns the corresponding UNIX timestamp.

              e.g. Mon 1 January 2001 11:00:00 UTC becomes 978346800", + run: DateTime.run_to_unix_timestamp, + input_type: "string", + output_type: "number", + args: [ + { + name: "Units", + type: "option", + value: DateTime.UNITS + } + ] + }, + "Translate DateTime Format": { + description: "Parses a datetime string in one format and re-writes it in another.

              Run with no input to see the relevant format string examples.", + run: DateTime.run_translate_format, + input_type: "string", + output_type: "html", + args: [ + { + name: "Built in formats", + type: "populate_option", + value: DateTime.DATETIME_FORMATS, + target: 1 + }, + { + name: "Input format string", + type: "binary_string", + value: DateTime.INPUT_FORMAT_STRING + }, + { + name: "Input timezone", + type: "option", + value: DateTime.TIMEZONES + }, + { + name: "Output format string", + type: "binary_string", + value: DateTime.OUTPUT_FORMAT_STRING + }, + { + name: "Output timezone", + type: "option", + value: DateTime.TIMEZONES + } + ] + }, + "Parse DateTime": { + description: "Parses a DateTime string in your specified format and displays it in whichever timezone you choose with the following information:
              • Date
              • Time
              • Period (AM/PM)
              • Timezone
              • UTC offset
              • Daylight Saving Time
              • Leap year
              • Days in this month
              • Day of year
              • Week number
              • Quarter
              Run with no input to see format string examples if required.", + run: DateTime.run_parse, + input_type: "string", + output_type: "html", + args: [ + { + name: "Built in formats", + type: "populate_option", + value: DateTime.DATETIME_FORMATS, + target: 1 + }, + { + name: "Input format string", + type: "binary_string", + value: DateTime.INPUT_FORMAT_STRING + }, + { + name: "Input timezone", + type: "option", + value: DateTime.TIMEZONES + }, + ] + }, + "Convert distance": { + description: "Converts a unit of distance to another format.", + run: Convert.run_distance, + input_type: "number", + output_type: "number", + args: [ + { + name: "Input units", + type: "option", + value: Convert.DISTANCE_UNITS + }, + { + name: "Output units", + type: "option", + value: Convert.DISTANCE_UNITS + } + ] + }, + "Convert area": { + description: "Converts a unit of area to another format.", + run: Convert.run_area, + input_type: "number", + output_type: "number", + args: [ + { + name: "Input units", + type: "option", + value: Convert.AREA_UNITS + }, + { + name: "Output units", + type: "option", + value: Convert.AREA_UNITS + } + ] + }, + "Convert mass": { + description: "Converts a unit of mass to another format.", + run: Convert.run_mass, + input_type: "number", + output_type: "number", + args: [ + { + name: "Input units", + type: "option", + value: Convert.MASS_UNITS + }, + { + name: "Output units", + type: "option", + value: Convert.MASS_UNITS + } + ] + }, + "Convert speed": { + description: "Converts a unit of speed to another format.", + run: Convert.run_speed, + input_type: "number", + output_type: "number", + args: [ + { + name: "Input units", + type: "option", + value: Convert.SPEED_UNITS + }, + { + name: "Output units", + type: "option", + value: Convert.SPEED_UNITS + } + ] + }, + "Convert data units": { + description: "Converts a unit of data to another format.", + run: Convert.run_data_size, + input_type: "number", + output_type: "number", + args: [ + { + name: "Input units", + type: "option", + value: Convert.DATA_UNITS + }, + { + name: "Output units", + type: "option", + value: Convert.DATA_UNITS + } + ] + }, + "Raw Deflate": { + description: "Compresses data using the deflate algorithm with no headers.", + run: Compress.run_raw_deflate, + input_type: "byte_array", + output_type: "byte_array", + args: [ + { + name: "Compression type", + type: "option", + value: Compress.COMPRESSION_TYPE + } + ] + }, + "Raw Inflate": { + description: "Decompresses data which has been compressed using the deflate algorithm with no headers.", + run: Compress.run_raw_inflate, + input_type: "byte_array", + output_type: "byte_array", + args: [ + { + name: "Start index", + type: "number", + value: Compress.INFLATE_INDEX + }, + { + name: "Initial output buffer size", + type: "number", + value: Compress.INFLATE_BUFFER_SIZE + }, + { + name: "Buffer expansion type", + type: "option", + value: Compress.INFLATE_BUFFER_TYPE + }, + { + name: "Resize buffer after decompression", + type: "boolean", + value: Compress.INFLATE_RESIZE + }, + { + name: "Verify result", + type: "boolean", + value: Compress.INFLATE_VERIFY + } + ] + }, + "Zlib Deflate": { + description: "Compresses data using the deflate algorithm adding zlib headers.", + run: Compress.run_zlib_deflate, + input_type: "byte_array", + output_type: "byte_array", + args: [ + { + name: "Compression type", + type: "option", + value: Compress.COMPRESSION_TYPE + } + ] + }, + "Zlib Inflate": { + description: "Decompresses data which has been compressed using the deflate algorithm with zlib headers.", + run: Compress.run_zlib_inflate, + input_type: "byte_array", + output_type: "byte_array", + args: [ + { + name: "Start index", + type: "number", + value: Compress.INFLATE_INDEX + }, + { + name: "Initial output buffer size", + type: "number", + value: Compress.INFLATE_BUFFER_SIZE + }, + { + name: "Buffer expansion type", + type: "option", + value: Compress.INFLATE_BUFFER_TYPE + }, + { + name: "Resize buffer after decompression", + type: "boolean", + value: Compress.INFLATE_RESIZE + }, + { + name: "Verify result", + type: "boolean", + value: Compress.INFLATE_VERIFY + } + ] + }, + "Gzip": { + description: "Compresses data using the deflate algorithm with gzip headers.", + run: Compress.run_gzip, + input_type: "byte_array", + output_type: "byte_array", + args: [ + { + name: "Compression type", + type: "option", + value: Compress.COMPRESSION_TYPE + }, + { + name: "Filename (optional)", + type: "string", + value: "" + }, + { + name: "Comment (optional)", + type: "string", + value: "" + }, + { + name: "Include file checksum", + type: "boolean", + value: Compress.GZIP_CHECKSUM + } + ] + }, + "Gunzip": { + description: "Decompresses data which has been compressed using the deflate algorithm with gzip headers.", + run: Compress.run_gunzip, + input_type: "byte_array", + output_type: "byte_array", + args: [] + }, + "Zip": { + description: "Compresses data using the PKZIP algorithm with the given filename.

              No support for multiple files at this time.", + run: Compress.run_pkzip, + input_type: "byte_array", + output_type: "byte_array", + args: [ + { + name: "Filename", + type: "string", + value: Compress.PKZIP_FILENAME + }, + { + name: "Comment", + type: "string", + value: "" + }, + { + name: "Password", + type: "binary_string", + value: "" + }, + { + name: "Compression method", + type: "option", + value: Compress.COMPRESSION_METHOD + }, + { + name: "Operating system", + type: "option", + value: Compress.OS + }, + { + name: "Compression type", + type: "option", + value: Compress.COMPRESSION_TYPE + } + ] + }, + "Unzip": { + description: "Decompresses data using the PKZIP algorithm and displays it per file, with support for passwords.", + run: Compress.run_pkunzip, + input_type: "byte_array", + output_type: "html", + args: [ + { + name: "Password", + type: "binary_string", + value: "" + }, + { + name: "Verify result", + type: "boolean", + value: Compress.PKUNZIP_VERIFY + } + ] + }, + "Bzip2 Decompress": { + description: "Decompresses data using the Bzip2 algorithm.", + run: Compress.run_bzip2_decompress, + input_type: "byte_array", + output_type: "string", + args: [] + }, + "Generic Code Beautify": { + description: "Attempts to pretty print C-style languages such as C, C++, C#, Java, PHP, JavaScript etc.

              This will not do a perfect job, and the resulting code may not work any more. This operation is designed purely to make obfuscated or minified code more easy to read and understand.

              Things which will not work properly:
              • For loop formatting
              • Do-While loop formatting
              • Switch/Case indentation
              • Certain bit shift operators
              ", + run: Code.run_generic_beautify, + input_type: "string", + output_type: "string", + args: [] + }, + "JavaScript Parser": { + description: "Returns an Abstract Syntax Tree for valid JavaScript code.", + run: JS.run_parse, + input_type: "string", + output_type: "string", + args: [ + { + name: "Location info", + type: "boolean", + value: JS.PARSE_LOC + }, + { + name: "Range info", + type: "boolean", + value: JS.PARSE_RANGE + }, + { + name: "Include tokens array", + type: "boolean", + value: JS.PARSE_TOKENS + }, + { + name: "Include comments array", + type: "boolean", + value: JS.PARSE_COMMENT + }, + { + name: "Report errors and try to continue", + type: "boolean", + value: JS.PARSE_TOLERANT + }, + ] + }, + "JavaScript Beautify": { + description: "Parses and pretty prints valid JavaScript code. Also works with JavaScript Object Notation (JSON).", + run: JS.run_beautify, + input_type: "string", + output_type: "string", + args: [ + { + name: "Indent string", + type: "binary_short_string", + value: JS.BEAUTIFY_INDENT + }, + { + name: "Quotes", + type: "option", + value: JS.BEAUTIFY_QUOTES + }, + { + name: "Semicolons before closing braces", + type: "boolean", + value: JS.BEAUTIFY_SEMICOLONS + }, + { + name: "Include comments", + type: "boolean", + value: JS.BEAUTIFY_COMMENT + }, + ] + }, + "JavaScript Minify": { + description: "Compresses JavaScript code.", + run: JS.run_minify, + input_type: "string", + output_type: "string", + args: [] + }, + "XML Beautify": { + description: "Indents and prettifies eXtensible Markup Language (XML) code.", + run: Code.run_xml_beautify, + input_type: "string", + output_type: "string", + args: [ + { + name: "Indent string", + type: "binary_short_string", + value: Code.BEAUTIFY_INDENT + } + ] + }, + "JSON Beautify": { + description: "Indents and prettifies JavaScript Object Notation (JSON) code.", + run: Code.run_json_beautify, + input_type: "string", + output_type: "string", + args: [ + { + name: "Indent string", + type: "binary_short_string", + value: Code.BEAUTIFY_INDENT + } + ] + }, + "CSS Beautify": { + description: "Indents and prettifies Cascading Style Sheets (CSS) code.", + run: Code.run_css_beautify, + input_type: "string", + output_type: "string", + args: [ + { + name: "Indent string", + type: "binary_short_string", + value: Code.BEAUTIFY_INDENT + } + ] + }, + "SQL Beautify": { + description: "Indents and prettifies Structured Query Language (SQL) code.", + run: Code.run_sql_beautify, + input_type: "string", + output_type: "string", + args: [ + { + name: "Indent string", + type: "binary_short_string", + value: Code.BEAUTIFY_INDENT + } + ] + }, + "XML Minify": { + description: "Compresses eXtensible Markup Language (XML) code.", + run: Code.run_xml_minify, + input_type: "string", + output_type: "string", + args: [ + { + name: "Preserve comments", + type: "boolean", + value: Code.PRESERVE_COMMENTS + } + ] + }, + "JSON Minify": { + description: "Compresses JavaScript Object Notation (JSON) code.", + run: Code.run_json_minify, + input_type: "string", + output_type: "string", + args: [] + }, + "CSS Minify": { + description: "Compresses Cascading Style Sheets (CSS) code.", + run: Code.run_css_minify, + input_type: "string", + output_type: "string", + args: [ + { + name: "Preserve comments", + type: "boolean", + value: Code.PRESERVE_COMMENTS + } + ] + }, + "SQL Minify": { + description: "Compresses Structured Query Language (SQL) code.", + run: Code.run_sql_minify, + input_type: "string", + output_type: "string", + args: [] + }, + "Analyse hash": { + description: "Tries to determine information about a given hash and suggests which algorithm may have been used to generate it based on its length.", + run: Hash.run_analyse, + input_type: "string", + output_type: "string", + args: [] + }, + "MD5": { + description: "MD5 (Message-Digest 5) is a widely used hash function. It has been used in a variety of security applications and is also commonly used to check the integrity of files.

              However, MD5 is not collision resistant and it isn't suitable for applications like SSL/TLS certificates or digital signatures that rely on this property.", + run: Hash.run_md5, + input_type: "string", + output_type: "string", + args: [] + }, + "SHA1": { + description: "The SHA (Secure Hash Algorithm) hash functions were designed by the NSA. SHA-1 is the most established of the existing SHA hash functions and it is used in a variety of security applications and protocols.

              However, SHA-1's collision resistance has been weakening as new attacks are discovered or improved.", + run: Hash.run_sha1, + input_type: "string", + output_type: "string", + args: [] + }, + "SHA224": { + description: "SHA-224 is largely identical to SHA-256 but is truncated to 224 bytes.", + run: Hash.run_sha224, + input_type: "string", + output_type: "string", + args: [] + }, + "SHA256": { + description: "SHA-256 is one of the four variants in the SHA-2 set. It isn't as widely used as SHA-1, though it provides much better security.", + run: Hash.run_sha256, + input_type: "string", + output_type: "string", + args: [] + }, + "SHA384": { + description: "SHA-384 is largely identical to SHA-512 but is truncated to 384 bytes.", + run: Hash.run_sha384, + input_type: "string", + output_type: "string", + args: [] + }, + "SHA512": { + description: "SHA-512 is largely identical to SHA-256 but operates on 64-bit words rather than 32.", + run: Hash.run_sha512, + input_type: "string", + output_type: "string", + args: [] + }, + "SHA3": { + description: "This is an implementation of Keccak[c=2d]. SHA3 functions based on different implementations of Keccak will give different results.", + run: Hash.run_sha3, + input_type: "string", + output_type: "string", + args: [ + { + name: "Output length", + type: "option", + value: Hash.SHA3_LENGTH + } + ] + }, + "RIPEMD-160": { + description: "RIPEMD (RACE Integrity Primitives Evaluation Message Digest) is a family of cryptographic hash functions developed in Leuven, Belgium, by Hans Dobbertin, Antoon Bosselaers and Bart Preneel at the COSIC research group at the Katholieke Universiteit Leuven, and first published in 1996.

              RIPEMD was based upon the design principles used in MD4, and is similar in performance to the more popular SHA-1.

              RIPEMD-160 is an improved, 160-bit version of the original RIPEMD, and the most common version in the family.", + run: Hash.run_ripemd160, + input_type: "string", + output_type: "string", + args: [] + }, + "HMAC": { + description: "Keyed-Hash Message Authentication Codes (HMAC) are a mechanism for message authentication using cryptographic hash functions.", + run: Hash.run_hmac, + input_type: "string", + output_type: "string", + args: [ + { + name: "Password", + type: "binary_string", + value: "" + }, + { + name: "Hashing function", + type: "option", + value: Hash.HMAC_FUNCTIONS + }, + ] + }, + "Fletcher-16 Checksum": { + description: "The Fletcher checksum is an algorithm for computing a position-dependent checksum devised by John Gould Fletcher at Lawrence Livermore Labs in the late 1970s.

              The objective of the Fletcher checksum was to provide error-detection properties approaching those of a cyclic redundancy check but with the lower computational effort associated with summation techniques.", + run: Checksum.run_fletcher16, + input_type: "byte_array", + output_type: "string", + args: [] + }, + "Adler-32 Checksum": { + description: "Adler-32 is a checksum algorithm which was invented by Mark Adler in 1995, and is a modification of the Fletcher checksum. Compared to a cyclic redundancy check of the same length, it trades reliability for speed (preferring the latter).

              Adler-32 is more reliable than Fletcher-16, and slightly less reliable than Fletcher-32.", + run: Checksum.run_adler32, + input_type: "byte_array", + output_type: "string", + args: [] + }, + "CRC-32 Checksum": { + description: "A cyclic redundancy check (CRC) is an error-detecting code commonly used in digital networks and storage devices to detect accidental changes to raw data.

              The CRC was invented by W. Wesley Peterson in 1961; the 32-bit CRC function of Ethernet and many other standards is the work of several researchers and was published in 1975.", + run: Checksum.run_crc32, + input_type: "byte_array", + output_type: "string", + args: [] + }, + "Generate all hashes": { + description: "Generates all available hashes and checksums for the input.", + run: Hash.run_all, + input_type: "string", + output_type: "string", + args: [] + }, + "Entropy": { + description: "Calculates the Shannon entropy of the input data which gives an idea of its randomness. 8 is the maximum.", + run: Entropy.run_entropy, + input_type: "byte_array", + output_type: "html", + args: [ + { + name: "Chunk size", + type: "number", + value: Entropy.CHUNK_SIZE + } + ] + }, + "Frequency distribution": { + description: "Displays the distribution of bytes in the data as a graph.", + run: Entropy.run_freq_distrib, + input_type: "byte_array", + output_type: "html", + args: [ + { + name: "Show 0%'s", + type: "boolean", + value: Entropy.FREQ_ZEROS + } + ] + }, + "Numberwang": { + description: "Based on the popular gameshow by Mitchell and Webb.", + run: Numberwang.run, + input_type: "string", + output_type: "string", + args: [] + }, + "Parse X.509 certificate": { + description: "X.509 is an ITU-T standard for a public key infrastructure (PKI) and Privilege Management Infrastructure (PMI). It is commonly involved with SSL/TLS security.

              This operation displays the contents of a certificate in a human readable format, similar to the openssl command line tool.", + run: PublicKey.run_parse_x509, + input_type: "string", + output_type: "string", + args: [ + { + name: "Input format", + type: "option", + value: PublicKey.X509_INPUT_FORMAT + } + ] + }, + "PEM to Hex": { + description: "Converts PEM (Privacy Enhanced Mail) format to a hexadecimal DER (Distinguished Encoding Rules) string.", + run: PublicKey.run_pem_to_hex, + input_type: "string", + output_type: "string", + args: [] + }, + "Hex to PEM": { + description: "Converts a hexadecimal DER (Distinguished Encoding Rules) string into PEM (Privacy Enhanced Mail) format.", + run: PublicKey.run_hex_to_pem, + input_type: "string", + output_type: "string", + args: [ + { + name: "Header string", + type: "string", + value: PublicKey.PEM_HEADER_STRING + } + ] + }, + "Hex to Object Identifier": { + description: "Converts a hexadecimal string into an object identifier (OID).", + run: PublicKey.run_hex_to_object_identifier, + input_type: "string", + output_type: "string", + args: [] + }, + "Object Identifier to Hex": { + description: "Converts an object identifier (OID) into a hexadecimal string.", + run: PublicKey.run_object_identifier_to_hex, + input_type: "string", + output_type: "string", + args: [] + }, + "Parse ASN.1 hex string": { + description: "Abstract Syntax Notation One (ASN.1) is a standard and notation that describes rules and structures for representing, encoding, transmitting, and decoding data in telecommunications and computer networking.

              This operation parses arbitrary ASN.1 data and presents the resulting tree.", + run: PublicKey.run_parse_asn1_hex_string, + input_type: "string", + output_type: "string", + args: [ + { + name: "Starting index", + type: "number", + value: 0 + }, + { + name: "Truncate octet strings longer than", + type: "number", + value: PublicKey.ASN1_TRUNCATE_LENGTH + } + ] + }, + "Detect File Type": { + description: "Attempts to guess the MIME (Multipurpose Internet Mail Extensions) type of the data based on 'magic bytes'.

              Currently supports the following file types: 7z, amr, avi, bmp, bz2, class, cr2, crx, dex, dmg, doc, elf, eot, epub, exe, flac, flv, gif, gz, ico, iso, jpg, jxr, m4a, m4v, mid, mkv, mov, mp3, mp4, mpg, ogg, otf, pdf, png, ppt, ps, psd, rar, rtf, sqlite, swf, tar, tar.z, tif, ttf, utf8, vmdk, wav, webm, webp, wmv, woff, woff2, xls, xz, zip.", + run: FileType.run_detect, + input_type: "byte_array", + output_type: "string", + args: [] + }, + "Scan for Embedded Files": { + description: "Scans the data for potential embedded files by looking for magic bytes at all offsets. This operation is prone to false positives.

              WARNING: Files over about 100KB in size will take a VERY long time to process.", + run: FileType.run_scan_for_embedded_files, + input_type: "byte_array", + output_type: "string", + args: [ + { + name: "Ignore common byte sequences", + type: "boolean", + value: FileType.IGNORE_COMMON_BYTE_SEQUENCES + } + ] + }, + "Expand alphabet range": { + description: "Expand an alphabet range string into a list of the characters in that range.

              e.g. a-z becomes abcdefghijklmnopqrstuvwxyz.", + run: SeqUtils.run_expand_alph_range, + input_type: "string", + output_type: "string", + args: [ + { + name: "Delimiter", + type: "binary_string", + value: "" + } + ] + }, + "Diff": { + description: "Compares two inputs (separated by the specified delimiter) and highlights the differences between them.", + run: StrUtils.run_diff, + input_type: "string", + output_type: "html", + args: [ + { + name: "Sample delimiter", + type: "binary_string", + value: StrUtils.DIFF_SAMPLE_DELIMITER + }, + { + name: "Diff by", + type: "option", + value: StrUtils.DIFF_BY + }, + { + name: "Show added", + type: "boolean", + value: true + }, + { + name: "Show removed", + type: "boolean", + value: true + }, + { + name: "Ignore whitespace (relevant for word and line)", + type: "boolean", + value: false + } + ] + }, + "Parse UNIX file permissions": { + description: "Given a UNIX/Linux file permission string in octal or textual format, this operation explains which permissions are granted to which user groups.

              Input should be in either octal (e.g. 755) or textual (e.g. drwxr-xr-x) format.", + run: OS.run_parse_unix_perms, + input_type: "string", + output_type: "string", + args: [] + }, + "Swap endianness": { + description: "Switches the data from big-endian to little-endian or vice-versa. Data can be read in as hexadecimal or raw bytes. It will be returned in the same format as it is entered.", + run: Endian.run_swap_endianness, + highlight: true, + highlight_reverse: true, + input_type: "string", + output_type: "string", + args: [ + { + name: "Data format", + type: "option", + value: Endian.DATA_FORMAT + }, + { + name: "Word length (bytes)", + type: "number", + value: Endian.WORD_LENGTH + }, + { + name: "Pad incomplete words", + type: "boolean", + value: Endian.PAD_INCOMPLETE_WORDS + } + ] + }, + "Syntax highlighter": { + description: "Adds syntax highlighting to a range of source code languages. Note that this will not indent the code. Use one of the 'Beautify' operations for that.", + run: Code.run_syntax_highlight, + highlight: true, + highlight_reverse: true, + input_type: "string", + output_type: "html", + args: [ + { + name: "Language/File extension", + type: "option", + value: Code.LANGUAGES + }, + { + name: "Display line numbers", + type: "boolean", + value: Code.LINE_NUMS + } + ] + }, + "Parse escaped string": { + description: "Replaces escaped characters with the bytes they represent.

              e.g.Hello\\nWorld becomes Hello
              World
              ", + run: StrUtils.run_parse_escaped_string, + input_type: "string", + output_type: "string", + args: [] + }, + "TCP/IP Checksum": { + description: "Calculates the checksum for a TCP (Transport Control Protocol) or IP (Internet Protocol) header from an input of raw bytes.", + run: Checksum.run_tcp_ip, + input_type: "byte_array", + output_type: "string", + args: [] + }, + "Parse colour code": { + description: "Converts a colour code in a standard format to other standard formats and displays the colour itself.

              Example inputs
              • #d9edf7
              • rgba(217,237,247,1)
              • hsla(200,65%,91%,1)
              • cmyk(0.12, 0.04, 0.00, 0.03)
              ", + run: HTML.run_parse_colour_code, + input_type: "string", + output_type: "html", + args: [] + }, + "Generate UUID": { + description: "Generates an RFC 4122 version 4 compliant Universally Unique Identifier (UUID), also known as a Globally Unique Identifier (GUID).

              A version 4 UUID relies on random numbers, in this case generated using window.crypto if available and falling back to Math.random if not.", + run: UUID.run_generate_v4, + input_type: "string", + output_type: "string", + args: [] + } +}; \ No newline at end of file diff --git a/src/js/core/Chef.js b/src/js/core/Chef.js new file mode 100755 index 00000000..459cdcf9 --- /dev/null +++ b/src/js/core/Chef.js @@ -0,0 +1,120 @@ +/** + * The main controller for CyberChef. + * + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * @class + */ +var Chef = function() { + this.dish = new Dish(); +}; + + +/** + * Runs the recipe over the input. + * + * @param {string} input_text - The input data as a string + * @param {Object[]} recipe_config - The recipe configuration object + * @param {Object} options - The options object storing various user choices + * @param {boolean} options.attemp_highlight - Whether or not to attempt highlighting + * @param {number} progress - The position in the recipe to start from + * @param {number} [step] - The number of operations to execute + * + * @returns {Object} response + * @returns {string} response.result - The output of the recipe + * @returns {string} response.type - The data type of the result + * @returns {number} response.progress - The position that we have got to in the recipe + * @returns {number} response.options - The app options object (which may have been changed) + * @returns {number} response.duration - The number of ms it took to execute the recipe + * @returns {number} response.error - The error object thrown by a failed operation (false if no error) +*/ +Chef.prototype.bake = function(input_text, recipe_config, options, progress, step) { + var start_time = new Date().getTime(), + recipe = new Recipe(recipe_config), + contains_fc = recipe.contains_flow_control(), + error = false; + + // Reset attempt_highlight flag + if (options.hasOwnProperty("attempt_highlight")) { + options.attempt_highlight = true; + } + + if (contains_fc) options.attempt_highlight = false; + + // Clean up progress + if (progress >= recipe_config.length) { + progress = 0; + } + + if (step) { + // Unset breakpoint on this step + recipe.set_breakpoint(progress, false); + // Set breakpoint on next step + recipe.set_breakpoint(progress + 1, true); + } + + // If stepping with flow control, we have to start from the beginning + // but still want to skip all previous breakpoints + if (progress > 0 && contains_fc) { + recipe.remove_breaks_up_to(progress); + progress = 0; + } + + // If starting from scratch, load data + if (progress === 0) { + this.dish.set(input_text, Dish.STRING); + } + + try { + progress = recipe.execute(this.dish, progress); + } catch (err) { + // We can't throw the error from here as we will return in the finally block and ignore it + // so we return the error in the result instead. + error = err; + progress = err.progress; + } finally { + return { + result: this.dish.type == Dish.HTML ? + this.dish.get(Dish.HTML) : + this.dish.get(Dish.STRING), + type: Dish.enum_lookup(this.dish.type), + progress: progress, + options: options, + duration: new Date().getTime() - start_time, + error: error + }; + } +}; + + +/** + * When a browser tab is unfocused and the browser has to run lots of dynamic content in other tabs, + * it swaps out the memory for that tab. If the CyberChef tab has been unfocused for more than a + * minute, we run a silent bake which will force the browser to load and cache all the relevant + * JavaScript code needed to do a real bake. + * + * This will stop baking taking a long time when the CyberChef browser tab has been unfocused for a + * long time and the browser has swapped out all its memory. + * + * The output will not be modified (hence "silent" bake). + * + * This will only actually execute the recipe if auto-bake is enabled, otherwise it will just load + * the recipe, ingredients and dish. + * + * @param {Object[]} recipe_config - The recipe configuration object + * @returns {number} The time it took to run the silent bake in milliseconds. +*/ +Chef.prototype.silent_bake = function(recipe_config) { + var start_time = new Date().getTime(), + recipe = new Recipe(recipe_config), + dish = new Dish("", Dish.STRING); + + try { + recipe.execute(dish); + } catch(err) { + // Suppress all errors + } + return new Date().getTime() - start_time; +}; diff --git a/src/js/core/Dish.js b/src/js/core/Dish.js new file mode 100755 index 00000000..c69ebef3 --- /dev/null +++ b/src/js/core/Dish.js @@ -0,0 +1,202 @@ +/** + * The data being operated on by each operation. + * + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * @class + * @param {byte_array|string|number} value - The value of the input data. + * @param {number} type - The data type of value, see Dish enums. + */ +var Dish = function(value, type) { + this.value = value || typeof value == "string" ? value : null; + this.type = type || Dish.BYTE_ARRAY; +}; + + +/** + * Dish data type enum for byte arrays. + * @readonly + * @enum + */ +Dish.BYTE_ARRAY = 0; +/** + * Dish data type enum for strings. + * @readonly + * @enum + */ +Dish.STRING = 1; +/** + * Dish data type enum for numbers. + * @readonly + * @enum + */ +Dish.NUMBER = 2; +/** + * Dish data type enum for HTML. + * @readonly + * @enum + */ +Dish.HTML = 3; + + +/** + * Returns the data type enum for the given type string. + * + * @static + * @param {string} type_str - The name of the data type. + * @returns {number} The data type enum value. + */ +Dish.type_enum = function(type_str) { + switch (type_str) { + case "byte_array": + case "Byte array": + return Dish.BYTE_ARRAY; + case "string": + case "String": + return Dish.STRING; + case "number": + case "Number": + return Dish.NUMBER; + case "html": + case "HTML": + return Dish.HTML; + default: + throw "Invalid data type string. No matching enum."; + } +}; + + +/** + * Returns the data type string for the given type enum. + * + * @static + * @param {string} type_enum - The enum value of the data type. + * @returns {number} The data type as a string. + */ +Dish.enum_lookup = function(type_enum) { + switch (type_enum) { + case Dish.BYTE_ARRAY: + return "byte_array"; + case Dish.STRING: + return "string"; + case Dish.NUMBER: + return "number"; + case Dish.HTML: + return "html"; + default: + throw "Invalid data type enum. No matching type."; + } +}; + + +/** + * Sets the data value and type and then validates them. + * + * @param {byte_array|string|number} value - The value of the input data. + * @param {number} type - The data type of value, see Dish enums. + */ +Dish.prototype.set = function(value, type) { + this.value = value; + this.type = type; + + if (!this.valid()) { + var sample = Utils.truncate(JSON.stringify(this.value), 13); + throw "Data is not a valid " + Dish.enum_lookup(type) + ": " + sample; + } +}; + + +/** + * Returns the value of the data in the type format specified. + * + * @param {number} type - The data type of value, see Dish enums. + * @returns {byte_array|string|number} The value of the output data. + */ +Dish.prototype.get = function(type) { + if (this.type != type) { + this.translate(type); + } + return this.value; +}; + + +/** + * Translates the data to the given type format. + * + * @param {number} to_type - The data type of value, see Dish enums. + */ +Dish.prototype.translate = function(to_type) { + // Convert data to intermediate byte_array type + switch (this.type) { + case Dish.STRING: + this.value = this.value ? Utils.str_to_byte_array(this.value) : []; + this.type = Dish.BYTE_ARRAY; + break; + case Dish.NUMBER: + this.value = typeof this.value == "number" ? Utils.str_to_byte_array(this.value.toString()) : []; + this.type = Dish.BYTE_ARRAY; + break; + case Dish.HTML: + this.value = this.value ? Utils.str_to_byte_array(Utils.strip_html_tags(this.value, true)) : []; + this.type = Dish.BYTE_ARRAY; + break; + default: + break; + } + + // Convert from byte_array to to_type + switch (to_type) { + case Dish.STRING: + case Dish.HTML: + this.value = this.value ? Utils.byte_array_to_utf8(this.value) : ""; + this.type = Dish.STRING; + break; + case Dish.NUMBER: + this.value = this.value ? parseFloat(Utils.byte_array_to_utf8(this.value)) : 0; + this.type = Dish.NUMBER; + break; + default: + break; + } +}; + + +/** + * Validates that the value is the type that has been specified. + * May have to disable parts of BYTE_ARRAY validation if it effects performance. + * + * @returns {boolean} Whether the data is valid or not. +*/ +Dish.prototype.valid = function() { + switch (this.type) { + case Dish.BYTE_ARRAY: + if (!(this.value instanceof Array)) { + return false; + } + + // Check that every value is a number between 0 - 255 + for (var i = 0; i < this.value.length; i++) { + if (typeof this.value[i] != "number" || + this.value[i] < 0 || + this.value[i] > 255) { + return false; + } + } + return true; + case Dish.STRING: + case Dish.HTML: + if (typeof this.value == "string") { + return true; + } + return false; + case Dish.NUMBER: + if (typeof this.value == "number") { + return true; + } + return false; + default: + return false; + } +}; diff --git a/src/js/core/FlowControl.js b/src/js/core/FlowControl.js new file mode 100755 index 00000000..51af24a0 --- /dev/null +++ b/src/js/core/FlowControl.js @@ -0,0 +1,171 @@ +/** + * Flow Control operations. + * + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * @namespace + */ +var FlowControl = { + + /** + * @constant + * @default + */ + FORK_DELIM: "\\n", + /** + * @constant + * @default + */ + MERGE_DELIM: "\\n", + + /** + * Fork operation. + * + * @param {Object} state - The current state of the recipe. + * @param {number} state.progress - The current position in the recipe. + * @param {Dish} state.dish - The Dish being operated on. + * @param {Operation[]} state.op_list - The list of operations in the recipe. + * @returns {Object} The updated state of the recipe. + */ + run_fork: function(state) { + var op_list = state.op_list, + input_type = op_list[state.progress].input_type, + output_type = op_list[state.progress].output_type, + input = state.dish.get(input_type), + ings = op_list[state.progress].get_ing_values(), + split_delim = ings[0], + merge_delim = ings[1], + sub_op_list = [], + inputs = []; + + if (input) + inputs = input.split(split_delim); + + // Create sub_op_list for each tranche to operate on + // (all remaining operations unless we encounter a Merge) + for (var i = state.progress + 1; i < op_list.length; i++) { + if (op_list[i].name == "Merge" && !op_list[i].is_disabled()) { + break; + } else { + sub_op_list.push(op_list[i]); + } + } + + var recipe = new Recipe(), + output = "", + progress; + + recipe.add_operations(sub_op_list); + + // Run recipe over each tranche + for (i = 0; i < inputs.length; i++) { + var dish = new Dish(inputs[i], input_type); + progress = recipe.execute(dish, 0); + output += dish.get(output_type) + merge_delim; + } + + state.dish.set(output, output_type); + state.progress += progress; + return state; + }, + + + /** + * Merge operation. + * + * @param {Object} state - The current state of the recipe. + * @param {number} state.progress - The current position in the recipe. + * @param {Dish} state.dish - The Dish being operated on. + * @param {Operation[]} state.op_list - The list of operations in the recipe. + * @returns {Object} The updated state of the recipe. + */ + run_merge: function(state) { + // No need to actually do anything here. The fork operation will + // merge when it sees this operation. + return state; + }, + + + /** + * @constant + * @default + */ + JUMP_NUM: 0, + /** + * @constant + * @default + */ + MAX_JUMPS: 10, + + /** + * Jump operation. + * + * @param {Object} state - The current state of the recipe. + * @param {number} state.progress - The current position in the recipe. + * @param {Dish} state.dish - The Dish being operated on. + * @param {Operation[]} state.op_list - The list of operations in the recipe. + * @param {number} state.num_jumps - The number of jumps taken so far. + * @returns {Object} The updated state of the recipe. + */ + run_jump: function(state) { + var ings = state.op_list[state.progress].get_ing_values(), + jump_num = ings[0], + max_jumps = ings[1]; + + if (state.num_jumps >= max_jumps) { + throw "Reached maximum jumps, sorry!"; + } + + state.progress += jump_num; + state.num_jumps++; + return state; + }, + + + /** + * Conditional Jump operation. + * + * @param {Object} state - The current state of the recipe. + * @param {number} state.progress - The current position in the recipe. + * @param {Dish} state.dish - The Dish being operated on. + * @param {Operation[]} state.op_list - The list of operations in the recipe. + * @param {number} state.num_jumps - The number of jumps taken so far. + * @returns {Object} The updated state of the recipe. + */ + run_cond_jump: function(state) { + var ings = state.op_list[state.progress].get_ing_values(), + dish = state.dish, + regex_str = ings[0], + jump_num = ings[1], + max_jumps = ings[2]; + + if (state.num_jumps >= max_jumps) { + throw "Reached maximum jumps, sorry!"; + } + + if (regex_str !== "" && dish.get(Dish.STRING).search(regex_str) > -1) { + state.progress += jump_num; + state.num_jumps++; + } + + return state; + }, + + + /** + * Return operation. + * + * @param {Object} state - The current state of the recipe. + * @param {number} state.progress - The current position in the recipe. + * @param {Dish} state.dish - The Dish being operated on. + * @param {Operation[]} state.op_list - The list of operations in the recipe. + * @returns {Object} The updated state of the recipe. + */ + run_return: function(state) { + state.progress = state.op_list.length; + return state; + }, + +}; diff --git a/src/js/core/Ingredient.js b/src/js/core/Ingredient.js new file mode 100755 index 00000000..df551b6f --- /dev/null +++ b/src/js/core/Ingredient.js @@ -0,0 +1,86 @@ +/** + * The arguments to operations. + * + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * @class + * @param {Object} ingredient_config + */ +var Ingredient = function(ingredient_config) { + this.name = ""; + this.type = ""; + this.value = null; + + if (ingredient_config) { + this._parse_config(ingredient_config); + } +}; + + +/** + * Reads and parses the given config. + * + * @private + * @param {Object} ingredient_config + */ +Ingredient.prototype._parse_config = function(ingredient_config) { + this.name = ingredient_config.name; + this.type = ingredient_config.type; +}; + + +/** + * Returns the value of the Ingredient as it should be displayed in a recipe config. + * + * @returns {*} + */ +Ingredient.prototype.get_config = function() { + return this.value; +}; + + +/** + * Sets the value of the Ingredient. + * + * @param {*} value + */ +Ingredient.prototype.set_value = function(value) { + this.value = Ingredient.prepare(value, this.type); +}; + + +/** + * Most values will be strings when they are entered. This function converts them to the correct + * type. + * + * @static + * @param {*} data + * @param {string} type - The name of the data type. +*/ +Ingredient.prepare = function(data, type) { + switch (type) { + case "binary_string": + case "binary_short_string": + case "editable_option": + return Utils.parse_escaped_chars(data); + case "byte_array": + if (typeof data == "string") { + data = data.replace(/\s+/g, ''); + return Utils.hex_to_byte_array(data); + } else { + return data; + } + break; + case "number": + var number = parseFloat(data); + if (isNaN(number)) { + var sample = Utils.truncate(data.toString(), 10); + throw "Invalid ingredient value. Not a number: " + sample; + } + return number; + default: + return data; + } +}; diff --git a/src/js/core/Operation.js b/src/js/core/Operation.js new file mode 100755 index 00000000..26a1e279 --- /dev/null +++ b/src/js/core/Operation.js @@ -0,0 +1,157 @@ +/** + * The Operation specified by the user to be run. + * + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * @class + * @param {string} operation_name + * @param {Object} operation_config + */ +var Operation = function(operation_name, operation_config) { + this.name = operation_name; + this.description = ""; + this.input_type = -1; + this.output_type = -1; + this.run = null; + this.highlight = null; + this.highlight_reverse = null; + this.breakpoint = false; + this.disabled = false; + this.ing_list = []; + + if (operation_config) { + this._parse_config(operation_config); + } +}; + + +/** + * Reads and parses the given config. + * + * @private + * @param {Object} operation_config + */ +Operation.prototype._parse_config = function(operation_config) { + this.description = operation_config.description; + this.input_type = Dish.type_enum(operation_config.input_type); + this.output_type = Dish.type_enum(operation_config.output_type); + this.run = operation_config.run; + this.highlight = operation_config.highlight; + this.highlight_reverse = operation_config.highlight_reverse; + this.flow_control = operation_config.flow_control; + + for (var a = 0; a < operation_config.args.length; a++) { + var ingredient_config = operation_config.args[a]; + var ingredient = new Ingredient(ingredient_config); + this.add_ingredient(ingredient); + } +}; + + +/** + * Returns the value of the Operation as it should be displayed in a recipe config. + * + * @returns {Object} + */ +Operation.prototype.get_config = function() { + var ingredient_config = []; + + for (var o = 0; o < this.ing_list.length; o++) { + ingredient_config.push(this.ing_list[o].get_config()); + } + + var operation_config = { + "op": this.name, + "args": ingredient_config + }; + + return operation_config; +}; + + +/** + * Adds a new Ingredient to this Operation. + * + * @param {Ingredient} ingredient + */ +Operation.prototype.add_ingredient = function(ingredient) { + this.ing_list.push(ingredient); +}; + + +/** + * Set the Ingredient values for this Operation. + * + * @param {Object[]} ing_values + */ +Operation.prototype.set_ing_values = function(ing_values) { + for (var i = 0; i < ing_values.length; i++) { + this.ing_list[i].set_value(ing_values[i]); + } +}; + + +/** + * Get the Ingredient values for this Operation. + * + * @returns {Object[]} + */ +Operation.prototype.get_ing_values = function() { + var ing_values = []; + for (var i = 0; i < this.ing_list.length; i++) { + ing_values.push(this.ing_list[i].value); + } + return ing_values; +}; + + +/** + * Set whether this Operation has a breakpoint. + * + * @param {boolean} value + */ +Operation.prototype.set_breakpoint = function(value) { + this.breakpoint = !!value; +}; + + +/** + * Returns true if this Operation has a breakpoint set. + * + * @returns {boolean} + */ +Operation.prototype.is_breakpoint = function() { + return this.breakpoint; +}; + + +/** + * Set whether this Operation is disabled. + * + * @param {boolean} value + */ +Operation.prototype.set_disabled = function(value) { + this.disabled = !!value; +}; + + +/** + * Returns true if this Operation is disabled. + * + * @returns {boolean} + */ +Operation.prototype.is_disabled = function() { + return this.disabled; +}; + + +/** + * Returns true if this Operation is a flow control. + * + * @returns {boolean} + */ +Operation.prototype.is_flow_control = function() { + return this.flow_control; +}; diff --git a/src/js/core/Recipe.js b/src/js/core/Recipe.js new file mode 100755 index 00000000..b93d7560 --- /dev/null +++ b/src/js/core/Recipe.js @@ -0,0 +1,215 @@ +/** + * The Recipe controls a list of Operations and the Dish they operate on. + * + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * @class + * @param {Object} recipe_config + */ +var Recipe = function(recipe_config) { + this.op_list = []; + + if (recipe_config) { + this._parse_config(recipe_config); + } +}; + + +/** + * Reads and parses the given config. + * + * @private + * @param {Object} recipe_config + */ +Recipe.prototype._parse_config = function(recipe_config) { + for (var c = 0; c < recipe_config.length; c++) { + var operation_name = recipe_config[c].op; + var operation_config = OperationConfig[operation_name]; + var operation = new Operation(operation_name, operation_config); + operation.set_ing_values(recipe_config[c].args); + operation.set_breakpoint(recipe_config[c].breakpoint); + operation.set_disabled(recipe_config[c].disabled); + this.add_operation(operation); + } +}; + + +/** + * Returns the value of the Recipe as it should be displayed in a recipe config. + * + * @returns {*} + */ +Recipe.prototype.get_config = function() { + var recipe_config = []; + + for (var o = 0; o < this.op_list.length; o++) { + recipe_config.push(this.op_list[o].get_config()); + } + + return recipe_config; +}; + + +/** + * Adds a new Operation to this Recipe. + * + * @param {Operation} operation + */ +Recipe.prototype.add_operation = function(operation) { + this.op_list.push(operation); +}; + + +/** + * Adds a list of Operations to this Recipe. + * + * @param {Operation[]} operations + */ +Recipe.prototype.add_operations = function(operations) { + this.op_list = this.op_list.concat(operations); +}; + + +/** + * Set a breakpoint on a specified Operation. + * + * @param {number} position - The index of the Operation + * @param {boolean} value + */ +Recipe.prototype.set_breakpoint = function(position, value) { + try { + this.op_list[position].set_breakpoint(value); + } catch (err) { + // Ignore index error + } +}; + + +/** + * Remove breakpoints on all Operations in the Recipe up to the specified position. Used by Flow + * Control Fork operation. + * + * @param {number} pos + */ +Recipe.prototype.remove_breaks_up_to = function(pos) { + for (var i = 0; i < pos; i++) { + this.op_list[i].set_breakpoint(false); + } +}; + + +/** + * Returns true if there is an Flow Control Operation in this Recipe. + * + * @returns {boolean} + */ +Recipe.prototype.contains_flow_control = function() { + for (var i = 0; i < this.op_list.length; i++) { + if (this.op_list[i].is_flow_control()) return true; + } + return false; +}; + + +/** + * Returns the index of the last Operation index that will be executed, taking into account disabled + * Operations and breakpoints. + * + * @param {number} [start_index=0] - The index to start searching from + * @returns (number} + */ +Recipe.prototype.last_op_index = function(start_index) { + var i = start_index + 1 || 0, + op; + + for (; i < this.op_list.length; i++) { + op = this.op_list[i]; + if (op.is_disabled()) return i-1; + if (op.is_breakpoint()) return i-1; + } + + return i-1; +}; + + +/** + * Executes each operation in the recipe over the given Dish. + * + * @param {Dish} dish + * @param {number} [start_from=0] - The index of the Operation to start executing from + * @returns {number} - The final progress through the recipe + */ +Recipe.prototype.execute = function(dish, start_from) { + start_from = start_from || 0; + var op, input, output, num_jumps = 0; + + for (var i = start_from; i < this.op_list.length; i++) { + op = this.op_list[i]; + if (op.is_disabled()) { + continue; + } + if (op.is_breakpoint()) { + return i; + } + + try { + input = dish.get(op.input_type); + + if (op.is_flow_control()) { + // Package up the current state + var state = { + "progress" : i, + "dish" : dish, + "op_list" : this.op_list, + "num_jumps" : num_jumps + }; + + state = op.run(state); + i = state.progress; + num_jumps = state.num_jumps; + } else { + output = op.run(input, op.get_ing_values()); + dish.set(output, op.output_type); + } + } catch (err) { + var e = typeof err == "string" ? { message: err } : err; + + e.progress = i; + e.display_str = op.name + " - "; + if (e.fileName) { + e.display_str += e.name + " in " + e.fileName + + " on line " + e.lineNumber + + ".

              Message: " + e.message; + } else { + e.display_str += e.message; + } + + throw e; + } + } + + return this.op_list.length; +}; + + +/** + * Returns the recipe configuration in string format. + * + * @returns {string} + */ +Recipe.prototype.to_string = function() { + return JSON.stringify(this.get_config()); +}; + + +/** + * Creates a Recipe from a given configuration string. + * + * @param {string} recipe_str + */ +Recipe.prototype.from_string = function(recipe_str) { + var recipe_config = JSON.parse(recipe_str); + this._parse_config(recipe_config); +}; diff --git a/src/js/core/Utils.js b/src/js/core/Utils.js new file mode 100755 index 00000000..2e52517b --- /dev/null +++ b/src/js/core/Utils.js @@ -0,0 +1,1144 @@ +/* globals CryptoJS, moment */ + +/** + * Utility functions for use in operations, the core framework and the stage. + * + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * @namespace + */ +var Utils = { + + /** + * Translates an ordinal into a character. + * + * @param {number} o + * @returns {char} + * + * @example + * // returns 'a' + * Utils.chr(97); + */ + chr: function(o) { + return String.fromCharCode(o); + }, + + + /** + * Translates a character into an ordinal. + * + * @param {char} c + * @returns {number} + * + * @example + * // returns 97 + * Utils.ord('a'); + */ + ord: function(c) { + return c.charCodeAt(0); + }, + + + /** + * Adds leading zeros to strings + * + * @param {string} str - String to add leading characters to. + * @param {number} max - Maximum width of the string. + * @param {char} [chr='0'] - The character to pad with. + * @returns {string} + * + * @example + * // returns "0a" + * Utils.pad_left("a", 2); + * + * // returns "000a" + * Utils.pad_left("a", 4); + * + * // returns "xxxa" + * Utils.pad_left("a", 4, "x"); + * + * // returns "bcabchello" + * Utils.pad_left("hello", 10, "abc"); + */ + pad_left: function(str, max, chr) { + chr = chr || "0"; + var start_index = chr.length - (max - str.length); + start_index = start_index < 0 ? 0 : start_index; + return str.length < max ? + Utils.pad_left(chr.slice(start_index, chr.length) + str, max, chr) : str; + }, + + + /** + * Adds trailing spaces to strings. + * + * @param {string} str - String to add trailing characters to. + * @param {number} max - Maximum width of the string. + * @param {char} [chr='0'] - The character to pad with. + * @returns {string} + * + * @example + * // returns "a " + * Utils.pad_right("a", 4); + * + * // returns "axxx" + * Utils.pad_right("a", 4, "x"); + */ + pad_right: function(str, max, chr) { + chr = chr || " "; + return str.length < max ? + Utils.pad_right(str + chr.slice(0, max-str.length), max, chr) : str; + }, + + + /** + * @alias Utils.pad_left + */ + pad: function(str, max, chr) { + return Utils.pad_left(str, max, chr); + }, + + + /** + * Truncates a long string to max length and adds suffix. + * + * @param {string} str - String to truncate + * @param {number} max - Maximum length of the final string + * @param {string} [suffix='...'] - The string to add to the end of the final string + * @returns {string} + * + * @example + * // returns "A long..." + * Utils.truncate("A long string", 9); + * + * // returns "A long s-" + * Utils.truncate("A long string", 9, "-"); + */ + truncate: function(str, max, suffix) { + suffix = suffix || "..."; + if (str.length > max) { + str = str.slice(0, max - suffix.length) + suffix; + } + return str; + }, + + + /** + * Converts a character or number to its hex representation. + * + * @param {char|number} c + * @param {number} [length=2] - The width of the resulting hex number. + * @returns {string} + * + * @example + * // returns "6e" + * Utils.hex("n"); + * + * // returns "6e" + * Utils.hex(110); + */ + hex: function(c, length) { + c = typeof c == "string" ? Utils.ord(c) : c; + length = length || 2; + return Utils.pad(c.toString(16), length); + }, + + + /** + * Converts a character or number to its binary representation. + * + * @param {char|number} c + * @param {number} [length=8] - The width of the resulting binary number. + * @returns {string} + * + * @example + * // returns "01101110" + * Utils.bin("n"); + * + * // returns "01101110" + * Utils.bin(110); + */ + bin: function(c, length) { + c = typeof c == "string" ? Utils.ord(c) : c; + length = length || 8; + return Utils.pad(c.toString(2), length); + }, + + + /** + * Returns a string with all non-printable chars as dots, optionally preserving whitespace. + * + * @param {string} str - The input string to display. + * @param {boolean} [preserve_ws=false] - Whether or not to print whitespace. + * @returns {string} + */ + printable: function(str, preserve_ws) { + if (window && window.app && !window.app.options.treat_as_utf8) { + str = Utils.byte_array_to_chars(Utils.str_to_byte_array(str)); + } + + var re = /[\0-\x08\x0B-\x0C\x0E-\x1F\x7F-\x9F\xAD\u0378\u0379\u037F-\u0383\u038B\u038D\u03A2\u0528-\u0530\u0557\u0558\u0560\u0588\u058B-\u058E\u0590\u05C8-\u05CF\u05EB-\u05EF\u05F5-\u0605\u061C\u061D\u06DD\u070E\u070F\u074B\u074C\u07B2-\u07BF\u07FB-\u07FF\u082E\u082F\u083F\u085C\u085D\u085F-\u089F\u08A1\u08AD-\u08E3\u08FF\u0978\u0980\u0984\u098D\u098E\u0991\u0992\u09A9\u09B1\u09B3-\u09B5\u09BA\u09BB\u09C5\u09C6\u09C9\u09CA\u09CF-\u09D6\u09D8-\u09DB\u09DE\u09E4\u09E5\u09FC-\u0A00\u0A04\u0A0B-\u0A0E\u0A11\u0A12\u0A29\u0A31\u0A34\u0A37\u0A3A\u0A3B\u0A3D\u0A43-\u0A46\u0A49\u0A4A\u0A4E-\u0A50\u0A52-\u0A58\u0A5D\u0A5F-\u0A65\u0A76-\u0A80\u0A84\u0A8E\u0A92\u0AA9\u0AB1\u0AB4\u0ABA\u0ABB\u0AC6\u0ACA\u0ACE\u0ACF\u0AD1-\u0ADF\u0AE4\u0AE5\u0AF2-\u0B00\u0B04\u0B0D\u0B0E\u0B11\u0B12\u0B29\u0B31\u0B34\u0B3A\u0B3B\u0B45\u0B46\u0B49\u0B4A\u0B4E-\u0B55\u0B58-\u0B5B\u0B5E\u0B64\u0B65\u0B78-\u0B81\u0B84\u0B8B-\u0B8D\u0B91\u0B96-\u0B98\u0B9B\u0B9D\u0BA0-\u0BA2\u0BA5-\u0BA7\u0BAB-\u0BAD\u0BBA-\u0BBD\u0BC3-\u0BC5\u0BC9\u0BCE\u0BCF\u0BD1-\u0BD6\u0BD8-\u0BE5\u0BFB-\u0C00\u0C04\u0C0D\u0C11\u0C29\u0C34\u0C3A-\u0C3C\u0C45\u0C49\u0C4E-\u0C54\u0C57\u0C5A-\u0C5F\u0C64\u0C65\u0C70-\u0C77\u0C80\u0C81\u0C84\u0C8D\u0C91\u0CA9\u0CB4\u0CBA\u0CBB\u0CC5\u0CC9\u0CCE-\u0CD4\u0CD7-\u0CDD\u0CDF\u0CE4\u0CE5\u0CF0\u0CF3-\u0D01\u0D04\u0D0D\u0D11\u0D3B\u0D3C\u0D45\u0D49\u0D4F-\u0D56\u0D58-\u0D5F\u0D64\u0D65\u0D76-\u0D78\u0D80\u0D81\u0D84\u0D97-\u0D99\u0DB2\u0DBC\u0DBE\u0DBF\u0DC7-\u0DC9\u0DCB-\u0DCE\u0DD5\u0DD7\u0DE0-\u0DF1\u0DF5-\u0E00\u0E3B-\u0E3E\u0E5C-\u0E80\u0E83\u0E85\u0E86\u0E89\u0E8B\u0E8C\u0E8E-\u0E93\u0E98\u0EA0\u0EA4\u0EA6\u0EA8\u0EA9\u0EAC\u0EBA\u0EBE\u0EBF\u0EC5\u0EC7\u0ECE\u0ECF\u0EDA\u0EDB\u0EE0-\u0EFF\u0F48\u0F6D-\u0F70\u0F98\u0FBD\u0FCD\u0FDB-\u0FFF\u10C6\u10C8-\u10CC\u10CE\u10CF\u1249\u124E\u124F\u1257\u1259\u125E\u125F\u1289\u128E\u128F\u12B1\u12B6\u12B7\u12BF\u12C1\u12C6\u12C7\u12D7\u1311\u1316\u1317\u135B\u135C\u137D-\u137F\u139A-\u139F\u13F5-\u13FF\u169D-\u169F\u16F1-\u16FF\u170D\u1715-\u171F\u1737-\u173F\u1754-\u175F\u176D\u1771\u1774-\u177F\u17DE\u17DF\u17EA-\u17EF\u17FA-\u17FF\u180F\u181A-\u181F\u1878-\u187F\u18AB-\u18AF\u18F6-\u18FF\u191D-\u191F\u192C-\u192F\u193C-\u193F\u1941-\u1943\u196E\u196F\u1975-\u197F\u19AC-\u19AF\u19CA-\u19CF\u19DB-\u19DD\u1A1C\u1A1D\u1A5F\u1A7D\u1A7E\u1A8A-\u1A8F\u1A9A-\u1A9F\u1AAE-\u1AFF\u1B4C-\u1B4F\u1B7D-\u1B7F\u1BF4-\u1BFB\u1C38-\u1C3A\u1C4A-\u1C4C\u1C80-\u1CBF\u1CC8-\u1CCF\u1CF7-\u1CFF\u1DE7-\u1DFB\u1F16\u1F17\u1F1E\u1F1F\u1F46\u1F47\u1F4E\u1F4F\u1F58\u1F5A\u1F5C\u1F5E\u1F7E\u1F7F\u1FB5\u1FC5\u1FD4\u1FD5\u1FDC\u1FF0\u1FF1\u1FF5\u1FFF\u200B-\u200F\u202A-\u202E\u2060-\u206F\u2072\u2073\u208F\u209D-\u209F\u20BB-\u20CF\u20F1-\u20FF\u218A-\u218F\u23F4-\u23FF\u2427-\u243F\u244B-\u245F\u2700\u2B4D-\u2B4F\u2B5A-\u2BFF\u2C2F\u2C5F\u2CF4-\u2CF8\u2D26\u2D28-\u2D2C\u2D2E\u2D2F\u2D68-\u2D6E\u2D71-\u2D7E\u2D97-\u2D9F\u2DA7\u2DAF\u2DB7\u2DBF\u2DC7\u2DCF\u2DD7\u2DDF\u2E3C-\u2E7F\u2E9A\u2EF4-\u2EFF\u2FD6-\u2FEF\u2FFC-\u2FFF\u3040\u3097\u3098\u3100-\u3104\u312E-\u3130\u318F\u31BB-\u31BF\u31E4-\u31EF\u321F\u32FF\u4DB6-\u4DBF\u9FCD-\u9FFF\uA48D-\uA48F\uA4C7-\uA4CF\uA62C-\uA63F\uA698-\uA69E\uA6F8-\uA6FF\uA78F\uA794-\uA79F\uA7AB-\uA7F7\uA82C-\uA82F\uA83A-\uA83F\uA878-\uA87F\uA8C5-\uA8CD\uA8DA-\uA8DF\uA8FC-\uA8FF\uA954-\uA95E\uA97D-\uA97F\uA9CE\uA9DA-\uA9DD\uA9E0-\uA9FF\uAA37-\uAA3F\uAA4E\uAA4F\uAA5A\uAA5B\uAA7C-\uAA7F\uAAC3-\uAADA\uAAF7-\uAB00\uAB07\uAB08\uAB0F\uAB10\uAB17-\uAB1F\uAB27\uAB2F-\uABBF\uABEE\uABEF\uABFA-\uABFF\uD7A4-\uD7AF\uD7C7-\uD7CA\uD7FC-\uF8FF\uFA6E\uFA6F\uFADA-\uFAFF\uFB07-\uFB12\uFB18-\uFB1C\uFB37\uFB3D\uFB3F\uFB42\uFB45\uFBC2-\uFBD2\uFD40-\uFD4F\uFD90\uFD91\uFDC8-\uFDEF\uFDFE\uFDFF\uFE1A-\uFE1F\uFE27-\uFE2F\uFE53\uFE67\uFE6C-\uFE6F\uFE75\uFEFD-\uFF00\uFFBF-\uFFC1\uFFC8\uFFC9\uFFD0\uFFD1\uFFD8\uFFD9\uFFDD-\uFFDF\uFFE7\uFFEF-\uFFFB\uFFFE\uFFFF]/g; + var ws_re = /[\x09-\x10\x0D\u2028\u2029]/g; + + str = str.replace(re, "."); + if (!preserve_ws) str = str.replace(ws_re, "."); + return str; + }, + + + /** + * Parse a string entered by a user and replace escaped chars with the bytes they represent. + * + * @param {string} str + * @returns {string} + * + * @example + * // returns "\x00" + * Utils.parse_escaped_chars("\\x00"); + * + * // returns "\n" + * Utils.parse_escaped_chars("\\n"); + */ + parse_escaped_chars: function(str) { + return str.replace(/(\\)?\\([nrtbf]|x[\da-f]{2})/g, function(m, a, b) { + if (a == "\\") return "\\"+b; + switch (b[0]) { + case "n": + return "\n"; + case "r": + return "\r"; + case "t": + return "\t"; + case "b": + return "\b"; + case "f": + return "\f"; + case "x": + return Utils.chr(parseInt(b.substr(1), 16)); + } + }); + }, + + + /** + * Expand an alphabet range string into a list of the characters in that range. + * + * @param {string} alph_str + * @returns {char[]} + * + * @example + * // returns ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"] + * Utils.expand_alph_range("0-9"); + * + * // returns ["a", "b", "c", "d", "0", "1", "2", "3", "+", "/"] + * Utils.expand_alph_range("a-d0-3+/"); + * + * // returns ["a", "b", "c", "d", "0", "-", "3"] + * Utils.expand_alph_range("a-d0\\-3") + */ + expand_alph_range: function(alph_str) { + var alph_arr = []; + + for (var i = 0; i < alph_str.length; i++) { + if (i < alph_str.length - 2 && + alph_str[i+1] == "-" && + alph_str[i] != "\\") { + var start = Utils.ord(alph_str[i]), + end = Utils.ord(alph_str[i+2]); + + for (var j = start; j <= end; j++) { + alph_arr.push(Utils.chr(j)); + } + i += 2; + } else if (i < alph_str.length - 2 && + alph_str[i] == "\\" && + alph_str[i+1] == "-") { + alph_arr.push("-"); + i++; + } else { + alph_arr.push(alph_str[i]); + } + } + return alph_arr; + }, + + + /** + * Translates a hex string into an array of bytes. + * + * @param {string} hex_str + * @returns {byte_array} + * + * @example + * // returns [0xfe, 0x09, 0xa7] + * Utils.hex_to_byte_array("fe09a7"); + */ + hex_to_byte_array: function(hex_str) { + // TODO: Handle errors i.e. input string is not hex + if (!hex_str) return []; + hex_str = hex_str.replace(/\s+/g, ''); + var byte_array = []; + for (var i = 0; i < hex_str.length; i += 2) { + byte_array.push(parseInt(hex_str.substr(i, 2), 16)); + } + return byte_array; + }, + + + /** + * Translates an array of bytes to a hex string. + * + * @param {byte_array} byte_array + * @returns {string} + * + * @example + * // returns "fe09a7" + * Utils.byte_array_to_hex([0xfe, 0x09, 0xa7]); + */ + byte_array_to_hex: function(byte_array) { + if (!byte_array) return ""; + var hex_str = ""; + for (var i = 0; i < byte_array.length; i++) { + hex_str += Utils.hex(byte_array[i]) + " "; + } + return hex_str.slice(0, hex_str.length-1); + }, + + + /** + * Converts a string to a byte array. + * Treats the string as UTF-8 if any values are over 255. + * + * @param {string} str + * @returns {byte_array} + * + * @example + * // returns [72,101,108,108,111] + * Utils.str_to_byte_array("Hello"); + * + * // returns [228,189,160,229,165,189] + * Utils.str_to_byte_array("你好"); + */ + str_to_byte_array: function(str) { + var byte_array = new Array(str.length); + var i = str.length, b; + while (i--) { + b = str.charCodeAt(i); + byte_array[i] = b; + // If any of the bytes are over 255, read as UTF-8 + if (b > 255) return Utils.str_to_utf8_byte_array(str); + } + return byte_array; + }, + + + /** + * Converts a string to a UTF-8 byte array. + * + * @param {string} str + * @returns {byte_array} + * + * @example + * // returns [72,101,108,108,111] + * Utils.str_to_utf8_byte_array("Hello"); + * + * // returns [228,189,160,229,165,189] + * Utils.str_to_utf8_byte_array("你好"); + */ + str_to_utf8_byte_array: function(str) { + var word_array = CryptoJS.enc.Utf8.parse(str), + byte_array = Utils.word_array_to_byte_array(word_array); + + if (str.length != word_array.sigBytes) + window.app.options.attempt_highlight = false; + return byte_array; + }, + + + /** + * Converts a string to a charcode array + * + * @param {string} str + * @returns {byte_array} + * + * @example + * // returns [72,101,108,108,111] + * Utils.str_to_charcode("Hello"); + * + * // returns [20320,22909] + * Utils.str_to_charcode("你好"); + */ + str_to_charcode: function(str) { + var byte_array = new Array(str.length); + var i = str.length; + while (i--) { + byte_array[i] = str.charCodeAt(i); + } + return byte_array; + }, + + + /** + * Attempts to convert a byte array to a UTF-8 string. + * + * @param {byte_array} byte_array + * @returns {string} + * + * @example + * // returns "Hello" + * Utils.byte_array_to_utf8([72,101,108,108,111]); + * + * // returns "你好" + * Utils.byte_array_to_utf8([228,189,160,229,165,189]); + */ + byte_array_to_utf8: function(byte_array) { + try { + // Try to output data as UTF-8 string + var words = []; + for (var i = 0; i < byte_array.length; i++) { + words[i >>> 2] |= byte_array[i] << (24 - (i % 4) * 8); + } + var word_array = new CryptoJS.lib.WordArray.init(words, byte_array.length), + str = CryptoJS.enc.Utf8.stringify(word_array); + + if (str.length != word_array.sigBytes) + window.app.options.attempt_highlight = false; + return str; + } catch (err) { + // If it fails, treat it as ANSI + return Utils.byte_array_to_chars(byte_array); + } + }, + + + /** + * Converts a charcode array to a string. + * + * @param {byte_array} byte_array + * @returns {string} + * + * @example + * // returns "Hello" + * Utils.byte_array_to_chars([72,101,108,108,111]); + * + * // returns "你好" + * Utils.byte_array_to_chars([20320,22909]); + */ + byte_array_to_chars: function(byte_array) { + if (!byte_array) return ""; + var str = ""; + for (var i = 0; i < byte_array.length;) { + str += String.fromCharCode(byte_array[i++]); + } + return str; + }, + + + /** + * Converts a CryptoJS.lib.WordArray to a byte_array. + * + * @param {CryptoJS.lib.WordArray} word_array + * @returns {byte_array} + * + * @example + * // returns [84, 101, 115, 116] + * Utils.word_array_to_byte_array(CryptoJS.enc.Hex.parse("54657374")); + */ + word_array_to_byte_array: function(word_array) { + if (word_array.sigBytes <= 0) return []; + + var words = word_array.words, + byte_array = []; + + for (var i = 0; i < word_array.sigBytes; i++) { + byte_array.push((words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff); + } + + return byte_array; + }, + + + /** + * Mapping of Unicode code points to Windows-1251 + * @private + * @constant + */ + UNIC_WIN1251_MAP: { + 0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, 10: 10, 11: 11, 12: 12, 13: 13, + 14: 14, 15: 15, 16: 16, 17: 17, 18: 18, 19: 19, 20: 20, 21: 21, 22: 22, 23: 23, 24: 24, + 25: 25, 26: 26, 27: 27, 28: 28, 29: 29, 30: 30, 31: 31, 32: 32, 33: 33, 34: 34, 35: 35, + 36: 36, 37: 37, 38: 38, 39: 39, 40: 40, 41: 41, 42: 42, 43: 43, 44: 44, 45: 45, 46: 46, + 47: 47, 48: 48, 49: 49, 50: 50, 51: 51, 52: 52, 53: 53, 54: 54, 55: 55, 56: 56, 57: 57, + 58: 58, 59: 59, 60: 60, 61: 61, 62: 62, 63: 63, 64: 64, 65: 65, 66: 66, 67: 67, 68: 68, + 69: 69, 70: 70, 71: 71, 72: 72, 73: 73, 74: 74, 75: 75, 76: 76, 77: 77, 78: 78, 79: 79, + 80: 80, 81: 81, 82: 82, 83: 83, 84: 84, 85: 85, 86: 86, 87: 87, 88: 88, 89: 89, 90: 90, + 91: 91, 92: 92, 93: 93, 94: 94, 95: 95, 96: 96, 97: 97, 98: 98, 99: 99, 100: 100, 101: 101, + 102: 102, 103: 103, 104: 104, 105: 105, 106: 106, 107: 107, 108: 108, 109: 109, 110: 110, + 111: 111, 112: 112, 113: 113, 114: 114, 115: 115, 116: 116, 117: 117, 118: 118, 119: 119, + 120: 120, 121: 121, 122: 122, 123: 123, 124: 124, 125: 125, 126: 126, 127: 127, 1027: 129, + 8225: 135, 1046: 198, 8222: 132, 1047: 199, 1168: 165, 1048: 200, 1113: 154, 1049: 201, + 1045: 197, 1050: 202, 1028: 170, 160: 160, 1040: 192, 1051: 203, 164: 164, 166: 166, + 167: 167, 169: 169, 171: 171, 172: 172, 173: 173, 174: 174, 1053: 205, 176: 176, 177: 177, + 1114: 156, 181: 181, 182: 182, 183: 183, 8221: 148, 187: 187, 1029: 189, 1056: 208, + 1057: 209, 1058: 210, 8364: 136, 1112: 188, 1115: 158, 1059: 211, 1060: 212, 1030: 178, + 1061: 213, 1062: 214, 1063: 215, 1116: 157, 1064: 216, 1065: 217, 1031: 175, 1066: 218, + 1067: 219, 1068: 220, 1069: 221, 1070: 222, 1032: 163, 8226: 149, 1071: 223, 1072: 224, + 8482: 153, 1073: 225, 8240: 137, 1118: 162, 1074: 226, 1110: 179, 8230: 133, 1075: 227, + 1033: 138, 1076: 228, 1077: 229, 8211: 150, 1078: 230, 1119: 159, 1079: 231, 1042: 194, + 1080: 232, 1034: 140, 1025: 168, 1081: 233, 1082: 234, 8212: 151, 1083: 235, 1169: 180, + 1084: 236, 1052: 204, 1085: 237, 1035: 142, 1086: 238, 1087: 239, 1088: 240, 1089: 241, + 1090: 242, 1036: 141, 1041: 193, 1091: 243, 1092: 244, 8224: 134, 1093: 245, 8470: 185, + 1094: 246, 1054: 206, 1095: 247, 1096: 248, 8249: 139, 1097: 249, 1098: 250, 1044: 196, + 1099: 251, 1111: 191, 1055: 207, 1100: 252, 1038: 161, 8220: 147, 1101: 253, 8250: 155, + 1102: 254, 8216: 145, 1103: 255, 1043: 195, 1105: 184, 1039: 143, 1026: 128, 1106: 144, + 8218: 130, 1107: 131, 8217: 146, 1108: 186, 1109: 190 + }, + + /** + * Mapping of Windows-1251 code points to Unicode + * @private + * @constant + */ + WIN1251_UNIC_MAP: { + 0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, 10: 10, 11: 11, 12: 12, 13: 13, + 14: 14, 15: 15, 16: 16, 17: 17, 18: 18, 19: 19, 20: 20, 21: 21, 22: 22, 23: 23, 24: 24, + 25: 25, 26: 26, 27: 27, 28: 28, 29: 29, 30: 30, 31: 31, 32: 32, 33: 33, 34: 34, 35: 35, + 36: 36, 37: 37, 38: 38, 39: 39, 40: 40, 41: 41, 42: 42, 43: 43, 44: 44, 45: 45, 46: 46, + 47: 47, 48: 48, 49: 49, 50: 50, 51: 51, 52: 52, 53: 53, 54: 54, 55: 55, 56: 56, 57: 57, + 58: 58, 59: 59, 60: 60, 61: 61, 62: 62, 63: 63, 64: 64, 65: 65, 66: 66, 67: 67, 68: 68, + 69: 69, 70: 70, 71: 71, 72: 72, 73: 73, 74: 74, 75: 75, 76: 76, 77: 77, 78: 78, 79: 79, + 80: 80, 81: 81, 82: 82, 83: 83, 84: 84, 85: 85, 86: 86, 87: 87, 88: 88, 89: 89, 90: 90, + 91: 91, 92: 92, 93: 93, 94: 94, 95: 95, 96: 96, 97: 97, 98: 98, 99: 99, 100: 100, 101: 101, + 102: 102, 103: 103, 104: 104, 105: 105, 106: 106, 107: 107, 108: 108, 109: 109, 110: 110, + 111: 111, 112: 112, 113: 113, 114: 114, 115: 115, 116: 116, 117: 117, 118: 118, 119: 119, + 120: 120, 121: 121, 122: 122, 123: 123, 124: 124, 125: 125, 126: 126, 127: 127, 160: 160, + 164: 164, 166: 166, 167: 167, 169: 169, 171: 171, 172: 172, 173: 173, 174: 174, 176: 176, + 177: 177, 181: 181, 182: 182, 183: 183, 187: 187, 168: 1025, 128: 1026, 129: 1027, + 170: 1028, 189: 1029, 178: 1030, 175: 1031, 163: 1032, 138: 1033, 140: 1034, 142: 1035, + 141: 1036, 161: 1038, 143: 1039, 192: 1040, 193: 1041, 194: 1042, 195: 1043, 196: 1044, + 197: 1045, 198: 1046, 199: 1047, 200: 1048, 201: 1049, 202: 1050, 203: 1051, 204: 1052, + 205: 1053, 206: 1054, 207: 1055, 208: 1056, 209: 1057, 210: 1058, 211: 1059, 212: 1060, + 213: 1061, 214: 1062, 215: 1063, 216: 1064, 217: 1065, 218: 1066, 219: 1067, 220: 1068, + 221: 1069, 222: 1070, 223: 1071, 224: 1072, 225: 1073, 226: 1074, 227: 1075, 228: 1076, + 229: 1077, 230: 1078, 231: 1079, 232: 1080, 233: 1081, 234: 1082, 235: 1083, 236: 1084, + 237: 1085, 238: 1086, 239: 1087, 240: 1088, 241: 1089, 242: 1090, 243: 1091, 244: 1092, + 245: 1093, 246: 1094, 247: 1095, 248: 1096, 249: 1097, 250: 1098, 251: 1099, 252: 1100, + 253: 1101, 254: 1102, 255: 1103, 184: 1105, 144: 1106, 131: 1107, 186: 1108, 190: 1109, + 179: 1110, 191: 1111, 188: 1112, 154: 1113, 156: 1114, 158: 1115, 157: 1116, 162: 1118, + 159: 1119, 165: 1168, 180: 1169, 150: 8211, 151: 8212, 145: 8216, 146: 8217, 130: 8218, + 147: 8220, 148: 8221, 132: 8222, 134: 8224, 135: 8225, 149: 8226, 133: 8230, 137: 8240, + 139: 8249, 155: 8250, 136: 8364, 185: 8470, 153: 8482 + }, + + + /** + * Converts a Unicode string to Windows-1251 encoding + * + * @param {string} unic_str + * @returns {string} String encoded in Windows-1251 + * + * @example + * // returns "îáíîâëåííàÿ òåõíè÷êà ïî Áîèíãó. îðèãèíàë ó ìåíÿ. çàáåðåòå êîãäà áóäåòå â ÊÈ" + * Utils.unicode_to_win1251("обновленная техничка по Боингу. оригинал у меня. заберете когда будете в КИ"); + */ + unicode_to_win1251: function(unic_str) { + var res = []; + + for (var i = 0; i < unic_str.length; i++) { + var ord = unic_str.charCodeAt(i); + if (!(ord in Utils.UNIC_WIN1251_MAP)) + throw "Character '" + unic_str.charAt(i) + "' isn't supported by Windows-1251"; + res.push(String.fromCharCode(Utils.UNIC_WIN1251_MAP[ord])); + } + + return res.join(''); + }, + + + /** + * Converts a Windows-1251 string to Unicode encoding + * + * @param {string} win1251_str + * @returns {string} String encoded in Unicode + * + * @example + * // returns "обновленная техничка по Боингу. оригинал у меня. заберете когда будете в КИ" + * Utils.unicode_to_win1251("îáíîâëåííàÿ òåõíè÷êà ïî Áîèíãó. îðèãèíàë ó ìåíÿ. çàáåðåòå êîãäà áóäåòå â ÊÈ"); + */ + win1251_to_unicode: function(win1251_str) { + var res = []; + + for (var i = 0; i < win1251_str.length; i++) { + var ord = win1251_str.charCodeAt(i); + if (!(ord in Utils.WIN1251_UNIC_MAP)) + throw "Character '" + win1251_str.charAt(i) + "' isn't supported by Windows-1251"; + res.push(String.fromCharCode(Utils.WIN1251_UNIC_MAP[ord])); + } + + return res.join(''); + }, + + + /** + * Base64's the input byte array using the given alphabet, returning a string. + * + * @param {byte_array|string} data + * @param {string} [alphabet] + * @returns {string} + * + * @example + * // returns "SGVsbG8=" + * Utils.to_base64([72, 101, 108, 108, 111]); + * + * // returns "SGVsbG8=" + * Utils.to_base64("Hello"); + */ + to_base64: function(data, alphabet) { + if (!data) return ""; + if (typeof data == "string") { + data = Utils.str_to_byte_array(data); + } + + alphabet = alphabet ? + Utils.expand_alph_range(alphabet).join("") : + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; + var output = "", + chr1, chr2, chr3, + enc1, enc2, enc3, enc4, + i = 0; + + while (i < data.length) { + chr1 = data[i++]; + chr2 = data[i++]; + chr3 = data[i++]; + + enc1 = chr1 >> 2; + enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); + enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); + enc4 = chr3 & 63; + + if (isNaN(chr2)) { + enc3 = enc4 = 64; + } else if (isNaN(chr3)) { + enc4 = 64; + } + + output += alphabet.charAt(enc1) + alphabet.charAt(enc2) + + alphabet.charAt(enc3) + alphabet.charAt(enc4); + } + + return output; + }, + + + /** + * UnBase64's the input string using the given alphabet, returning a byte array. + * + * @param {byte_array} data + * @param {string} [alphabet] + * @param {string} [return_type="string"] - Either "string" or "byte_array" + * @param {boolean} [remove_non_alph_chars=true] + * @returns {byte_array} + * + * @example + * // returns "Hello" + * Utils.from_base64("SGVsbG8="); + * + * // returns [72, 101, 108, 108, 111] + * Utils.from_base64("SGVsbG8=", null, "byte_array"); + */ + from_base64: function(data, alphabet, return_type, remove_non_alph_chars) { + return_type = return_type || "string"; + + if (!data) { + return return_type == "string" ? "" : []; + } + + alphabet = alphabet ? + Utils.expand_alph_range(alphabet).join("") : + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; + if (remove_non_alph_chars === undefined) + remove_non_alph_chars = true; + + var output = [], + chr1, chr2, chr3, + enc1, enc2, enc3, enc4, + i = 0; + + if (remove_non_alph_chars) { + var re = new RegExp("[^" + alphabet.replace(/[\[\]\\\-^$]/g, "\\$&") + "]", "g"); + data = data.replace(re, ""); + } + + while (i < data.length) { + enc1 = alphabet.indexOf(data.charAt(i++)); + enc2 = alphabet.indexOf(data.charAt(i++) || "="); + enc3 = alphabet.indexOf(data.charAt(i++) || "="); + enc4 = alphabet.indexOf(data.charAt(i++) || "="); + + enc2 = enc2 == -1 ? 64 : enc2; + enc3 = enc3 == -1 ? 64 : enc3; + enc4 = enc4 == -1 ? 64 : enc4; + + chr1 = (enc1 << 2) | (enc2 >> 4); + chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); + chr3 = ((enc3 & 3) << 6) | enc4; + + output.push(chr1); + + if (enc3 != 64) { + output.push(chr2); + } + if (enc4 != 64) { + output.push(chr3); + } + } + + return return_type == "string" ? Utils.byte_array_to_utf8(output) : output; + }, + + + /** + * Convert a byte array into a hex string. + * + * @param {byte_array} data + * @param {string} [delim=" "] + * @param {number} [padding=2] + * @returns {string} + * + * @example + * // returns "0a 14 1e" + * Utils.to_hex([10,20,30]); + * + * // returns "0a:14:1e" + * Utils.to_hex([10,20,30], ":"); + */ + to_hex: function(data, delim, padding) { + if (!data) return ""; + + delim = typeof delim == "string" ? delim : " "; + padding = padding || 2; + var output = ""; + + for (var i = 0; i < data.length; i++) { + output += Utils.pad(data[i].toString(16), padding) + delim; + } + + // Add \x or 0x to beginning + if (delim == "0x") output = "0x" + output; + if (delim == "\\x") output = "\\x" + output; + + if (delim.length) + return output.slice(0, -delim.length); + else + return output; + }, + + + /** + * Convert a byte array into a hex string as efficiently as possible with no options. + * + * @param {byte_array} data + * @returns {string} + * + * @example + * // returns "0a141e" + * Utils.to_hex([10,20,30]); + */ + to_hex_fast: function(data) { + if (!data) return ""; + + var output = []; + + for (var i = 0; i < data.length; i++) { + output.push((data[i] >>> 4).toString(16)); + output.push((data[i] & 0x0f).toString(16)); + } + + return output.join(""); + }, + + + /** + * Convert a hex string into a byte array. + * + * @param {string} data + * @param {string} [delim] + * @param {number} [byte_len=2] + * @returns {byte_array} + * + * @example + * // returns [10,20,30] + * Utils.from_hex("0a 14 1e"); + * + * // returns [10,20,30] + * Utils.from_hex("0a:14:1e", "Colon"); + */ + from_hex: function(data, delim, byte_len) { + delim = delim || (data.indexOf(" ") >= 0 ? "Space" : "None"); + byte_len = byte_len || 2; + if (delim != "None") { + var delim_regex = Utils.regex_rep[delim]; + data = data.replace(delim_regex, ''); + } + + var output = []; + for (var i = 0; i < data.length; i += byte_len) { + output.push(parseInt(data.substr(i, byte_len), 16)); + } + return output; + }, + + + /** + * Parses CSV data and returns it as a two dimensional array or strings. + * + * @param {string} data + * @returns {string[][]} + * + * @example + * // returns [["head1", "head2"], ["data1", "data2"]] + * Utils.parse_csv("head1,head2\ndata1,data2"); + */ + parse_csv: function(data) { + + var b, + ignore_next = false, + in_string = false, + cell = "", + line = [], + lines = []; + + for (var i = 0; i < data.length; i++) { + b = data[i]; + if (ignore_next) { + cell += b; + ignore_next = false; + } else if (b == "\\") { + cell += b; + ignore_next = true; + } else if (b == "\"" && !in_string) { + in_string = true; + } else if (b == "\"" && in_string) { + in_string = false; + } else if (b == "," && !in_string) { + line.push(cell); + cell = ""; + } else if ((b == "\n" || b == "\r") && !in_string) { + line.push(cell); + cell = ""; + lines.push(line); + line = []; + } else { + cell += b; + } + } + + if (line.length) { + line.push(cell); + lines.push(line); + } + + return lines; + }, + + + /** + * Removes all HTML (or XML) tags from the input string. + * + * @param {string} html_str + * @param {boolean} remove_script_and_style - Flag to specify whether to remove entire script or style blocks + * @returns {string} + * + * @example + * // returns "Test" + * Utils.strip_html_tags("
              Test
              "); + */ + strip_html_tags: function(html_str, remove_script_and_style) { + if (remove_script_and_style) { + html_str = html_str.replace(/<(script|style)[^>]*>.*<\/(script|style)>/gmi, ""); + } + return html_str.replace(/<[^>\n]+>/g, ""); + }, + + + /** + * Escapes HTML tags in a string to stop them being rendered + * + * @param {string} str + * @returns string + * + * @example + * // return "A <script> tag" + * Utils.escape_html("A } + *
            • define style rules. See the example page for examples. + *
            • mark the {@code
              } and {@code } tags in your source with
              + *    {@code class=prettyprint.}
              + *    You can also use the (html deprecated) {@code } tag, but the pretty
              + *    printer needs to do more substantial DOM manipulations to support that, so
              + *    some css styles may not be preserved.
              + * </ol>
              + * That's it.  I wanted to keep the API as simple as possible, so there's no
              + * need to specify which language the code is in, but if you wish, you can add
              + * another class to the {@code <pre>} or {@code <code>} element to specify the
              + * language, as in {@code <pre class="prettyprint lang-java">}.  Any class that
              + * starts with "lang-" followed by a file extension, specifies the file type.
              + * See the "lang-*.js" files in this directory for code that implements
              + * per-language file handlers.
              + * <p>
              + * Change log:<br>
              + * cbeust, 2006/08/22
              + * <blockquote>
              + *   Java annotations (start with "@") are now captured as literals ("lit")
              + * </blockquote>
              + * @requires console
              + */
              +
              +// JSLint declarations
              +/*global console, document, navigator, setTimeout, window, define */
              +
              +/** @define {boolean} */
              +var IN_GLOBAL_SCOPE = true;
              +
              +/**
              + * Split {@code prettyPrint} into multiple timeouts so as not to interfere with
              + * UI events.
              + * If set to {@code false}, {@code prettyPrint()} is synchronous.
              + */
              +window['PR_SHOULD_USE_CONTINUATION'] = true;
              +
              +/**
              + * Pretty print a chunk of code.
              + * @param {string} sourceCodeHtml The HTML to pretty print.
              + * @param {string} opt_langExtension The language name to use.
              + *     Typically, a filename extension like 'cpp' or 'java'.
              + * @param {number|boolean} opt_numberLines True to number lines,
              + *     or the 1-indexed number of the first line in sourceCodeHtml.
              + * @return {string} code as html, but prettier
              + */
              +var prettyPrintOne;
              +/**
              + * Find all the {@code <pre>} and {@code <code>} tags in the DOM with
              + * {@code class=prettyprint} and prettify them.
              + *
              + * @param {Function} opt_whenDone called when prettifying is done.
              + * @param {HTMLElement|HTMLDocument} opt_root an element or document
              + *   containing all the elements to pretty print.
              + *   Defaults to {@code document.body}.
              + */
              +var prettyPrint;
              +
              +
              +(function () {
              +  var win = window;
              +  // Keyword lists for various languages.
              +  // We use things that coerce to strings to make them compact when minified
              +  // and to defeat aggressive optimizers that fold large string constants.
              +  var FLOW_CONTROL_KEYWORDS = ["break,continue,do,else,for,if,return,while"];
              +  var C_KEYWORDS = [FLOW_CONTROL_KEYWORDS,"auto,case,char,const,default," + 
              +      "double,enum,extern,float,goto,inline,int,long,register,short,signed," +
              +      "sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"];
              +  var COMMON_KEYWORDS = [C_KEYWORDS,"catch,class,delete,false,import," +
              +      "new,operator,private,protected,public,this,throw,true,try,typeof"];
              +  var CPP_KEYWORDS = [COMMON_KEYWORDS,"alignof,align_union,asm,axiom,bool," +
              +      "concept,concept_map,const_cast,constexpr,decltype,delegate," +
              +      "dynamic_cast,explicit,export,friend,generic,late_check," +
              +      "mutable,namespace,nullptr,property,reinterpret_cast,static_assert," +
              +      "static_cast,template,typeid,typename,using,virtual,where"];
              +  var JAVA_KEYWORDS = [COMMON_KEYWORDS,
              +      "abstract,assert,boolean,byte,extends,final,finally,implements,import," +
              +      "instanceof,interface,null,native,package,strictfp,super,synchronized," +
              +      "throws,transient"];
              +  var CSHARP_KEYWORDS = [JAVA_KEYWORDS,
              +      "as,base,by,checked,decimal,delegate,descending,dynamic,event," +
              +      "fixed,foreach,from,group,implicit,in,internal,into,is,let," +
              +      "lock,object,out,override,orderby,params,partial,readonly,ref,sbyte," +
              +      "sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort," +
              +      "var,virtual,where"];
              +  var COFFEE_KEYWORDS = "all,and,by,catch,class,else,extends,false,finally," +
              +      "for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then," +
              +      "throw,true,try,unless,until,when,while,yes";
              +  var JSCRIPT_KEYWORDS = [COMMON_KEYWORDS,
              +      "debugger,eval,export,function,get,null,set,undefined,var,with," +
              +      "Infinity,NaN"];
              +  var PERL_KEYWORDS = "caller,delete,die,do,dump,elsif,eval,exit,foreach,for," +
              +      "goto,if,import,last,local,my,next,no,our,print,package,redo,require," +
              +      "sub,undef,unless,until,use,wantarray,while,BEGIN,END";
              +  var PYTHON_KEYWORDS = [FLOW_CONTROL_KEYWORDS, "and,as,assert,class,def,del," +
              +      "elif,except,exec,finally,from,global,import,in,is,lambda," +
              +      "nonlocal,not,or,pass,print,raise,try,with,yield," +
              +      "False,True,None"];
              +  var RUBY_KEYWORDS = [FLOW_CONTROL_KEYWORDS, "alias,and,begin,case,class," +
              +      "def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo," +
              +      "rescue,retry,self,super,then,true,undef,unless,until,when,yield," +
              +      "BEGIN,END"];
              +   var RUST_KEYWORDS = [FLOW_CONTROL_KEYWORDS, "as,assert,const,copy,drop," +
              +      "enum,extern,fail,false,fn,impl,let,log,loop,match,mod,move,mut,priv," +
              +      "pub,pure,ref,self,static,struct,true,trait,type,unsafe,use"];
              +  var SH_KEYWORDS = [FLOW_CONTROL_KEYWORDS, "case,done,elif,esac,eval,fi," +
              +      "function,in,local,set,then,until"];
              +  var ALL_KEYWORDS = [
              +      CPP_KEYWORDS, CSHARP_KEYWORDS, JSCRIPT_KEYWORDS, PERL_KEYWORDS,
              +      PYTHON_KEYWORDS, RUBY_KEYWORDS, SH_KEYWORDS];
              +  var C_TYPES = /^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)\b/;
              +
              +  // token style names.  correspond to css classes
              +  /**
              +   * token style for a string literal
              +   * @const
              +   */
              +  var PR_STRING = 'str';
              +  /**
              +   * token style for a keyword
              +   * @const
              +   */
              +  var PR_KEYWORD = 'kwd';
              +  /**
              +   * token style for a comment
              +   * @const
              +   */
              +  var PR_COMMENT = 'com';
              +  /**
              +   * token style for a type
              +   * @const
              +   */
              +  var PR_TYPE = 'typ';
              +  /**
              +   * token style for a literal value.  e.g. 1, null, true.
              +   * @const
              +   */
              +  var PR_LITERAL = 'lit';
              +  /**
              +   * token style for a punctuation string.
              +   * @const
              +   */
              +  var PR_PUNCTUATION = 'pun';
              +  /**
              +   * token style for plain text.
              +   * @const
              +   */
              +  var PR_PLAIN = 'pln';
              +
              +  /**
              +   * token style for an sgml tag.
              +   * @const
              +   */
              +  var PR_TAG = 'tag';
              +  /**
              +   * token style for a markup declaration such as a DOCTYPE.
              +   * @const
              +   */
              +  var PR_DECLARATION = 'dec';
              +  /**
              +   * token style for embedded source.
              +   * @const
              +   */
              +  var PR_SOURCE = 'src';
              +  /**
              +   * token style for an sgml attribute name.
              +   * @const
              +   */
              +  var PR_ATTRIB_NAME = 'atn';
              +  /**
              +   * token style for an sgml attribute value.
              +   * @const
              +   */
              +  var PR_ATTRIB_VALUE = 'atv';
              +
              +  /**
              +   * A class that indicates a section of markup that is not code, e.g. to allow
              +   * embedding of line numbers within code listings.
              +   * @const
              +   */
              +  var PR_NOCODE = 'nocode';
              +
              +  
              +  
              +  /**
              +   * A set of tokens that can precede a regular expression literal in
              +   * javascript
              +   * http://web.archive.org/web/20070717142515/http://www.mozilla.org/js/language/js20/rationale/syntax.html
              +   * has the full list, but I've removed ones that might be problematic when
              +   * seen in languages that don't support regular expression literals.
              +   *
              +   * <p>Specifically, I've removed any keywords that can't precede a regexp
              +   * literal in a syntactically legal javascript program, and I've removed the
              +   * "in" keyword since it's not a keyword in many languages, and might be used
              +   * as a count of inches.
              +   *
              +   * <p>The link above does not accurately describe EcmaScript rules since
              +   * it fails to distinguish between (a=++/b/i) and (a++/b/i) but it works
              +   * very well in practice.
              +   *
              +   * @private
              +   * @const
              +   */
              +  var REGEXP_PRECEDER_PATTERN = '(?:^^\\.?|[+-]|[!=]=?=?|\\#|%=?|&&?=?|\\(|\\*=?|[+\\-]=|->|\\/=?|::?|<<?=?|>>?>?=?|,|;|\\?|@|\\[|~|{|\\^\\^?=?|\\|\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*';
              +  
              +  // CAVEAT: this does not properly handle the case where a regular
              +  // expression immediately follows another since a regular expression may
              +  // have flags for case-sensitivity and the like.  Having regexp tokens
              +  // adjacent is not valid in any language I'm aware of, so I'm punting.
              +  // TODO: maybe style special characters inside a regexp as punctuation.
              +
              +  /**
              +   * Given a group of {@link RegExp}s, returns a {@code RegExp} that globally
              +   * matches the union of the sets of strings matched by the input RegExp.
              +   * Since it matches globally, if the input strings have a start-of-input
              +   * anchor (/^.../), it is ignored for the purposes of unioning.
              +   * @param {Array.<RegExp>} regexs non multiline, non-global regexs.
              +   * @return {RegExp} a global regex.
              +   */
              +  function combinePrefixPatterns(regexs) {
              +    var capturedGroupIndex = 0;
              +  
              +    var needToFoldCase = false;
              +    var ignoreCase = false;
              +    for (var i = 0, n = regexs.length; i < n; ++i) {
              +      var regex = regexs[i];
              +      if (regex.ignoreCase) {
              +        ignoreCase = true;
              +      } else if (/[a-z]/i.test(regex.source.replace(
              +                     /\\u[0-9a-f]{4}|\\x[0-9a-f]{2}|\\[^ux]/gi, ''))) {
              +        needToFoldCase = true;
              +        ignoreCase = false;
              +        break;
              +      }
              +    }
              +  
              +    var escapeCharToCodeUnit = {
              +      'b': 8,
              +      't': 9,
              +      'n': 0xa,
              +      'v': 0xb,
              +      'f': 0xc,
              +      'r': 0xd
              +    };
              +  
              +    function decodeEscape(charsetPart) {
              +      var cc0 = charsetPart.charCodeAt(0);
              +      if (cc0 !== 92 /* \\ */) {
              +        return cc0;
              +      }
              +      var c1 = charsetPart.charAt(1);
              +      cc0 = escapeCharToCodeUnit[c1];
              +      if (cc0) {
              +        return cc0;
              +      } else if ('0' <= c1 && c1 <= '7') {
              +        return parseInt(charsetPart.substring(1), 8);
              +      } else if (c1 === 'u' || c1 === 'x') {
              +        return parseInt(charsetPart.substring(2), 16);
              +      } else {
              +        return charsetPart.charCodeAt(1);
              +      }
              +    }
              +  
              +    function encodeEscape(charCode) {
              +      if (charCode < 0x20) {
              +        return (charCode < 0x10 ? '\\x0' : '\\x') + charCode.toString(16);
              +      }
              +      var ch = String.fromCharCode(charCode);
              +      return (ch === '\\' || ch === '-' || ch === ']' || ch === '^')
              +          ? "\\" + ch : ch;
              +    }
              +  
              +    function caseFoldCharset(charSet) {
              +      var charsetParts = charSet.substring(1, charSet.length - 1).match(
              +          new RegExp(
              +              '\\\\u[0-9A-Fa-f]{4}'
              +              + '|\\\\x[0-9A-Fa-f]{2}'
              +              + '|\\\\[0-3][0-7]{0,2}'
              +              + '|\\\\[0-7]{1,2}'
              +              + '|\\\\[\\s\\S]'
              +              + '|-'
              +              + '|[^-\\\\]',
              +              'g'));
              +      var ranges = [];
              +      var inverse = charsetParts[0] === '^';
              +  
              +      var out = ['['];
              +      if (inverse) { out.push('^'); }
              +  
              +      for (var i = inverse ? 1 : 0, n = charsetParts.length; i < n; ++i) {
              +        var p = charsetParts[i];
              +        if (/\\[bdsw]/i.test(p)) {  // Don't muck with named groups.
              +          out.push(p);
              +        } else {
              +          var start = decodeEscape(p);
              +          var end;
              +          if (i + 2 < n && '-' === charsetParts[i + 1]) {
              +            end = decodeEscape(charsetParts[i + 2]);
              +            i += 2;
              +          } else {
              +            end = start;
              +          }
              +          ranges.push([start, end]);
              +          // If the range might intersect letters, then expand it.
              +          // This case handling is too simplistic.
              +          // It does not deal with non-latin case folding.
              +          // It works for latin source code identifiers though.
              +          if (!(end < 65 || start > 122)) {
              +            if (!(end < 65 || start > 90)) {
              +              ranges.push([Math.max(65, start) | 32, Math.min(end, 90) | 32]);
              +            }
              +            if (!(end < 97 || start > 122)) {
              +              ranges.push([Math.max(97, start) & ~32, Math.min(end, 122) & ~32]);
              +            }
              +          }
              +        }
              +      }
              +  
              +      // [[1, 10], [3, 4], [8, 12], [14, 14], [16, 16], [17, 17]]
              +      // -> [[1, 12], [14, 14], [16, 17]]
              +      ranges.sort(function (a, b) { return (a[0] - b[0]) || (b[1]  - a[1]); });
              +      var consolidatedRanges = [];
              +      var lastRange = [];
              +      for (var i = 0; i < ranges.length; ++i) {
              +        var range = ranges[i];
              +        if (range[0] <= lastRange[1] + 1) {
              +          lastRange[1] = Math.max(lastRange[1], range[1]);
              +        } else {
              +          consolidatedRanges.push(lastRange = range);
              +        }
              +      }
              +  
              +      for (var i = 0; i < consolidatedRanges.length; ++i) {
              +        var range = consolidatedRanges[i];
              +        out.push(encodeEscape(range[0]));
              +        if (range[1] > range[0]) {
              +          if (range[1] + 1 > range[0]) { out.push('-'); }
              +          out.push(encodeEscape(range[1]));
              +        }
              +      }
              +      out.push(']');
              +      return out.join('');
              +    }
              +  
              +    function allowAnywhereFoldCaseAndRenumberGroups(regex) {
              +      // Split into character sets, escape sequences, punctuation strings
              +      // like ('(', '(?:', ')', '^'), and runs of characters that do not
              +      // include any of the above.
              +      var parts = regex.source.match(
              +          new RegExp(
              +              '(?:'
              +              + '\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]'  // a character set
              +              + '|\\\\u[A-Fa-f0-9]{4}'  // a unicode escape
              +              + '|\\\\x[A-Fa-f0-9]{2}'  // a hex escape
              +              + '|\\\\[0-9]+'  // a back-reference or octal escape
              +              + '|\\\\[^ux0-9]'  // other escape sequence
              +              + '|\\(\\?[:!=]'  // start of a non-capturing group
              +              + '|[\\(\\)\\^]'  // start/end of a group, or line start
              +              + '|[^\\x5B\\x5C\\(\\)\\^]+'  // run of other characters
              +              + ')',
              +              'g'));
              +      var n = parts.length;
              +  
              +      // Maps captured group numbers to the number they will occupy in
              +      // the output or to -1 if that has not been determined, or to
              +      // undefined if they need not be capturing in the output.
              +      var capturedGroups = [];
              +  
              +      // Walk over and identify back references to build the capturedGroups
              +      // mapping.
              +      for (var i = 0, groupIndex = 0; i < n; ++i) {
              +        var p = parts[i];
              +        if (p === '(') {
              +          // groups are 1-indexed, so max group index is count of '('
              +          ++groupIndex;
              +        } else if ('\\' === p.charAt(0)) {
              +          var decimalValue = +p.substring(1);
              +          if (decimalValue) {
              +            if (decimalValue <= groupIndex) {
              +              capturedGroups[decimalValue] = -1;
              +            } else {
              +              // Replace with an unambiguous escape sequence so that
              +              // an octal escape sequence does not turn into a backreference
              +              // to a capturing group from an earlier regex.
              +              parts[i] = encodeEscape(decimalValue);
              +            }
              +          }
              +        }
              +      }
              +  
              +      // Renumber groups and reduce capturing groups to non-capturing groups
              +      // where possible.
              +      for (var i = 1; i < capturedGroups.length; ++i) {
              +        if (-1 === capturedGroups[i]) {
              +          capturedGroups[i] = ++capturedGroupIndex;
              +        }
              +      }
              +      for (var i = 0, groupIndex = 0; i < n; ++i) {
              +        var p = parts[i];
              +        if (p === '(') {
              +          ++groupIndex;
              +          if (!capturedGroups[groupIndex]) {
              +            parts[i] = '(?:';
              +          }
              +        } else if ('\\' === p.charAt(0)) {
              +          var decimalValue = +p.substring(1);
              +          if (decimalValue && decimalValue <= groupIndex) {
              +            parts[i] = '\\' + capturedGroups[decimalValue];
              +          }
              +        }
              +      }
              +  
              +      // Remove any prefix anchors so that the output will match anywhere.
              +      // ^^ really does mean an anchored match though.
              +      for (var i = 0; i < n; ++i) {
              +        if ('^' === parts[i] && '^' !== parts[i + 1]) { parts[i] = ''; }
              +      }
              +  
              +      // Expand letters to groups to handle mixing of case-sensitive and
              +      // case-insensitive patterns if necessary.
              +      if (regex.ignoreCase && needToFoldCase) {
              +        for (var i = 0; i < n; ++i) {
              +          var p = parts[i];
              +          var ch0 = p.charAt(0);
              +          if (p.length >= 2 && ch0 === '[') {
              +            parts[i] = caseFoldCharset(p);
              +          } else if (ch0 !== '\\') {
              +            // TODO: handle letters in numeric escapes.
              +            parts[i] = p.replace(
              +                /[a-zA-Z]/g,
              +                function (ch) {
              +                  var cc = ch.charCodeAt(0);
              +                  return '[' + String.fromCharCode(cc & ~32, cc | 32) + ']';
              +                });
              +          }
              +        }
              +      }
              +  
              +      return parts.join('');
              +    }
              +  
              +    var rewritten = [];
              +    for (var i = 0, n = regexs.length; i < n; ++i) {
              +      var regex = regexs[i];
              +      if (regex.global || regex.multiline) { throw new Error('' + regex); }
              +      rewritten.push(
              +          '(?:' + allowAnywhereFoldCaseAndRenumberGroups(regex) + ')');
              +    }
              +  
              +    return new RegExp(rewritten.join('|'), ignoreCase ? 'gi' : 'g');
              +  }
              +
              +  /**
              +   * Split markup into a string of source code and an array mapping ranges in
              +   * that string to the text nodes in which they appear.
              +   *
              +   * <p>
              +   * The HTML DOM structure:</p>
              +   * <pre>
              +   * (Element   "p"
              +   *   (Element "b"
              +   *     (Text  "print "))       ; #1
              +   *   (Text    "'Hello '")      ; #2
              +   *   (Element "br")            ; #3
              +   *   (Text    "  + 'World';")) ; #4
              +   * </pre>
              +   * <p>
              +   * corresponds to the HTML
              +   * {@code <p><b>print </b>'Hello '<br>  + 'World';</p>}.</p>
              +   *
              +   * <p>
              +   * It will produce the output:</p>
              +   * <pre>
              +   * {
              +   *   sourceCode: "print 'Hello '\n  + 'World';",
              +   *   //                     1          2
              +   *   //           012345678901234 5678901234567
              +   *   spans: [0, #1, 6, #2, 14, #3, 15, #4]
              +   * }
              +   * </pre>
              +   * <p>
              +   * where #1 is a reference to the {@code "print "} text node above, and so
              +   * on for the other text nodes.
              +   * </p>
              +   *
              +   * <p>
              +   * The {@code} spans array is an array of pairs.  Even elements are the start
              +   * indices of substrings, and odd elements are the text nodes (or BR elements)
              +   * that contain the text for those substrings.
              +   * Substrings continue until the next index or the end of the source.
              +   * </p>
              +   *
              +   * @param {Node} node an HTML DOM subtree containing source-code.
              +   * @param {boolean} isPreformatted true if white-space in text nodes should
              +   *    be considered significant.
              +   * @return {Object} source code and the text nodes in which they occur.
              +   */
              +  function extractSourceSpans(node, isPreformatted) {
              +    var nocode = /(?:^|\s)nocode(?:\s|$)/;
              +  
              +    var chunks = [];
              +    var length = 0;
              +    var spans = [];
              +    var k = 0;
              +  
              +    function walk(node) {
              +      var type = node.nodeType;
              +      if (type == 1) {  // Element
              +        if (nocode.test(node.className)) { return; }
              +        for (var child = node.firstChild; child; child = child.nextSibling) {
              +          walk(child);
              +        }
              +        var nodeName = node.nodeName.toLowerCase();
              +        if ('br' === nodeName || 'li' === nodeName) {
              +          chunks[k] = '\n';
              +          spans[k << 1] = length++;
              +          spans[(k++ << 1) | 1] = node;
              +        }
              +      } else if (type == 3 || type == 4) {  // Text
              +        var text = node.nodeValue;
              +        if (text.length) {
              +          if (!isPreformatted) {
              +            text = text.replace(/[ \t\r\n]+/g, ' ');
              +          } else {
              +            text = text.replace(/\r\n?/g, '\n');  // Normalize newlines.
              +          }
              +          // TODO: handle tabs here?
              +          chunks[k] = text;
              +          spans[k << 1] = length;
              +          length += text.length;
              +          spans[(k++ << 1) | 1] = node;
              +        }
              +      }
              +    }
              +  
              +    walk(node);
              +  
              +    return {
              +      sourceCode: chunks.join('').replace(/\n$/, ''),
              +      spans: spans
              +    };
              +  }
              +
              +  /**
              +   * Apply the given language handler to sourceCode and add the resulting
              +   * decorations to out.
              +   * @param {number} basePos the index of sourceCode within the chunk of source
              +   *    whose decorations are already present on out.
              +   */
              +  function appendDecorations(basePos, sourceCode, langHandler, out) {
              +    if (!sourceCode) { return; }
              +    var job = {
              +      sourceCode: sourceCode,
              +      basePos: basePos
              +    };
              +    langHandler(job);
              +    out.push.apply(out, job.decorations);
              +  }
              +
              +  var notWs = /\S/;
              +
              +  /**
              +   * Given an element, if it contains only one child element and any text nodes
              +   * it contains contain only space characters, return the sole child element.
              +   * Otherwise returns undefined.
              +   * <p>
              +   * This is meant to return the CODE element in {@code <pre><code ...>} when
              +   * there is a single child element that contains all the non-space textual
              +   * content, but not to return anything where there are multiple child elements
              +   * as in {@code <pre><code>...</code><code>...</code></pre>} or when there
              +   * is textual content.
              +   */
              +  function childContentWrapper(element) {
              +    var wrapper = undefined;
              +    for (var c = element.firstChild; c; c = c.nextSibling) {
              +      var type = c.nodeType;
              +      wrapper = (type === 1)  // Element Node
              +          ? (wrapper ? element : c)
              +          : (type === 3)  // Text Node
              +          ? (notWs.test(c.nodeValue) ? element : wrapper)
              +          : wrapper;
              +    }
              +    return wrapper === element ? undefined : wrapper;
              +  }
              +
              +  /** Given triples of [style, pattern, context] returns a lexing function,
              +    * The lexing function interprets the patterns to find token boundaries and
              +    * returns a decoration list of the form
              +    * [index_0, style_0, index_1, style_1, ..., index_n, style_n]
              +    * where index_n is an index into the sourceCode, and style_n is a style
              +    * constant like PR_PLAIN.  index_n-1 <= index_n, and style_n-1 applies to
              +    * all characters in sourceCode[index_n-1:index_n].
              +    *
              +    * The stylePatterns is a list whose elements have the form
              +    * [style : string, pattern : RegExp, DEPRECATED, shortcut : string].
              +    *
              +    * Style is a style constant like PR_PLAIN, or can be a string of the
              +    * form 'lang-FOO', where FOO is a language extension describing the
              +    * language of the portion of the token in $1 after pattern executes.
              +    * E.g., if style is 'lang-lisp', and group 1 contains the text
              +    * '(hello (world))', then that portion of the token will be passed to the
              +    * registered lisp handler for formatting.
              +    * The text before and after group 1 will be restyled using this decorator
              +    * so decorators should take care that this doesn't result in infinite
              +    * recursion.  For example, the HTML lexer rule for SCRIPT elements looks
              +    * something like ['lang-js', /<[s]cript>(.+?)<\/script>/].  This may match
              +    * '<script>foo()<\/script>', which would cause the current decorator to
              +    * be called with '<script>' which would not match the same rule since
              +    * group 1 must not be empty, so it would be instead styled as PR_TAG by
              +    * the generic tag rule.  The handler registered for the 'js' extension would
              +    * then be called with 'foo()', and finally, the current decorator would
              +    * be called with '<\/script>' which would not match the original rule and
              +    * so the generic tag rule would identify it as a tag.
              +    *
              +    * Pattern must only match prefixes, and if it matches a prefix, then that
              +    * match is considered a token with the same style.
              +    *
              +    * Context is applied to the last non-whitespace, non-comment token
              +    * recognized.
              +    *
              +    * Shortcut is an optional string of characters, any of which, if the first
              +    * character, gurantee that this pattern and only this pattern matches.
              +    *
              +    * @param {Array} shortcutStylePatterns patterns that always start with
              +    *   a known character.  Must have a shortcut string.
              +    * @param {Array} fallthroughStylePatterns patterns that will be tried in
              +    *   order if the shortcut ones fail.  May have shortcuts.
              +    *
              +    * @return {function (Object)} a
              +    *   function that takes source code and returns a list of decorations.
              +    */
              +  function createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns) {
              +    var shortcuts = {};
              +    var tokenizer;
              +    (function () {
              +      var allPatterns = shortcutStylePatterns.concat(fallthroughStylePatterns);
              +      var allRegexs = [];
              +      var regexKeys = {};
              +      for (var i = 0, n = allPatterns.length; i < n; ++i) {
              +        var patternParts = allPatterns[i];
              +        var shortcutChars = patternParts[3];
              +        if (shortcutChars) {
              +          for (var c = shortcutChars.length; --c >= 0;) {
              +            shortcuts[shortcutChars.charAt(c)] = patternParts;
              +          }
              +        }
              +        var regex = patternParts[1];
              +        var k = '' + regex;
              +        if (!regexKeys.hasOwnProperty(k)) {
              +          allRegexs.push(regex);
              +          regexKeys[k] = null;
              +        }
              +      }
              +      allRegexs.push(/[\0-\uffff]/);
              +      tokenizer = combinePrefixPatterns(allRegexs);
              +    })();
              +
              +    var nPatterns = fallthroughStylePatterns.length;
              +
              +    /**
              +     * Lexes job.sourceCode and produces an output array job.decorations of
              +     * style classes preceded by the position at which they start in
              +     * job.sourceCode in order.
              +     *
              +     * @param {Object} job an object like <pre>{
              +     *    sourceCode: {string} sourceText plain text,
              +     *    basePos: {int} position of job.sourceCode in the larger chunk of
              +     *        sourceCode.
              +     * }</pre>
              +     */
              +    var decorate = function (job) {
              +      var sourceCode = job.sourceCode, basePos = job.basePos;
              +      /** Even entries are positions in source in ascending order.  Odd enties
              +        * are style markers (e.g., PR_COMMENT) that run from that position until
              +        * the end.
              +        * @type {Array.<number|string>}
              +        */
              +      var decorations = [basePos, PR_PLAIN];
              +      var pos = 0;  // index into sourceCode
              +      var tokens = sourceCode.match(tokenizer) || [];
              +      var styleCache = {};
              +
              +      for (var ti = 0, nTokens = tokens.length; ti < nTokens; ++ti) {
              +        var token = tokens[ti];
              +        var style = styleCache[token];
              +        var match = void 0;
              +
              +        var isEmbedded;
              +        if (typeof style === 'string') {
              +          isEmbedded = false;
              +        } else {
              +          var patternParts = shortcuts[token.charAt(0)];
              +          if (patternParts) {
              +            match = token.match(patternParts[1]);
              +            style = patternParts[0];
              +          } else {
              +            for (var i = 0; i < nPatterns; ++i) {
              +              patternParts = fallthroughStylePatterns[i];
              +              match = token.match(patternParts[1]);
              +              if (match) {
              +                style = patternParts[0];
              +                break;
              +              }
              +            }
              +
              +            if (!match) {  // make sure that we make progress
              +              style = PR_PLAIN;
              +            }
              +          }
              +
              +          isEmbedded = style.length >= 5 && 'lang-' === style.substring(0, 5);
              +          if (isEmbedded && !(match && typeof match[1] === 'string')) {
              +            isEmbedded = false;
              +            style = PR_SOURCE;
              +          }
              +
              +          if (!isEmbedded) { styleCache[token] = style; }
              +        }
              +
              +        var tokenStart = pos;
              +        pos += token.length;
              +
              +        if (!isEmbedded) {
              +          decorations.push(basePos + tokenStart, style);
              +        } else {  // Treat group 1 as an embedded block of source code.
              +          var embeddedSource = match[1];
              +          var embeddedSourceStart = token.indexOf(embeddedSource);
              +          var embeddedSourceEnd = embeddedSourceStart + embeddedSource.length;
              +          if (match[2]) {
              +            // If embeddedSource can be blank, then it would match at the
              +            // beginning which would cause us to infinitely recurse on the
              +            // entire token, so we catch the right context in match[2].
              +            embeddedSourceEnd = token.length - match[2].length;
              +            embeddedSourceStart = embeddedSourceEnd - embeddedSource.length;
              +          }
              +          var lang = style.substring(5);
              +          // Decorate the left of the embedded source
              +          appendDecorations(
              +              basePos + tokenStart,
              +              token.substring(0, embeddedSourceStart),
              +              decorate, decorations);
              +          // Decorate the embedded source
              +          appendDecorations(
              +              basePos + tokenStart + embeddedSourceStart,
              +              embeddedSource,
              +              langHandlerForExtension(lang, embeddedSource),
              +              decorations);
              +          // Decorate the right of the embedded section
              +          appendDecorations(
              +              basePos + tokenStart + embeddedSourceEnd,
              +              token.substring(embeddedSourceEnd),
              +              decorate, decorations);
              +        }
              +      }
              +      job.decorations = decorations;
              +    };
              +    return decorate;
              +  }
              +
              +  /** returns a function that produces a list of decorations from source text.
              +    *
              +    * This code treats ", ', and ` as string delimiters, and \ as a string
              +    * escape.  It does not recognize perl's qq() style strings.
              +    * It has no special handling for double delimiter escapes as in basic, or
              +    * the tripled delimiters used in python, but should work on those regardless
              +    * although in those cases a single string literal may be broken up into
              +    * multiple adjacent string literals.
              +    *
              +    * It recognizes C, C++, and shell style comments.
              +    *
              +    * @param {Object} options a set of optional parameters.
              +    * @return {function (Object)} a function that examines the source code
              +    *     in the input job and builds the decoration list.
              +    */
              +  function sourceDecorator(options) {
              +    var shortcutStylePatterns = [], fallthroughStylePatterns = [];
              +    if (options['tripleQuotedStrings']) {
              +      // '''multi-line-string''', 'single-line-string', and double-quoted
              +      shortcutStylePatterns.push(
              +          [PR_STRING,  /^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,
              +           null, '\'"']);
              +    } else if (options['multiLineStrings']) {
              +      // 'multi-line-string', "multi-line-string"
              +      shortcutStylePatterns.push(
              +          [PR_STRING,  /^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,
              +           null, '\'"`']);
              +    } else {
              +      // 'single-line-string', "single-line-string"
              +      shortcutStylePatterns.push(
              +          [PR_STRING,
              +           /^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,
              +           null, '"\'']);
              +    }
              +    if (options['verbatimStrings']) {
              +      // verbatim-string-literal production from the C# grammar.  See issue 93.
              +      fallthroughStylePatterns.push(
              +          [PR_STRING, /^@\"(?:[^\"]|\"\")*(?:\"|$)/, null]);
              +    }
              +    var hc = options['hashComments'];
              +    if (hc) {
              +      if (options['cStyleComments']) {
              +        if (hc > 1) {  // multiline hash comments
              +          shortcutStylePatterns.push(
              +              [PR_COMMENT, /^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/, null, '#']);
              +        } else {
              +          // Stop C preprocessor declarations at an unclosed open comment
              +          shortcutStylePatterns.push(
              +              [PR_COMMENT, /^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\b|[^\r\n]*)/,
              +               null, '#']);
              +        }
              +        // #include <stdio.h>
              +        fallthroughStylePatterns.push(
              +            [PR_STRING,
              +             /^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h(?:h|pp|\+\+)?|[a-z]\w*)>/,
              +             null]);
              +      } else {
              +        shortcutStylePatterns.push([PR_COMMENT, /^#[^\r\n]*/, null, '#']);
              +      }
              +    }
              +    if (options['cStyleComments']) {
              +      fallthroughStylePatterns.push([PR_COMMENT, /^\/\/[^\r\n]*/, null]);
              +      fallthroughStylePatterns.push(
              +          [PR_COMMENT, /^\/\*[\s\S]*?(?:\*\/|$)/, null]);
              +    }
              +    var regexLiterals = options['regexLiterals'];
              +    if (regexLiterals) {
              +      /**
              +       * @const
              +       */
              +      var regexExcls = regexLiterals > 1
              +        ? ''  // Multiline regex literals
              +        : '\n\r';
              +      /**
              +       * @const
              +       */
              +      var regexAny = regexExcls ? '.' : '[\\S\\s]';
              +      /**
              +       * @const
              +       */
              +      var REGEX_LITERAL = (
              +          // A regular expression literal starts with a slash that is
              +          // not followed by * or / so that it is not confused with
              +          // comments.
              +          '/(?=[^/*' + regexExcls + '])'
              +          // and then contains any number of raw characters,
              +          + '(?:[^/\\x5B\\x5C' + regexExcls + ']'
              +          // escape sequences (\x5C),
              +          +    '|\\x5C' + regexAny
              +          // or non-nesting character sets (\x5B\x5D);
              +          +    '|\\x5B(?:[^\\x5C\\x5D' + regexExcls + ']'
              +          +             '|\\x5C' + regexAny + ')*(?:\\x5D|$))+'
              +          // finally closed by a /.
              +          + '/');
              +      fallthroughStylePatterns.push(
              +          ['lang-regex',
              +           RegExp('^' + REGEXP_PRECEDER_PATTERN + '(' + REGEX_LITERAL + ')')
              +           ]);
              +    }
              +
              +    var types = options['types'];
              +    if (types) {
              +      fallthroughStylePatterns.push([PR_TYPE, types]);
              +    }
              +
              +    var keywords = ("" + options['keywords']).replace(/^ | $/g, '');
              +    if (keywords.length) {
              +      fallthroughStylePatterns.push(
              +          [PR_KEYWORD,
              +           new RegExp('^(?:' + keywords.replace(/[\s,]+/g, '|') + ')\\b'),
              +           null]);
              +    }
              +
              +    shortcutStylePatterns.push([PR_PLAIN,       /^\s+/, null, ' \r\n\t\xA0']);
              +
              +    var punctuation =
              +      // The Bash man page says
              +
              +      // A word is a sequence of characters considered as a single
              +      // unit by GRUB. Words are separated by metacharacters,
              +      // which are the following plus space, tab, and newline: { }
              +      // | & $ ; < >
              +      // ...
              +      
              +      // A word beginning with # causes that word and all remaining
              +      // characters on that line to be ignored.
              +
              +      // which means that only a '#' after /(?:^|[{}|&$;<>\s])/ starts a
              +      // comment but empirically
              +      // $ echo {#}
              +      // {#}
              +      // $ echo \$#
              +      // $#
              +      // $ echo }#
              +      // }#
              +
              +      // so /(?:^|[|&;<>\s])/ is more appropriate.
              +
              +      // http://gcc.gnu.org/onlinedocs/gcc-2.95.3/cpp_1.html#SEC3
              +      // suggests that this definition is compatible with a
              +      // default mode that tries to use a single token definition
              +      // to recognize both bash/python style comments and C
              +      // preprocessor directives.
              +
              +      // This definition of punctuation does not include # in the list of
              +      // follow-on exclusions, so # will not be broken before if preceeded
              +      // by a punctuation character.  We could try to exclude # after
              +      // [|&;<>] but that doesn't seem to cause many major problems.
              +      // If that does turn out to be a problem, we should change the below
              +      // when hc is truthy to include # in the run of punctuation characters
              +      // only when not followint [|&;<>].
              +      '^.[^\\s\\w.$@\'"`/\\\\]*';
              +    if (options['regexLiterals']) {
              +      punctuation += '(?!\s*\/)';
              +    }
              +
              +    fallthroughStylePatterns.push(
              +        // TODO(mikesamuel): recognize non-latin letters and numerals in idents
              +        [PR_LITERAL,     /^@[a-z_$][a-z_$@0-9]*/i, null],
              +        [PR_TYPE,        /^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/, null],
              +        [PR_PLAIN,       /^[a-z_$][a-z_$@0-9]*/i, null],
              +        [PR_LITERAL,
              +         new RegExp(
              +             '^(?:'
              +             // A hex number
              +             + '0x[a-f0-9]+'
              +             // or an octal or decimal number,
              +             + '|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)'
              +             // possibly in scientific notation
              +             + '(?:e[+\\-]?\\d+)?'
              +             + ')'
              +             // with an optional modifier like UL for unsigned long
              +             + '[a-z]*', 'i'),
              +         null, '0123456789'],
              +        // Don't treat escaped quotes in bash as starting strings.
              +        // See issue 144.
              +        [PR_PLAIN,       /^\\[\s\S]?/, null],
              +        [PR_PUNCTUATION, new RegExp(punctuation), null]);
              +
              +    return createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns);
              +  }
              +
              +  var decorateSource = sourceDecorator({
              +        'keywords': ALL_KEYWORDS,
              +        'hashComments': true,
              +        'cStyleComments': true,
              +        'multiLineStrings': true,
              +        'regexLiterals': true
              +      });
              +
              +  /**
              +   * Given a DOM subtree, wraps it in a list, and puts each line into its own
              +   * list item.
              +   *
              +   * @param {Node} node modified in place.  Its content is pulled into an
              +   *     HTMLOListElement, and each line is moved into a separate list item.
              +   *     This requires cloning elements, so the input might not have unique
              +   *     IDs after numbering.
              +   * @param {boolean} isPreformatted true iff white-space in text nodes should
              +   *     be treated as significant.
              +   */
              +  function numberLines(node, opt_startLineNum, isPreformatted) {
              +    var nocode = /(?:^|\s)nocode(?:\s|$)/;
              +    var lineBreak = /\r\n?|\n/;
              +  
              +    var document = node.ownerDocument;
              +  
              +    var li = document.createElement('li');
              +    while (node.firstChild) {
              +      li.appendChild(node.firstChild);
              +    }
              +    // An array of lines.  We split below, so this is initialized to one
              +    // un-split line.
              +    var listItems = [li];
              +  
              +    function walk(node) {
              +      var type = node.nodeType;
              +      if (type == 1 && !nocode.test(node.className)) {  // Element
              +        if ('br' === node.nodeName) {
              +          breakAfter(node);
              +          // Discard the <BR> since it is now flush against a </LI>.
              +          if (node.parentNode) {
              +            node.parentNode.removeChild(node);
              +          }
              +        } else {
              +          for (var child = node.firstChild; child; child = child.nextSibling) {
              +            walk(child);
              +          }
              +        }
              +      } else if ((type == 3 || type == 4) && isPreformatted) {  // Text
              +        var text = node.nodeValue;
              +        var match = text.match(lineBreak);
              +        if (match) {
              +          var firstLine = text.substring(0, match.index);
              +          node.nodeValue = firstLine;
              +          var tail = text.substring(match.index + match[0].length);
              +          if (tail) {
              +            var parent = node.parentNode;
              +            parent.insertBefore(
              +              document.createTextNode(tail), node.nextSibling);
              +          }
              +          breakAfter(node);
              +          if (!firstLine) {
              +            // Don't leave blank text nodes in the DOM.
              +            node.parentNode.removeChild(node);
              +          }
              +        }
              +      }
              +    }
              +  
              +    // Split a line after the given node.
              +    function breakAfter(lineEndNode) {
              +      // If there's nothing to the right, then we can skip ending the line
              +      // here, and move root-wards since splitting just before an end-tag
              +      // would require us to create a bunch of empty copies.
              +      while (!lineEndNode.nextSibling) {
              +        lineEndNode = lineEndNode.parentNode;
              +        if (!lineEndNode) { return; }
              +      }
              +  
              +      function breakLeftOf(limit, copy) {
              +        // Clone shallowly if this node needs to be on both sides of the break.
              +        var rightSide = copy ? limit.cloneNode(false) : limit;
              +        var parent = limit.parentNode;
              +        if (parent) {
              +          // We clone the parent chain.
              +          // This helps us resurrect important styling elements that cross lines.
              +          // E.g. in <i>Foo<br>Bar</i>
              +          // should be rewritten to <li><i>Foo</i></li><li><i>Bar</i></li>.
              +          var parentClone = breakLeftOf(parent, 1);
              +          // Move the clone and everything to the right of the original
              +          // onto the cloned parent.
              +          var next = limit.nextSibling;
              +          parentClone.appendChild(rightSide);
              +          for (var sibling = next; sibling; sibling = next) {
              +            next = sibling.nextSibling;
              +            parentClone.appendChild(sibling);
              +          }
              +        }
              +        return rightSide;
              +      }
              +  
              +      var copiedListItem = breakLeftOf(lineEndNode.nextSibling, 0);
              +  
              +      // Walk the parent chain until we reach an unattached LI.
              +      for (var parent;
              +           // Check nodeType since IE invents document fragments.
              +           (parent = copiedListItem.parentNode) && parent.nodeType === 1;) {
              +        copiedListItem = parent;
              +      }
              +      // Put it on the list of lines for later processing.
              +      listItems.push(copiedListItem);
              +    }
              +  
              +    // Split lines while there are lines left to split.
              +    for (var i = 0;  // Number of lines that have been split so far.
              +         i < listItems.length;  // length updated by breakAfter calls.
              +         ++i) {
              +      walk(listItems[i]);
              +    }
              +  
              +    // Make sure numeric indices show correctly.
              +    if (opt_startLineNum === (opt_startLineNum|0)) {
              +      listItems[0].setAttribute('value', opt_startLineNum);
              +    }
              +  
              +    var ol = document.createElement('ol');
              +    ol.className = 'linenums';
              +    var offset = Math.max(0, ((opt_startLineNum - 1 /* zero index */)) | 0) || 0;
              +    for (var i = 0, n = listItems.length; i < n; ++i) {
              +      li = listItems[i];
              +      // Stick a class on the LIs so that stylesheets can
              +      // color odd/even rows, or any other row pattern that
              +      // is co-prime with 10.
              +      li.className = 'L' + ((i + offset) % 10);
              +      if (!li.firstChild) {
              +        li.appendChild(document.createTextNode('\xA0'));
              +      }
              +      ol.appendChild(li);
              +    }
              +  
              +    node.appendChild(ol);
              +  }
              +  /**
              +   * Breaks {@code job.sourceCode} around style boundaries in
              +   * {@code job.decorations} and modifies {@code job.sourceNode} in place.
              +   * @param {Object} job like <pre>{
              +   *    sourceCode: {string} source as plain text,
              +   *    sourceNode: {HTMLElement} the element containing the source,
              +   *    spans: {Array.<number|Node>} alternating span start indices into source
              +   *       and the text node or element (e.g. {@code <BR>}) corresponding to that
              +   *       span.
              +   *    decorations: {Array.<number|string} an array of style classes preceded
              +   *       by the position at which they start in job.sourceCode in order
              +   * }</pre>
              +   * @private
              +   */
              +  function recombineTagsAndDecorations(job) {
              +    var isIE8OrEarlier = /\bMSIE\s(\d+)/.exec(navigator.userAgent);
              +    isIE8OrEarlier = isIE8OrEarlier && +isIE8OrEarlier[1] <= 8;
              +    var newlineRe = /\n/g;
              +  
              +    var source = job.sourceCode;
              +    var sourceLength = source.length;
              +    // Index into source after the last code-unit recombined.
              +    var sourceIndex = 0;
              +  
              +    var spans = job.spans;
              +    var nSpans = spans.length;
              +    // Index into spans after the last span which ends at or before sourceIndex.
              +    var spanIndex = 0;
              +  
              +    var decorations = job.decorations;
              +    var nDecorations = decorations.length;
              +    // Index into decorations after the last decoration which ends at or before
              +    // sourceIndex.
              +    var decorationIndex = 0;
              +  
              +    // Remove all zero-length decorations.
              +    decorations[nDecorations] = sourceLength;
              +    var decPos, i;
              +    for (i = decPos = 0; i < nDecorations;) {
              +      if (decorations[i] !== decorations[i + 2]) {
              +        decorations[decPos++] = decorations[i++];
              +        decorations[decPos++] = decorations[i++];
              +      } else {
              +        i += 2;
              +      }
              +    }
              +    nDecorations = decPos;
              +  
              +    // Simplify decorations.
              +    for (i = decPos = 0; i < nDecorations;) {
              +      var startPos = decorations[i];
              +      // Conflate all adjacent decorations that use the same style.
              +      var startDec = decorations[i + 1];
              +      var end = i + 2;
              +      while (end + 2 <= nDecorations && decorations[end + 1] === startDec) {
              +        end += 2;
              +      }
              +      decorations[decPos++] = startPos;
              +      decorations[decPos++] = startDec;
              +      i = end;
              +    }
              +  
              +    nDecorations = decorations.length = decPos;
              +  
              +    var sourceNode = job.sourceNode;
              +    var oldDisplay;
              +    if (sourceNode) {
              +      oldDisplay = sourceNode.style.display;
              +      sourceNode.style.display = 'none';
              +    }
              +    try {
              +      var decoration = null;
              +      while (spanIndex < nSpans) {
              +        var spanStart = spans[spanIndex];
              +        var spanEnd = spans[spanIndex + 2] || sourceLength;
              +  
              +        var decEnd = decorations[decorationIndex + 2] || sourceLength;
              +  
              +        var end = Math.min(spanEnd, decEnd);
              +  
              +        var textNode = spans[spanIndex + 1];
              +        var styledText;
              +        if (textNode.nodeType !== 1  // Don't muck with <BR>s or <LI>s
              +            // Don't introduce spans around empty text nodes.
              +            && (styledText = source.substring(sourceIndex, end))) {
              +          // This may seem bizarre, and it is.  Emitting LF on IE causes the
              +          // code to display with spaces instead of line breaks.
              +          // Emitting Windows standard issue linebreaks (CRLF) causes a blank
              +          // space to appear at the beginning of every line but the first.
              +          // Emitting an old Mac OS 9 line separator makes everything spiffy.
              +          if (isIE8OrEarlier) {
              +            styledText = styledText.replace(newlineRe, '\r');
              +          }
              +          textNode.nodeValue = styledText;
              +          var document = textNode.ownerDocument;
              +          var span = document.createElement('span');
              +          span.className = decorations[decorationIndex + 1];
              +          var parentNode = textNode.parentNode;
              +          parentNode.replaceChild(span, textNode);
              +          span.appendChild(textNode);
              +          if (sourceIndex < spanEnd) {  // Split off a text node.
              +            spans[spanIndex + 1] = textNode
              +                // TODO: Possibly optimize by using '' if there's no flicker.
              +                = document.createTextNode(source.substring(end, spanEnd));
              +            parentNode.insertBefore(textNode, span.nextSibling);
              +          }
              +        }
              +  
              +        sourceIndex = end;
              +  
              +        if (sourceIndex >= spanEnd) {
              +          spanIndex += 2;
              +        }
              +        if (sourceIndex >= decEnd) {
              +          decorationIndex += 2;
              +        }
              +      }
              +    } finally {
              +      if (sourceNode) {
              +        sourceNode.style.display = oldDisplay;
              +      }
              +    }
              +  }
              +
              +  /** Maps language-specific file extensions to handlers. */
              +  var langHandlerRegistry = {};
              +  /** Register a language handler for the given file extensions.
              +    * @param {function (Object)} handler a function from source code to a list
              +    *      of decorations.  Takes a single argument job which describes the
              +    *      state of the computation.   The single parameter has the form
              +    *      {@code {
              +    *        sourceCode: {string} as plain text.
              +    *        decorations: {Array.<number|string>} an array of style classes
              +    *                     preceded by the position at which they start in
              +    *                     job.sourceCode in order.
              +    *                     The language handler should assigned this field.
              +    *        basePos: {int} the position of source in the larger source chunk.
              +    *                 All positions in the output decorations array are relative
              +    *                 to the larger source chunk.
              +    *      } }
              +    * @param {Array.<string>} fileExtensions
              +    */
              +  function registerLangHandler(handler, fileExtensions) {
              +    for (var i = fileExtensions.length; --i >= 0;) {
              +      var ext = fileExtensions[i];
              +      if (!langHandlerRegistry.hasOwnProperty(ext)) {
              +        langHandlerRegistry[ext] = handler;
              +      } else if (win['console']) {
              +        console['warn']('cannot override language handler %s', ext);
              +      }
              +    }
              +  }
              +  function langHandlerForExtension(extension, source) {
              +    if (!(extension && langHandlerRegistry.hasOwnProperty(extension))) {
              +      // Treat it as markup if the first non whitespace character is a < and
              +      // the last non-whitespace character is a >.
              +      extension = /^\s*</.test(source)
              +          ? 'default-markup'
              +          : 'default-code';
              +    }
              +    return langHandlerRegistry[extension];
              +  }
              +  registerLangHandler(decorateSource, ['default-code']);
              +  registerLangHandler(
              +      createSimpleLexer(
              +          [],
              +          [
              +           [PR_PLAIN,       /^[^<?]+/],
              +           [PR_DECLARATION, /^<!\w[^>]*(?:>|$)/],
              +           [PR_COMMENT,     /^<\!--[\s\S]*?(?:-\->|$)/],
              +           // Unescaped content in an unknown language
              +           ['lang-',        /^<\?([\s\S]+?)(?:\?>|$)/],
              +           ['lang-',        /^<\%([\s\S]+?)(?:%>|$)/],
              +           [PR_PUNCTUATION, /^(?:<[%?]|[%?]>)/],
              +           ['lang-',        /^<xmp\b[^>]*>([\s\S]+?)<\/xmp\b[^>]*>/i],
              +           // Unescaped content in javascript.  (Or possibly vbscript).
              +           ['lang-js',      /^<script\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],
              +           // Contains unescaped stylesheet content
              +           ['lang-css',     /^<style\b[^>]*>([\s\S]*?)(<\/style\b[^>]*>)/i],
              +           ['lang-in.tag',  /^(<\/?[a-z][^<>]*>)/i]
              +          ]),
              +      ['default-markup', 'htm', 'html', 'mxml', 'xhtml', 'xml', 'xsl']);
              +  registerLangHandler(
              +      createSimpleLexer(
              +          [
              +           [PR_PLAIN,        /^[\s]+/, null, ' \t\r\n'],
              +           [PR_ATTRIB_VALUE, /^(?:\"[^\"]*\"?|\'[^\']*\'?)/, null, '\"\'']
              +           ],
              +          [
              +           [PR_TAG,          /^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],
              +           [PR_ATTRIB_NAME,  /^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],
              +           ['lang-uq.val',   /^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],
              +           [PR_PUNCTUATION,  /^[=<>\/]+/],
              +           ['lang-js',       /^on\w+\s*=\s*\"([^\"]+)\"/i],
              +           ['lang-js',       /^on\w+\s*=\s*\'([^\']+)\'/i],
              +           ['lang-js',       /^on\w+\s*=\s*([^\"\'>\s]+)/i],
              +           ['lang-css',      /^style\s*=\s*\"([^\"]+)\"/i],
              +           ['lang-css',      /^style\s*=\s*\'([^\']+)\'/i],
              +           ['lang-css',      /^style\s*=\s*([^\"\'>\s]+)/i]
              +           ]),
              +      ['in.tag']);
              +  registerLangHandler(
              +      createSimpleLexer([], [[PR_ATTRIB_VALUE, /^[\s\S]+/]]), ['uq.val']);
              +  registerLangHandler(sourceDecorator({
              +          'keywords': CPP_KEYWORDS,
              +          'hashComments': true,
              +          'cStyleComments': true,
              +          'types': C_TYPES
              +        }), ['c', 'cc', 'cpp', 'cxx', 'cyc', 'm']);
              +  registerLangHandler(sourceDecorator({
              +          'keywords': 'null,true,false'
              +        }), ['json']);
              +  registerLangHandler(sourceDecorator({
              +          'keywords': CSHARP_KEYWORDS,
              +          'hashComments': true,
              +          'cStyleComments': true,
              +          'verbatimStrings': true,
              +          'types': C_TYPES
              +        }), ['cs']);
              +  registerLangHandler(sourceDecorator({
              +          'keywords': JAVA_KEYWORDS,
              +          'cStyleComments': true
              +        }), ['java']);
              +  registerLangHandler(sourceDecorator({
              +          'keywords': SH_KEYWORDS,
              +          'hashComments': true,
              +          'multiLineStrings': true
              +        }), ['bash', 'bsh', 'csh', 'sh']);
              +  registerLangHandler(sourceDecorator({
              +          'keywords': PYTHON_KEYWORDS,
              +          'hashComments': true,
              +          'multiLineStrings': true,
              +          'tripleQuotedStrings': true
              +        }), ['cv', 'py', 'python']);
              +  registerLangHandler(sourceDecorator({
              +          'keywords': PERL_KEYWORDS,
              +          'hashComments': true,
              +          'multiLineStrings': true,
              +          'regexLiterals': 2  // multiline regex literals
              +        }), ['perl', 'pl', 'pm']);
              +  registerLangHandler(sourceDecorator({
              +          'keywords': RUBY_KEYWORDS,
              +          'hashComments': true,
              +          'multiLineStrings': true,
              +          'regexLiterals': true
              +        }), ['rb', 'ruby']);
              +  registerLangHandler(sourceDecorator({
              +          'keywords': JSCRIPT_KEYWORDS,
              +          'cStyleComments': true,
              +          'regexLiterals': true
              +        }), ['javascript', 'js']);
              +  registerLangHandler(sourceDecorator({
              +          'keywords': COFFEE_KEYWORDS,
              +          'hashComments': 3,  // ### style block comments
              +          'cStyleComments': true,
              +          'multilineStrings': true,
              +          'tripleQuotedStrings': true,
              +          'regexLiterals': true
              +        }), ['coffee']);
              +  registerLangHandler(sourceDecorator({
              +          'keywords': RUST_KEYWORDS,
              +          'cStyleComments': true,
              +          'multilineStrings': true
              +        }), ['rc', 'rs', 'rust']);
              +  registerLangHandler(
              +      createSimpleLexer([], [[PR_STRING, /^[\s\S]+/]]), ['regex']);
              +
              +  function applyDecorator(job) {
              +    var opt_langExtension = job.langExtension;
              +
              +    try {
              +      // Extract tags, and convert the source code to plain text.
              +      var sourceAndSpans = extractSourceSpans(job.sourceNode, job.pre);
              +      /** Plain text. @type {string} */
              +      var source = sourceAndSpans.sourceCode;
              +      job.sourceCode = source;
              +      job.spans = sourceAndSpans.spans;
              +      job.basePos = 0;
              +
              +      // Apply the appropriate language handler
              +      langHandlerForExtension(opt_langExtension, source)(job);
              +
              +      // Integrate the decorations and tags back into the source code,
              +      // modifying the sourceNode in place.
              +      recombineTagsAndDecorations(job);
              +    } catch (e) {
              +      if (win['console']) {
              +        console['log'](e && e['stack'] || e);
              +      }
              +    }
              +  }
              +
              +  /**
              +   * Pretty print a chunk of code.
              +   * @param sourceCodeHtml {string} The HTML to pretty print.
              +   * @param opt_langExtension {string} The language name to use.
              +   *     Typically, a filename extension like 'cpp' or 'java'.
              +   * @param opt_numberLines {number|boolean} True to number lines,
              +   *     or the 1-indexed number of the first line in sourceCodeHtml.
              +   */
              +  function $prettyPrintOne(sourceCodeHtml, opt_langExtension, opt_numberLines) {
              +    var container = document.createElement('div');
              +    // This could cause images to load and onload listeners to fire.
              +    // E.g. <img onerror="alert(1337)" src="nosuchimage.png">.
              +    // We assume that the inner HTML is from a trusted source.
              +    // The pre-tag is required for IE8 which strips newlines from innerHTML
              +    // when it is injected into a <pre> tag.
              +    // http://stackoverflow.com/questions/451486/pre-tag-loses-line-breaks-when-setting-innerhtml-in-ie
              +    // http://stackoverflow.com/questions/195363/inserting-a-newline-into-a-pre-tag-ie-javascript
              +    container.innerHTML = '<pre>' + sourceCodeHtml + '</pre>';
              +    container = container.firstChild;
              +    if (opt_numberLines) {
              +      numberLines(container, opt_numberLines, true);
              +    }
              +
              +    var job = {
              +      langExtension: opt_langExtension,
              +      numberLines: opt_numberLines,
              +      sourceNode: container,
              +      pre: 1
              +    };
              +    applyDecorator(job);
              +    return container.innerHTML;
              +  }
              +
              +   /**
              +    * Find all the {@code <pre>} and {@code <code>} tags in the DOM with
              +    * {@code class=prettyprint} and prettify them.
              +    *
              +    * @param {Function} opt_whenDone called when prettifying is done.
              +    * @param {HTMLElement|HTMLDocument} opt_root an element or document
              +    *   containing all the elements to pretty print.
              +    *   Defaults to {@code document.body}.
              +    */
              +  function $prettyPrint(opt_whenDone, opt_root) {
              +    var root = opt_root || document.body;
              +    var doc = root.ownerDocument || document;
              +    function byTagName(tn) { return root.getElementsByTagName(tn); }
              +    // fetch a list of nodes to rewrite
              +    var codeSegments = [byTagName('pre'), byTagName('code'), byTagName('xmp')];
              +    var elements = [];
              +    for (var i = 0; i < codeSegments.length; ++i) {
              +      for (var j = 0, n = codeSegments[i].length; j < n; ++j) {
              +        elements.push(codeSegments[i][j]);
              +      }
              +    }
              +    codeSegments = null;
              +
              +    var clock = Date;
              +    if (!clock['now']) {
              +      clock = { 'now': function () { return +(new Date); } };
              +    }
              +
              +    // The loop is broken into a series of continuations to make sure that we
              +    // don't make the browser unresponsive when rewriting a large page.
              +    var k = 0;
              +    var prettyPrintingJob;
              +
              +    var langExtensionRe = /\blang(?:uage)?-([\w.]+)(?!\S)/;
              +    var prettyPrintRe = /\bprettyprint\b/;
              +    var prettyPrintedRe = /\bprettyprinted\b/;
              +    var preformattedTagNameRe = /pre|xmp/i;
              +    var codeRe = /^code$/i;
              +    var preCodeXmpRe = /^(?:pre|code|xmp)$/i;
              +    var EMPTY = {};
              +
              +    function doWork() {
              +      var endTime = (win['PR_SHOULD_USE_CONTINUATION'] ?
              +                     clock['now']() + 250 /* ms */ :
              +                     Infinity);
              +      for (; k < elements.length && clock['now']() < endTime; k++) {
              +        var cs = elements[k];
              +
              +        // Look for a preceding comment like
              +        // <?prettify lang="..." linenums="..."?>
              +        var attrs = EMPTY;
              +        {
              +          for (var preceder = cs; (preceder = preceder.previousSibling);) {
              +            var nt = preceder.nodeType;
              +            // <?foo?> is parsed by HTML 5 to a comment node (8)
              +            // like <!--?foo?-->, but in XML is a processing instruction
              +            var value = (nt === 7 || nt === 8) && preceder.nodeValue;
              +            if (value
              +                ? !/^\??prettify\b/.test(value)
              +                : (nt !== 3 || /\S/.test(preceder.nodeValue))) {
              +              // Skip over white-space text nodes but not others.
              +              break;
              +            }
              +            if (value) {
              +              attrs = {};
              +              value.replace(
              +                  /\b(\w+)=([\w:.%+-]+)/g,
              +                function (_, name, value) { attrs[name] = value; });
              +              break;
              +            }
              +          }
              +        }
              +
              +        var className = cs.className;
              +        if ((attrs !== EMPTY || prettyPrintRe.test(className))
              +            // Don't redo this if we've already done it.
              +            // This allows recalling pretty print to just prettyprint elements
              +            // that have been added to the page since last call.
              +            && !prettyPrintedRe.test(className)) {
              +
              +          // make sure this is not nested in an already prettified element
              +          var nested = false;
              +          for (var p = cs.parentNode; p; p = p.parentNode) {
              +            var tn = p.tagName;
              +            if (preCodeXmpRe.test(tn)
              +                && p.className && prettyPrintRe.test(p.className)) {
              +              nested = true;
              +              break;
              +            }
              +          }
              +          if (!nested) {
              +            // Mark done.  If we fail to prettyprint for whatever reason,
              +            // we shouldn't try again.
              +            cs.className += ' prettyprinted';
              +
              +            // If the classes includes a language extensions, use it.
              +            // Language extensions can be specified like
              +            //     <pre class="prettyprint lang-cpp">
              +            // the language extension "cpp" is used to find a language handler
              +            // as passed to PR.registerLangHandler.
              +            // HTML5 recommends that a language be specified using "language-"
              +            // as the prefix instead.  Google Code Prettify supports both.
              +            // http://dev.w3.org/html5/spec-author-view/the-code-element.html
              +            var langExtension = attrs['lang'];
              +            if (!langExtension) {
              +              langExtension = className.match(langExtensionRe);
              +              // Support <pre class="prettyprint"><code class="language-c">
              +              var wrapper;
              +              if (!langExtension && (wrapper = childContentWrapper(cs))
              +                  && codeRe.test(wrapper.tagName)) {
              +                langExtension = wrapper.className.match(langExtensionRe);
              +              }
              +
              +              if (langExtension) { langExtension = langExtension[1]; }
              +            }
              +
              +            var preformatted;
              +            if (preformattedTagNameRe.test(cs.tagName)) {
              +              preformatted = 1;
              +            } else {
              +              var currentStyle = cs['currentStyle'];
              +              var defaultView = doc.defaultView;
              +              var whitespace = (
              +                  currentStyle
              +                  ? currentStyle['whiteSpace']
              +                  : (defaultView
              +                     && defaultView.getComputedStyle)
              +                  ? defaultView.getComputedStyle(cs, null)
              +                  .getPropertyValue('white-space')
              +                  : 0);
              +              preformatted = whitespace
              +                  && 'pre' === whitespace.substring(0, 3);
              +            }
              +
              +            // Look for a class like linenums or linenums:<n> where <n> is the
              +            // 1-indexed number of the first line.
              +            var lineNums = attrs['linenums'];
              +            if (!(lineNums = lineNums === 'true' || +lineNums)) {
              +              lineNums = className.match(/\blinenums\b(?::(\d+))?/);
              +              lineNums =
              +                lineNums
              +                ? lineNums[1] && lineNums[1].length
              +                  ? +lineNums[1] : true
              +                : false;
              +            }
              +            if (lineNums) { numberLines(cs, lineNums, preformatted); }
              +
              +            // do the pretty printing
              +            prettyPrintingJob = {
              +              langExtension: langExtension,
              +              sourceNode: cs,
              +              numberLines: lineNums,
              +              pre: preformatted
              +            };
              +            applyDecorator(prettyPrintingJob);
              +          }
              +        }
              +      }
              +      if (k < elements.length) {
              +        // finish up in a continuation
              +        setTimeout(doWork, 250);
              +      } else if ('function' === typeof opt_whenDone) {
              +        opt_whenDone();
              +      }
              +    }
              +
              +    doWork();
              +  }
              +
              +  /**
              +   * Contains functions for creating and registering new language handlers.
              +   * @type {Object}
              +   */
              +  var PR = win['PR'] = {
              +        'createSimpleLexer': createSimpleLexer,
              +        'registerLangHandler': registerLangHandler,
              +        'sourceDecorator': sourceDecorator,
              +        'PR_ATTRIB_NAME': PR_ATTRIB_NAME,
              +        'PR_ATTRIB_VALUE': PR_ATTRIB_VALUE,
              +        'PR_COMMENT': PR_COMMENT,
              +        'PR_DECLARATION': PR_DECLARATION,
              +        'PR_KEYWORD': PR_KEYWORD,
              +        'PR_LITERAL': PR_LITERAL,
              +        'PR_NOCODE': PR_NOCODE,
              +        'PR_PLAIN': PR_PLAIN,
              +        'PR_PUNCTUATION': PR_PUNCTUATION,
              +        'PR_SOURCE': PR_SOURCE,
              +        'PR_STRING': PR_STRING,
              +        'PR_TAG': PR_TAG,
              +        'PR_TYPE': PR_TYPE,
              +        'prettyPrintOne':
              +           IN_GLOBAL_SCOPE
              +             ? (win['prettyPrintOne'] = $prettyPrintOne)
              +             : (prettyPrintOne = $prettyPrintOne),
              +        'prettyPrint': prettyPrint =
              +           IN_GLOBAL_SCOPE
              +             ? (win['prettyPrint'] = $prettyPrint)
              +             : (prettyPrint = $prettyPrint)
              +      };
              +
              +  // Make PR available via the Asynchronous Module Definition (AMD) API.
              +  // Per https://github.com/amdjs/amdjs-api/wiki/AMD:
              +  // The Asynchronous Module Definition (AMD) API specifies a
              +  // mechanism for defining modules such that the module and its
              +  // dependencies can be asynchronously loaded.
              +  // ...
              +  // To allow a clear indicator that a global define function (as
              +  // needed for script src browser loading) conforms to the AMD API,
              +  // any global define function SHOULD have a property called "amd"
              +  // whose value is an object. This helps avoid conflict with any
              +  // other existing JavaScript code that could have defined a define()
              +  // function that does not conform to the AMD API.
              +  if (typeof define === "function" && define['amd']) {
              +    define("google-code-prettify", [], function () {
              +      return PR; 
              +    });
              +  }
              +})();
              \ No newline at end of file
              diff --git a/src/js/lib/punycode.js b/src/js/lib/punycode.js
              new file mode 100755
              index 00000000..d07b6ef5
              --- /dev/null
              +++ b/src/js/lib/punycode.js
              @@ -0,0 +1,336 @@
              +/** @license
              +========================================================================
              +  Javascript Punycode converter derived from example in RFC3492.
              +  This implementation is created by some@domain.name and released into public domain
              +  
              +  From RFC3492:
              +  Disclaimer and license
              +  Regarding this entire document or any portion of it (including the
              +  pseudocode and C code), the author makes no guarantees and is not
              +  responsible for any damage resulting from its use. The author grants
              +  irrevocable permission to anyone to use, modify, and distribute it in
              +  any way that does not diminish the rights of anyone else to use,
              +  modify, and distribute it, provided that redistributed derivative works do not contain misleading author or version information. Derivative works need not be licensed under similar terms.
              +  
              +  I put my work in this punycode and utf16 in the public domain.
              +*/
              +"use strict";
              +
              +var punycode = new function Punycode() {
              +    // This object converts to and from puny-code used in IDN
              +    //
              +    // punycode.ToASCII(domain)
              +    // 
              +    // Returns a puny coded representation of "domain".
              +    // It only converts the part of the domain name that
              +    // has non ASCII characters. I.e. it dosent matter if
              +    // you call it with a domain that already is in ASCII.
              +    //
              +    // punycode.ToUnicode(domain)
              +    //
              +    // Converts a puny-coded domain name to unicode.
              +    // It only converts the puny-coded parts of the domain name.
              +    // I.e. it dosent matter if you call it on a string
              +    // that already has been converted to unicode.
              +    //
              +    //
              +    this.utf16 = {
              +        // The utf16-class is necessary to convert from javascripts internal character representation to unicode and back.
              +        decode:function(input){
              +            var output = [], i=0, len=input.length,value,extra;
              +            while (i < len) {
              +                value = input.charCodeAt(i++);
              +                if ((value & 0xF800) === 0xD800) {
              +                    extra = input.charCodeAt(i++);
              +                    if ( ((value & 0xFC00) !== 0xD800) || ((extra & 0xFC00) !== 0xDC00) ) {
              +                        throw new RangeError("UTF-16(decode): Illegal UTF-16 sequence");
              +                    }
              +                    value = ((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000;
              +                }
              +                output.push(value);
              +            }
              +            return output;
              +        },
              +        encode:function(input){
              +            var output = [], i=0, len=input.length,value;
              +            while (i < len) {
              +                value = input[i++];
              +                if ( (value & 0xF800) === 0xD800 ) {
              +                    throw new RangeError("UTF-16(encode): Illegal UTF-16 value");
              +                }
              +                if (value > 0xFFFF) {
              +                    value -= 0x10000;
              +                    output.push(String.fromCharCode(((value >>>10) & 0x3FF) | 0xD800));
              +                    value = 0xDC00 | (value & 0x3FF);
              +                }
              +                output.push(String.fromCharCode(value));
              +            }
              +            return output.join("");
              +        }
              +    }
              +
              +    //Default parameters
              +    var initial_n = 0x80;
              +    var initial_bias = 72;
              +    var delimiter = "\x2D";
              +    var base = 36;
              +    var damp = 700;
              +    var tmin=1;
              +    var tmax=26;
              +    var skew=38;
              +    var maxint = 0x7FFFFFFF;
              +
              +    // decode_digit(cp) returns the numeric value of a basic code 
              +    // point (for use in representing integers) in the range 0 to
              +    // base-1, or base if cp is does not represent a value.
              +
              +    function decode_digit(cp) {
              +        return cp - 48 < 10 ? cp - 22 : cp - 65 < 26 ? cp - 65 : cp - 97 < 26 ? cp - 97 : base;
              +    }
              +
              +    // encode_digit(d,flag) returns the basic code point whose value
              +    // (when used for representing integers) is d, which needs to be in
              +    // the range 0 to base-1. The lowercase form is used unless flag is
              +    // nonzero, in which case the uppercase form is used. The behavior
              +    // is undefined if flag is nonzero and digit d has no uppercase form. 
              +
              +    function encode_digit(d, flag) {
              +        return d + 22 + 75 * (d < 26) - ((flag != 0) << 5);
              +        //  0..25 map to ASCII a..z or A..Z 
              +        // 26..35 map to ASCII 0..9
              +    }
              +    //** Bias adaptation function **
              +    function adapt(delta, numpoints, firsttime ) {
              +        var k;
              +        delta = firsttime ? Math.floor(delta / damp) : (delta >> 1);
              +        delta += Math.floor(delta / numpoints);
              +
              +        for (k = 0; delta > (((base - tmin) * tmax) >> 1); k += base) {
              +                delta = Math.floor(delta / ( base - tmin ));
              +        }
              +        return Math.floor(k + (base - tmin + 1) * delta / (delta + skew));
              +    }
              +
              +    // encode_basic(bcp,flag) forces a basic code point to lowercase if flag is zero,
              +    // uppercase if flag is nonzero, and returns the resulting code point.
              +    // The code point is unchanged if it is caseless.
              +    // The behavior is undefined if bcp is not a basic code point.
              +
              +    function encode_basic(bcp, flag) {
              +        bcp -= (bcp - 97 < 26) << 5;
              +        return bcp + ((!flag && (bcp - 65 < 26)) << 5);
              +    }
              +
              +    // Main decode
              +    this.decode=function(input,preserveCase) {
              +        // Dont use utf16
              +        var output=[];
              +        var case_flags=[];
              +        var input_length = input.length;
              +
              +        var n, out, i, bias, basic, j, ic, oldi, w, k, digit, t, len;
              +
              +        // Initialize the state: 
              +
              +        n = initial_n;
              +        i = 0;
              +        bias = initial_bias;
              +
              +        // Handle the basic code points: Let basic be the number of input code 
              +        // points before the last delimiter, or 0 if there is none, then
              +        // copy the first basic code points to the output.
              +
              +        basic = input.lastIndexOf(delimiter);
              +        if (basic < 0) basic = 0;
              +
              +        for (j = 0; j < basic; ++j) {
              +            if(preserveCase) case_flags[output.length] = ( input.charCodeAt(j) -65 < 26);
              +            if ( input.charCodeAt(j) >= 0x80) {
              +                throw new RangeError("Illegal input >= 0x80");
              +            }
              +            output.push( input.charCodeAt(j) );
              +        }
              +
              +        // Main decoding loop: Start just after the last delimiter if any
              +        // basic code points were copied; start at the beginning otherwise. 
              +
              +        for (ic = basic > 0 ? basic + 1 : 0; ic < input_length; ) {
              +
              +            // ic is the index of the next character to be consumed,
              +
              +            // Decode a generalized variable-length integer into delta,
              +            // which gets added to i. The overflow checking is easier
              +            // if we increase i as we go, then subtract off its starting 
              +            // value at the end to obtain delta.
              +            for (oldi = i, w = 1, k = base; ; k += base) {
              +                    if (ic >= input_length) {
              +                        throw RangeError ("punycode_bad_input(1)");
              +                    }
              +                    digit = decode_digit(input.charCodeAt(ic++));
              +
              +                    if (digit >= base) {
              +                        throw RangeError("punycode_bad_input(2)");
              +                    }
              +                    if (digit > Math.floor((maxint - i) / w)) {
              +                        throw RangeError ("punycode_overflow(1)");
              +                    }
              +                    i += digit * w;
              +                    t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
              +                    if (digit < t) { break; }
              +                    if (w > Math.floor(maxint / (base - t))) {
              +                        throw RangeError("punycode_overflow(2)");
              +                    }
              +                    w *= (base - t);
              +            }
              +
              +            out = output.length + 1;
              +            bias = adapt(i - oldi, out, oldi === 0);
              +
              +            // i was supposed to wrap around from out to 0,
              +            // incrementing n each time, so we'll fix that now: 
              +            if ( Math.floor(i / out) > maxint - n) {
              +                throw RangeError("punycode_overflow(3)");
              +            }
              +            n += Math.floor( i / out ) ;
              +            i %= out;
              +
              +            // Insert n at position i of the output: 
              +            // Case of last character determines uppercase flag: 
              +            if (preserveCase) { case_flags.splice(i, 0, input.charCodeAt(ic -1) -65 < 26);}
              +
              +            output.splice(i, 0, n);
              +            i++;
              +        }
              +        if (preserveCase) {
              +            for (i = 0, len = output.length; i < len; i++) {
              +                if (case_flags[i]) {
              +                    output[i] = (String.fromCharCode(output[i]).toUpperCase()).charCodeAt(0);
              +                }
              +            }
              +        }
              +        return this.utf16.encode(output);
              +    };
              +
              +    //** Main encode function **
              +
              +    this.encode = function (input,preserveCase) {
              +        //** Bias adaptation function **
              +
              +        var n, delta, h, b, bias, j, m, q, k, t, ijv, case_flags;
              +
              +        if (preserveCase) {
              +            // Preserve case, step1 of 2: Get a list of the unaltered string
              +            case_flags = this.utf16.decode(input);
              +        }
              +        // Converts the input in UTF-16 to Unicode
              +        input = this.utf16.decode(input.toLowerCase());
              +
              +        var input_length = input.length; // Cache the length
              +
              +        if (preserveCase) {
              +            // Preserve case, step2 of 2: Modify the list to true/false
              +            for (j=0; j < input_length; j++) {
              +                case_flags[j] = input[j] != case_flags[j];
              +            }
              +        }
              +
              +        var output=[];
              +
              +
              +        // Initialize the state: 
              +        n = initial_n;
              +        delta = 0;
              +        bias = initial_bias;
              +
              +        // Handle the basic code points: 
              +        for (j = 0; j < input_length; ++j) {
              +            if ( input[j] < 0x80) {
              +                output.push(
              +                    String.fromCharCode(
              +                        case_flags ? encode_basic(input[j], case_flags[j]) : input[j]
              +                    )
              +                );
              +            }
              +        }
              +
              +        h = b = output.length;
              +
              +        // h is the number of code points that have been handled, b is the
              +        // number of basic code points 
              +
              +        if (b > 0) output.push(delimiter);
              +
              +        // Main encoding loop: 
              +        //
              +        while (h < input_length) {
              +            // All non-basic code points < n have been
              +            // handled already. Find the next larger one: 
              +
              +            for (m = maxint, j = 0; j < input_length; ++j) {
              +                ijv = input[j];
              +                if (ijv >= n && ijv < m) m = ijv;
              +            }
              +
              +            // Increase delta enough to advance the decoder's
              +            // <n,i> state to <m,0>, but guard against overflow: 
              +
              +            if (m - n > Math.floor((maxint - delta) / (h + 1))) {
              +                throw RangeError("punycode_overflow (1)");
              +            }
              +            delta += (m - n) * (h + 1);
              +            n = m;
              +
              +            for (j = 0; j < input_length; ++j) {
              +                ijv = input[j];
              +
              +                if (ijv < n ) {
              +                    if (++delta > maxint) return Error("punycode_overflow(2)");
              +                }
              +
              +                if (ijv == n) {
              +                    // Represent delta as a generalized variable-length integer: 
              +                    for (q = delta, k = base; ; k += base) {
              +                        t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
              +                        if (q < t) break;
              +                        output.push( String.fromCharCode(encode_digit(t + (q - t) % (base - t), 0)) );
              +                        q = Math.floor( (q - t) / (base - t) );
              +                    }
              +                    output.push( String.fromCharCode(encode_digit(q, preserveCase && case_flags[j] ? 1:0 )));
              +                    bias = adapt(delta, h + 1, h == b);
              +                    delta = 0;
              +                    ++h;
              +                }
              +            }
              +
              +            ++delta, ++n;
              +        }
              +        return output.join("");
              +    }
              +
              +    this.ToASCII = function ( domain ) {
              +        var domain_array = domain.split(".");
              +        var out = [];
              +        for (var i=0; i < domain_array.length; ++i) {
              +            var s = domain_array[i];
              +            out.push(
              +                s.match(/[^A-Za-z0-9-]/) ?
              +                "xn--" + punycode.encode(s) :
              +                s
              +            );
              +        }
              +        return out.join(".");
              +    }
              +    this.ToUnicode = function ( domain ) {
              +        var domain_array = domain.split(".");
              +        var out = [];
              +        for (var i=0; i < domain_array.length; ++i) {
              +            var s = domain_array[i];
              +            out.push(
              +                s.match(/^xn--/) ?
              +                punycode.decode(s.slice(4)) :
              +                s
              +            );
              +        }
              +        return out.join(".");
              +    }
              +}();
              \ No newline at end of file
              diff --git a/src/js/lib/rawdeflate.js b/src/js/lib/rawdeflate.js
              new file mode 100755
              index 00000000..a5f04dfb
              --- /dev/null
              +++ b/src/js/lib/rawdeflate.js
              @@ -0,0 +1,23 @@
              +/* zlib.js 2012 - imaya [ https://github.com/imaya/zlib.js ] The MIT License */(function() {'use strict';var n=void 0,u=!0,aa=this;function ba(e,d){var c=e.split("."),f=aa;!(c[0]in f)&&f.execScript&&f.execScript("var "+c[0]);for(var a;c.length&&(a=c.shift());)!c.length&&d!==n?f[a]=d:f=f[a]?f[a]:f[a]={}};var C="undefined"!==typeof Uint8Array&&"undefined"!==typeof Uint16Array&&"undefined"!==typeof Uint32Array&&"undefined"!==typeof DataView;function K(e,d){this.index="number"===typeof d?d:0;this.d=0;this.buffer=e instanceof(C?Uint8Array:Array)?e:new (C?Uint8Array:Array)(32768);if(2*this.buffer.length<=this.index)throw Error("invalid index");this.buffer.length<=this.index&&ca(this)}function ca(e){var d=e.buffer,c,f=d.length,a=new (C?Uint8Array:Array)(f<<1);if(C)a.set(d);else for(c=0;c<f;++c)a[c]=d[c];return e.buffer=a}
              +K.prototype.a=function(e,d,c){var f=this.buffer,a=this.index,b=this.d,k=f[a],m;c&&1<d&&(e=8<d?(L[e&255]<<24|L[e>>>8&255]<<16|L[e>>>16&255]<<8|L[e>>>24&255])>>32-d:L[e]>>8-d);if(8>d+b)k=k<<d|e,b+=d;else for(m=0;m<d;++m)k=k<<1|e>>d-m-1&1,8===++b&&(b=0,f[a++]=L[k],k=0,a===f.length&&(f=ca(this)));f[a]=k;this.buffer=f;this.d=b;this.index=a};K.prototype.finish=function(){var e=this.buffer,d=this.index,c;0<this.d&&(e[d]<<=8-this.d,e[d]=L[e[d]],d++);C?c=e.subarray(0,d):(e.length=d,c=e);return c};
              +var ga=new (C?Uint8Array:Array)(256),M;for(M=0;256>M;++M){for(var R=M,S=R,ha=7,R=R>>>1;R;R>>>=1)S<<=1,S|=R&1,--ha;ga[M]=(S<<ha&255)>>>0}var L=ga;function ja(e){this.buffer=new (C?Uint16Array:Array)(2*e);this.length=0}ja.prototype.getParent=function(e){return 2*((e-2)/4|0)};ja.prototype.push=function(e,d){var c,f,a=this.buffer,b;c=this.length;a[this.length++]=d;for(a[this.length++]=e;0<c;)if(f=this.getParent(c),a[c]>a[f])b=a[c],a[c]=a[f],a[f]=b,b=a[c+1],a[c+1]=a[f+1],a[f+1]=b,c=f;else break;return this.length};
              +ja.prototype.pop=function(){var e,d,c=this.buffer,f,a,b;d=c[0];e=c[1];this.length-=2;c[0]=c[this.length];c[1]=c[this.length+1];for(b=0;;){a=2*b+2;if(a>=this.length)break;a+2<this.length&&c[a+2]>c[a]&&(a+=2);if(c[a]>c[b])f=c[b],c[b]=c[a],c[a]=f,f=c[b+1],c[b+1]=c[a+1],c[a+1]=f;else break;b=a}return{index:e,value:d,length:this.length}};function ka(e,d){this.e=ma;this.f=0;this.input=C&&e instanceof Array?new Uint8Array(e):e;this.c=0;d&&(d.lazy&&(this.f=d.lazy),"number"===typeof d.compressionType&&(this.e=d.compressionType),d.outputBuffer&&(this.b=C&&d.outputBuffer instanceof Array?new Uint8Array(d.outputBuffer):d.outputBuffer),"number"===typeof d.outputIndex&&(this.c=d.outputIndex));this.b||(this.b=new (C?Uint8Array:Array)(32768))}var ma=2,T=[],U;
              +for(U=0;288>U;U++)switch(u){case 143>=U:T.push([U+48,8]);break;case 255>=U:T.push([U-144+400,9]);break;case 279>=U:T.push([U-256+0,7]);break;case 287>=U:T.push([U-280+192,8]);break;default:throw"invalid literal: "+U;}
              +ka.prototype.h=function(){var e,d,c,f,a=this.input;switch(this.e){case 0:c=0;for(f=a.length;c<f;){d=C?a.subarray(c,c+65535):a.slice(c,c+65535);c+=d.length;var b=d,k=c===f,m=n,g=n,p=n,v=n,x=n,l=this.b,h=this.c;if(C){for(l=new Uint8Array(this.b.buffer);l.length<=h+b.length+5;)l=new Uint8Array(l.length<<1);l.set(this.b)}m=k?1:0;l[h++]=m|0;g=b.length;p=~g+65536&65535;l[h++]=g&255;l[h++]=g>>>8&255;l[h++]=p&255;l[h++]=p>>>8&255;if(C)l.set(b,h),h+=b.length,l=l.subarray(0,h);else{v=0;for(x=b.length;v<x;++v)l[h++]=
              +b[v];l.length=h}this.c=h;this.b=l}break;case 1:var q=new K(C?new Uint8Array(this.b.buffer):this.b,this.c);q.a(1,1,u);q.a(1,2,u);var t=na(this,a),w,da,z;w=0;for(da=t.length;w<da;w++)if(z=t[w],K.prototype.a.apply(q,T[z]),256<z)q.a(t[++w],t[++w],u),q.a(t[++w],5),q.a(t[++w],t[++w],u);else if(256===z)break;this.b=q.finish();this.c=this.b.length;break;case ma:var B=new K(C?new Uint8Array(this.b.buffer):this.b,this.c),ra,J,N,O,P,Ia=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],W,sa,X,ta,ea,ia=Array(19),
              +ua,Q,fa,y,va;ra=ma;B.a(1,1,u);B.a(ra,2,u);J=na(this,a);W=oa(this.j,15);sa=pa(W);X=oa(this.i,7);ta=pa(X);for(N=286;257<N&&0===W[N-1];N--);for(O=30;1<O&&0===X[O-1];O--);var wa=N,xa=O,F=new (C?Uint32Array:Array)(wa+xa),r,G,s,Y,E=new (C?Uint32Array:Array)(316),D,A,H=new (C?Uint8Array:Array)(19);for(r=G=0;r<wa;r++)F[G++]=W[r];for(r=0;r<xa;r++)F[G++]=X[r];if(!C){r=0;for(Y=H.length;r<Y;++r)H[r]=0}r=D=0;for(Y=F.length;r<Y;r+=G){for(G=1;r+G<Y&&F[r+G]===F[r];++G);s=G;if(0===F[r])if(3>s)for(;0<s--;)E[D++]=0,
              +H[0]++;else for(;0<s;)A=138>s?s:138,A>s-3&&A<s&&(A=s-3),10>=A?(E[D++]=17,E[D++]=A-3,H[17]++):(E[D++]=18,E[D++]=A-11,H[18]++),s-=A;else if(E[D++]=F[r],H[F[r]]++,s--,3>s)for(;0<s--;)E[D++]=F[r],H[F[r]]++;else for(;0<s;)A=6>s?s:6,A>s-3&&A<s&&(A=s-3),E[D++]=16,E[D++]=A-3,H[16]++,s-=A}e=C?E.subarray(0,D):E.slice(0,D);ea=oa(H,7);for(y=0;19>y;y++)ia[y]=ea[Ia[y]];for(P=19;4<P&&0===ia[P-1];P--);ua=pa(ea);B.a(N-257,5,u);B.a(O-1,5,u);B.a(P-4,4,u);for(y=0;y<P;y++)B.a(ia[y],3,u);y=0;for(va=e.length;y<va;y++)if(Q=
              +e[y],B.a(ua[Q],ea[Q],u),16<=Q){y++;switch(Q){case 16:fa=2;break;case 17:fa=3;break;case 18:fa=7;break;default:throw"invalid code: "+Q;}B.a(e[y],fa,u)}var ya=[sa,W],za=[ta,X],I,Aa,Z,la,Ba,Ca,Da,Ea;Ba=ya[0];Ca=ya[1];Da=za[0];Ea=za[1];I=0;for(Aa=J.length;I<Aa;++I)if(Z=J[I],B.a(Ba[Z],Ca[Z],u),256<Z)B.a(J[++I],J[++I],u),la=J[++I],B.a(Da[la],Ea[la],u),B.a(J[++I],J[++I],u);else if(256===Z)break;this.b=B.finish();this.c=this.b.length;break;default:throw"invalid compression type";}return this.b};
              +function qa(e,d){this.length=e;this.g=d}
              +var Fa=function(){function e(a){switch(u){case 3===a:return[257,a-3,0];case 4===a:return[258,a-4,0];case 5===a:return[259,a-5,0];case 6===a:return[260,a-6,0];case 7===a:return[261,a-7,0];case 8===a:return[262,a-8,0];case 9===a:return[263,a-9,0];case 10===a:return[264,a-10,0];case 12>=a:return[265,a-11,1];case 14>=a:return[266,a-13,1];case 16>=a:return[267,a-15,1];case 18>=a:return[268,a-17,1];case 22>=a:return[269,a-19,2];case 26>=a:return[270,a-23,2];case 30>=a:return[271,a-27,2];case 34>=a:return[272,
              +a-31,2];case 42>=a:return[273,a-35,3];case 50>=a:return[274,a-43,3];case 58>=a:return[275,a-51,3];case 66>=a:return[276,a-59,3];case 82>=a:return[277,a-67,4];case 98>=a:return[278,a-83,4];case 114>=a:return[279,a-99,4];case 130>=a:return[280,a-115,4];case 162>=a:return[281,a-131,5];case 194>=a:return[282,a-163,5];case 226>=a:return[283,a-195,5];case 257>=a:return[284,a-227,5];case 258===a:return[285,a-258,0];default:throw"invalid length: "+a;}}var d=[],c,f;for(c=3;258>=c;c++)f=e(c),d[c]=f[2]<<24|
              +f[1]<<16|f[0];return d}(),Ga=C?new Uint32Array(Fa):Fa;
              +function na(e,d){function c(a,c){var b=a.g,d=[],f=0,e;e=Ga[a.length];d[f++]=e&65535;d[f++]=e>>16&255;d[f++]=e>>24;var g;switch(u){case 1===b:g=[0,b-1,0];break;case 2===b:g=[1,b-2,0];break;case 3===b:g=[2,b-3,0];break;case 4===b:g=[3,b-4,0];break;case 6>=b:g=[4,b-5,1];break;case 8>=b:g=[5,b-7,1];break;case 12>=b:g=[6,b-9,2];break;case 16>=b:g=[7,b-13,2];break;case 24>=b:g=[8,b-17,3];break;case 32>=b:g=[9,b-25,3];break;case 48>=b:g=[10,b-33,4];break;case 64>=b:g=[11,b-49,4];break;case 96>=b:g=[12,b-
              +65,5];break;case 128>=b:g=[13,b-97,5];break;case 192>=b:g=[14,b-129,6];break;case 256>=b:g=[15,b-193,6];break;case 384>=b:g=[16,b-257,7];break;case 512>=b:g=[17,b-385,7];break;case 768>=b:g=[18,b-513,8];break;case 1024>=b:g=[19,b-769,8];break;case 1536>=b:g=[20,b-1025,9];break;case 2048>=b:g=[21,b-1537,9];break;case 3072>=b:g=[22,b-2049,10];break;case 4096>=b:g=[23,b-3073,10];break;case 6144>=b:g=[24,b-4097,11];break;case 8192>=b:g=[25,b-6145,11];break;case 12288>=b:g=[26,b-8193,12];break;case 16384>=
              +b:g=[27,b-12289,12];break;case 24576>=b:g=[28,b-16385,13];break;case 32768>=b:g=[29,b-24577,13];break;default:throw"invalid distance";}e=g;d[f++]=e[0];d[f++]=e[1];d[f++]=e[2];var k,m;k=0;for(m=d.length;k<m;++k)l[h++]=d[k];t[d[0]]++;w[d[3]]++;q=a.length+c-1;x=null}var f,a,b,k,m,g={},p,v,x,l=C?new Uint16Array(2*d.length):[],h=0,q=0,t=new (C?Uint32Array:Array)(286),w=new (C?Uint32Array:Array)(30),da=e.f,z;if(!C){for(b=0;285>=b;)t[b++]=0;for(b=0;29>=b;)w[b++]=0}t[256]=1;f=0;for(a=d.length;f<a;++f){b=
              +m=0;for(k=3;b<k&&f+b!==a;++b)m=m<<8|d[f+b];g[m]===n&&(g[m]=[]);p=g[m];if(!(0<q--)){for(;0<p.length&&32768<f-p[0];)p.shift();if(f+3>=a){x&&c(x,-1);b=0;for(k=a-f;b<k;++b)z=d[f+b],l[h++]=z,++t[z];break}0<p.length?(v=Ha(d,f,p),x?x.length<v.length?(z=d[f-1],l[h++]=z,++t[z],c(v,0)):c(x,-1):v.length<da?x=v:c(v,0)):x?c(x,-1):(z=d[f],l[h++]=z,++t[z])}p.push(f)}l[h++]=256;t[256]++;e.j=t;e.i=w;return C?l.subarray(0,h):l}
              +function Ha(e,d,c){var f,a,b=0,k,m,g,p,v=e.length;m=0;p=c.length;a:for(;m<p;m++){f=c[p-m-1];k=3;if(3<b){for(g=b;3<g;g--)if(e[f+g-1]!==e[d+g-1])continue a;k=b}for(;258>k&&d+k<v&&e[f+k]===e[d+k];)++k;k>b&&(a=f,b=k);if(258===k)break}return new qa(b,d-a)}
              +function oa(e,d){var c=e.length,f=new ja(572),a=new (C?Uint8Array:Array)(c),b,k,m,g,p;if(!C)for(g=0;g<c;g++)a[g]=0;for(g=0;g<c;++g)0<e[g]&&f.push(g,e[g]);b=Array(f.length/2);k=new (C?Uint32Array:Array)(f.length/2);if(1===b.length)return a[f.pop().index]=1,a;g=0;for(p=f.length/2;g<p;++g)b[g]=f.pop(),k[g]=b[g].value;m=Ja(k,k.length,d);g=0;for(p=b.length;g<p;++g)a[b[g].index]=m[g];return a}
              +function Ja(e,d,c){function f(a){var b=g[a][p[a]];b===d?(f(a+1),f(a+1)):--k[b];++p[a]}var a=new (C?Uint16Array:Array)(c),b=new (C?Uint8Array:Array)(c),k=new (C?Uint8Array:Array)(d),m=Array(c),g=Array(c),p=Array(c),v=(1<<c)-d,x=1<<c-1,l,h,q,t,w;a[c-1]=d;for(h=0;h<c;++h)v<x?b[h]=0:(b[h]=1,v-=x),v<<=1,a[c-2-h]=(a[c-1-h]/2|0)+d;a[0]=b[0];m[0]=Array(a[0]);g[0]=Array(a[0]);for(h=1;h<c;++h)a[h]>2*a[h-1]+b[h]&&(a[h]=2*a[h-1]+b[h]),m[h]=Array(a[h]),g[h]=Array(a[h]);for(l=0;l<d;++l)k[l]=c;for(q=0;q<a[c-1];++q)m[c-
              +1][q]=e[q],g[c-1][q]=q;for(l=0;l<c;++l)p[l]=0;1===b[c-1]&&(--k[0],++p[c-1]);for(h=c-2;0<=h;--h){t=l=0;w=p[h+1];for(q=0;q<a[h];q++)t=m[h+1][w]+m[h+1][w+1],t>e[l]?(m[h][q]=t,g[h][q]=d,w+=2):(m[h][q]=e[l],g[h][q]=l,++l);p[h]=0;1===b[h]&&f(h)}return k}
              +function pa(e){var d=new (C?Uint16Array:Array)(e.length),c=[],f=[],a=0,b,k,m,g;b=0;for(k=e.length;b<k;b++)c[e[b]]=(c[e[b]]|0)+1;b=1;for(k=16;b<=k;b++)f[b]=a,a+=c[b]|0,a<<=1;b=0;for(k=e.length;b<k;b++){a=f[e[b]];f[e[b]]+=1;m=d[b]=0;for(g=e[b];m<g;m++)d[b]=d[b]<<1|a&1,a>>>=1}return d};ba("Zlib.RawDeflate",ka);ba("Zlib.RawDeflate.prototype.compress",ka.prototype.h);var Ka={NONE:0,FIXED:1,DYNAMIC:ma},V,La,$,Ma;if(Object.keys)V=Object.keys(Ka);else for(La in V=[],$=0,Ka)V[$++]=La;$=0;for(Ma=V.length;$<Ma;++$)La=V[$],ba("Zlib.RawDeflate.CompressionType."+La,Ka[La]);}).call(this);
              diff --git a/src/js/lib/rawinflate.js b/src/js/lib/rawinflate.js
              new file mode 100755
              index 00000000..75ea813c
              --- /dev/null
              +++ b/src/js/lib/rawinflate.js
              @@ -0,0 +1,14 @@
              +/* zlib.js 2012 - imaya [ https://github.com/imaya/zlib.js ] The MIT License */(function() {'use strict';var l=this;function p(b,e){var a=b.split("."),c=l;!(a[0]in c)&&c.execScript&&c.execScript("var "+a[0]);for(var d;a.length&&(d=a.shift());)!a.length&&void 0!==e?c[d]=e:c=c[d]?c[d]:c[d]={}};var q="undefined"!==typeof Uint8Array&&"undefined"!==typeof Uint16Array&&"undefined"!==typeof Uint32Array&&"undefined"!==typeof DataView;function t(b){var e=b.length,a=0,c=Number.POSITIVE_INFINITY,d,f,g,h,k,m,r,n,s,J;for(n=0;n<e;++n)b[n]>a&&(a=b[n]),b[n]<c&&(c=b[n]);d=1<<a;f=new (q?Uint32Array:Array)(d);g=1;h=0;for(k=2;g<=a;){for(n=0;n<e;++n)if(b[n]===g){m=0;r=h;for(s=0;s<g;++s)m=m<<1|r&1,r>>=1;J=g<<16|n;for(s=m;s<d;s+=k)f[s]=J;++h}++g;h<<=1;k<<=1}return[f,a,c]};function u(b,e){this.g=[];this.h=32768;this.c=this.f=this.d=this.k=0;this.input=q?new Uint8Array(b):b;this.l=!1;this.i=v;this.q=!1;if(e||!(e={}))e.index&&(this.d=e.index),e.bufferSize&&(this.h=e.bufferSize),e.bufferType&&(this.i=e.bufferType),e.resize&&(this.q=e.resize);switch(this.i){case w:this.a=32768;this.b=new (q?Uint8Array:Array)(32768+this.h+258);break;case v:this.a=0;this.b=new (q?Uint8Array:Array)(this.h);this.e=this.v;this.m=this.s;this.j=this.t;break;default:throw Error("invalid inflate mode");
              +}}var w=0,v=1;
              +u.prototype.u=function(){for(;!this.l;){var b=x(this,3);b&1&&(this.l=!0);b>>>=1;switch(b){case 0:var e=this.input,a=this.d,c=this.b,d=this.a,f=e.length,g=void 0,h=void 0,k=c.length,m=void 0;this.c=this.f=0;if(a+1>=f)throw Error("invalid uncompressed block header: LEN");g=e[a++]|e[a++]<<8;if(a+1>=f)throw Error("invalid uncompressed block header: NLEN");h=e[a++]|e[a++]<<8;if(g===~h)throw Error("invalid uncompressed block header: length verify");if(a+g>e.length)throw Error("input buffer is broken");switch(this.i){case w:for(;d+
              +g>c.length;){m=k-d;g-=m;if(q)c.set(e.subarray(a,a+m),d),d+=m,a+=m;else for(;m--;)c[d++]=e[a++];this.a=d;c=this.e();d=this.a}break;case v:for(;d+g>c.length;)c=this.e({o:2});break;default:throw Error("invalid inflate mode");}if(q)c.set(e.subarray(a,a+g),d),d+=g,a+=g;else for(;g--;)c[d++]=e[a++];this.d=a;this.a=d;this.b=c;break;case 1:this.j(y,z);break;case 2:A(this);break;default:throw Error("unknown BTYPE: "+b);}}return this.m()};
              +var B=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],C=q?new Uint16Array(B):B,D=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,258,258],E=q?new Uint16Array(D):D,F=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0],G=q?new Uint8Array(F):F,H=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577],I=q?new Uint16Array(H):H,K=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,
              +13],L=q?new Uint8Array(K):K,M=new (q?Uint8Array:Array)(288),N,O;N=0;for(O=M.length;N<O;++N)M[N]=143>=N?8:255>=N?9:279>=N?7:8;var y=t(M),P=new (q?Uint8Array:Array)(30),Q,R;Q=0;for(R=P.length;Q<R;++Q)P[Q]=5;var z=t(P);function x(b,e){for(var a=b.f,c=b.c,d=b.input,f=b.d,g=d.length,h;c<e;){if(f>=g)throw Error("input buffer is broken");a|=d[f++]<<c;c+=8}h=a&(1<<e)-1;b.f=a>>>e;b.c=c-e;b.d=f;return h}
              +function S(b,e){for(var a=b.f,c=b.c,d=b.input,f=b.d,g=d.length,h=e[0],k=e[1],m,r;c<k&&!(f>=g);)a|=d[f++]<<c,c+=8;m=h[a&(1<<k)-1];r=m>>>16;b.f=a>>r;b.c=c-r;b.d=f;return m&65535}
              +function A(b){function e(a,b,c){var e,d=this.p,f,g;for(g=0;g<a;)switch(e=S(this,b),e){case 16:for(f=3+x(this,2);f--;)c[g++]=d;break;case 17:for(f=3+x(this,3);f--;)c[g++]=0;d=0;break;case 18:for(f=11+x(this,7);f--;)c[g++]=0;d=0;break;default:d=c[g++]=e}this.p=d;return c}var a=x(b,5)+257,c=x(b,5)+1,d=x(b,4)+4,f=new (q?Uint8Array:Array)(C.length),g,h,k,m;for(m=0;m<d;++m)f[C[m]]=x(b,3);if(!q){m=d;for(d=f.length;m<d;++m)f[C[m]]=0}g=t(f);h=new (q?Uint8Array:Array)(a);k=new (q?Uint8Array:Array)(c);b.p=0;
              +b.j(t(e.call(b,a,g,h)),t(e.call(b,c,g,k)))}u.prototype.j=function(b,e){var a=this.b,c=this.a;this.n=b;for(var d=a.length-258,f,g,h,k;256!==(f=S(this,b));)if(256>f)c>=d&&(this.a=c,a=this.e(),c=this.a),a[c++]=f;else{g=f-257;k=E[g];0<G[g]&&(k+=x(this,G[g]));f=S(this,e);h=I[f];0<L[f]&&(h+=x(this,L[f]));c>=d&&(this.a=c,a=this.e(),c=this.a);for(;k--;)a[c]=a[c++-h]}for(;8<=this.c;)this.c-=8,this.d--;this.a=c};
              +u.prototype.t=function(b,e){var a=this.b,c=this.a;this.n=b;for(var d=a.length,f,g,h,k;256!==(f=S(this,b));)if(256>f)c>=d&&(a=this.e(),d=a.length),a[c++]=f;else{g=f-257;k=E[g];0<G[g]&&(k+=x(this,G[g]));f=S(this,e);h=I[f];0<L[f]&&(h+=x(this,L[f]));c+k>d&&(a=this.e(),d=a.length);for(;k--;)a[c]=a[c++-h]}for(;8<=this.c;)this.c-=8,this.d--;this.a=c};
              +u.prototype.e=function(){var b=new (q?Uint8Array:Array)(this.a-32768),e=this.a-32768,a,c,d=this.b;if(q)b.set(d.subarray(32768,b.length));else{a=0;for(c=b.length;a<c;++a)b[a]=d[a+32768]}this.g.push(b);this.k+=b.length;if(q)d.set(d.subarray(e,e+32768));else for(a=0;32768>a;++a)d[a]=d[e+a];this.a=32768;return d};
              +u.prototype.v=function(b){var e,a=this.input.length/this.d+1|0,c,d,f,g=this.input,h=this.b;b&&("number"===typeof b.o&&(a=b.o),"number"===typeof b.r&&(a+=b.r));2>a?(c=(g.length-this.d)/this.n[2],f=258*(c/2)|0,d=f<h.length?h.length+f:h.length<<1):d=h.length*a;q?(e=new Uint8Array(d),e.set(h)):e=h;return this.b=e};
              +u.prototype.m=function(){var b=0,e=this.b,a=this.g,c,d=new (q?Uint8Array:Array)(this.k+(this.a-32768)),f,g,h,k;if(0===a.length)return q?this.b.subarray(32768,this.a):this.b.slice(32768,this.a);f=0;for(g=a.length;f<g;++f){c=a[f];h=0;for(k=c.length;h<k;++h)d[b++]=c[h]}f=32768;for(g=this.a;f<g;++f)d[b++]=e[f];this.g=[];return this.buffer=d};
              +u.prototype.s=function(){var b,e=this.a;q?this.q?(b=new Uint8Array(e),b.set(this.b.subarray(0,e))):b=this.b.subarray(0,e):(this.b.length>e&&(this.b.length=e),b=this.b);return this.buffer=b};p("Zlib.RawInflate",u);p("Zlib.RawInflate.prototype.decompress",u.prototype.u);var T={ADAPTIVE:v,BLOCK:w},U,V,W,X;if(Object.keys)U=Object.keys(T);else for(V in U=[],W=0,T)U[W++]=V;W=0;for(X=U.length;W<X;++W)V=U[W],p("Zlib.RawInflate.BufferType."+V,T[V]);}).call(this);
              diff --git a/src/js/lib/snowfall.jquery.js b/src/js/lib/snowfall.jquery.js
              new file mode 100755
              index 00000000..c347a313
              --- /dev/null
              +++ b/src/js/lib/snowfall.jquery.js
              @@ -0,0 +1,409 @@
              +/** @license
              +========================================================================
              +  Snowfall jquery plugin version 1.51 Dec 2nd 2012
              +  
              +  Licensed under the Apache License, Version 2.0 (the "License");
              +  you may not use this file except in compliance with the License.
              +  You may obtain a copy of the License at
              +
              +     http://www.apache.org/licenses/LICENSE-2.0
              +
              +     Unless required by applicable law or agreed to in writing, software
              +     distributed under the License is distributed on an "AS IS" BASIS,
              +     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
              +     See the License for the specific language governing permissions and
              +     limitations under the License.
              +  
              +  Developed by Jason Brown for any bugs or questions email me at loktar69@hotmail
              +  info on the plugin is located on Somethinghitme.com
              +*/
              +
              +/*
              +  Version 1.51 Dec 2nd 2012
              +  // fixed bug where snow collection didn't happen if a valid doctype was declared.
              +
              +  Version 1.5 Oct 5th 2011
              +  Added collecting snow! Uses the canvas element to collect snow. In order to initialize snow collection use the following
              +
              +  $(document).snowfall({collection : 'element'});
              +
              +  element = any valid jquery selector.
              +
              +  The plugin then creates a canvas above every element that matches the selector, and collects the snow. If there are a varrying amount of elements the
              +  flakes get assigned a random one on start they will collide.
              +
              +  Version 1.4 Dec 8th 2010
              +  Fixed issues (I hope) with scroll bars flickering due to snow going over the edge of the screen.
              +  Added round snowflakes via css, will not work for any version of IE. - Thanks to Luke Barker of http://www.infinite-eye.com/
              +  Added shadows as an option via css again will not work with IE. The idea behind shadows, is to show flakes on lighter colored web sites - Thanks Yutt
              +
              +  Version 1.3.1 Nov 25th 2010
              +  Updated script that caused flakes not to show at all if plugin was initialized with no options, also added the fixes that Han Bongers suggested
              +
              +  Developed by Jason Brown for any bugs or questions email me at loktar69@hotmail
              +  info on the plugin is located on Somethinghitme.com
              +
              +  values for snow options are
              +
              +  flakeCount,
              +  flakeColor,
              +  flakeIndex,
              +  minSize,
              +  maxSize,
              +  minSpeed,
              +  maxSpeed,
              +  round,      true or false, makes the snowflakes rounded if the browser supports it.
              +  shadow      true or false, gives the snowflakes a shadow if the browser supports it.
              +
              +  Example Usage :
              +  $(document).snowfall({flakeCount : 100, maxSpeed : 10});
              +
              +  -or-
              +
              +  $('#element').snowfall({flakeCount : 800, maxSpeed : 5, maxSize : 5});
              +
              +  -or with defaults-
              +
              +  $(document).snowfall();
              +
              +  - To clear -
              +  $('#element').snowfall('clear');
              +*/
              +
              +// requestAnimationFrame polyfill from https://github.com/darius/requestAnimationFrame
              +if (!Date.now)
              +    Date.now = function() { return new Date().getTime(); };
              +
              +(function() {
              +    'use strict';
              +
              +    var vendors = ['webkit', 'moz'];
              +    for (var i = 0; i < vendors.length && !window.requestAnimationFrame; ++i) {
              +        var vp = vendors[i];
              +        window.requestAnimationFrame = window[vp+'RequestAnimationFrame'];
              +        window.cancelAnimationFrame = (window[vp+'CancelAnimationFrame']
              +                                   || window[vp+'CancelRequestAnimationFrame']);
              +    }
              +    if (/iP(ad|hone|od).*OS 6/.test(window.navigator.userAgent) // iOS6 is buggy
              +        || !window.requestAnimationFrame || !window.cancelAnimationFrame) {
              +        var lastTime = 0;
              +        window.requestAnimationFrame = function(callback) {
              +            var now = Date.now();
              +            var nextTime = Math.max(lastTime + 16, now);
              +            return setTimeout(function() { callback(lastTime = nextTime); },
              +                              nextTime - now);
              +        };
              +        window.cancelAnimationFrame = clearTimeout;
              +    }
              +}());
              +
              +(function($){
              +    $.snowfall = function(element, options){
              +        var flakes = [],
              +            defaults = {
              +                flakeCount : 35,
              +                flakeColor : '#ffffff',
              +				flakePosition: 'absolute',
              +                flakeIndex: 999999,
              +                minSize : 1,
              +                maxSize : 2,
              +                minSpeed : 1,
              +                maxSpeed : 5,
              +                round : false,
              +                shadow : false,
              +                collection : false,
              +                collectionHeight : 40,
              +                deviceorientation : false
              +            },
              +            options = $.extend(defaults, options),
              +            random = function random(min, max){
              +                return Math.round(min + Math.random()*(max-min));
              +            };
              +
              +            $(element).data("snowfall", this);
              +
              +            // Snow flake object
              +            function Flake(_x, _y, _size, _speed){
              +                // Flake properties
              +                this.x  = _x;
              +                this.y  = _y;
              +                this.size = _size;
              +                this.speed = _speed;
              +                this.step = 0;
              +                this.stepSize = random(1,10) / 100;
              +
              +                if(options.collection){
              +                    this.target = canvasCollection[random(0,canvasCollection.length-1)];
              +                }
              +
              +                var flakeMarkup = null;
              +
              +                if(options.image){
              +                    flakeMarkup = document.createElement("img");
              +                    flakeMarkup.src = options.image;
              +                }else{
              +                    flakeMarkup = document.createElement("div");
              +                    $(flakeMarkup).css({'background' : options.flakeColor});
              +                }
              +
              +                $(flakeMarkup).attr({
              +                    'class': 'snowfall-flakes', 
              +                }).css({
              +                    'width' : this.size, 
              +                    'height' : this.size, 
              +                    'position' : options.flakePosition, 
              +                    'top' : this.y, 
              +                    'left' : this.x, 
              +                    'fontSize' : 0, 
              +                    'zIndex' : options.flakeIndex
              +                });
              +
              +                if($(element).get(0).tagName === $(document).get(0).tagName){
              +                    $('body').append($(flakeMarkup));
              +                    element = $('body');
              +                }else{
              +                    $(element).append($(flakeMarkup));
              +                }
              +
              +                this.element = flakeMarkup;
              +
              +                // Update function, used to update the snow flakes, and checks current snowflake against bounds
              +                this.update = function(){
              +                    this.y += this.speed;
              +
              +                    if(this.y > (elHeight) - (this.size  + 6)){
              +                        this.reset();
              +                    }
              +
              +                    this.element.style.top = this.y + 'px';
              +                    this.element.style.left = this.x + 'px';
              +
              +                    this.step += this.stepSize;
              +
              +                    if (doRatio === false) {
              +                        this.x += Math.cos(this.step);
              +                    } else {
              +                        this.x += (doRatio + Math.cos(this.step));
              +                    }
              +
              +                    // Pileup check
              +                    if(options.collection){
              +                        if(this.x > this.target.x && this.x < this.target.width + this.target.x && this.y > this.target.y && this.y < this.target.height + this.target.y){
              +                            var ctx = this.target.element.getContext("2d"),
              +                                curX = this.x - this.target.x,
              +                                curY = this.y - this.target.y,
              +                                colData = this.target.colData;
              +
              +                                if(colData[parseInt(curX)][parseInt(curY+this.speed+this.size)] !== undefined || curY+this.speed+this.size > this.target.height){
              +                                    if(curY+this.speed+this.size > this.target.height){
              +                                        while(curY+this.speed+this.size > this.target.height && this.speed > 0){
              +                                            this.speed *= .5;
              +                                        }
              +
              +                                        ctx.fillStyle = "#fff";
              +										ctx.shadowOffsetX = 1;
              +										ctx.shadowOffsetY = 1;
              +										ctx.shadowColor = "#000";
              +										ctx.shadowBlur = 1;
              +										
              +                                        if(colData[parseInt(curX)][parseInt(curY+this.speed+this.size)] == undefined){
              +											// console.log("1");
              +                                            colData[parseInt(curX)][parseInt(curY+this.speed+this.size)] = 1;
              +                                            //ctx.fillRect(curX, (curY)+this.speed+this.size, this.size, this.size);
              +											
              +											ctx.beginPath();
              +											ctx.arc(curX, curY+this.speed+this.size, this.size / 2, 0, Math.PI * 2, true);
              +											ctx.closePath();
              +											ctx.fill();
              +											
              +                                        }else{
              +											// console.log("2");
              +                                            colData[parseInt(curX)][parseInt(curY+this.speed)] = 1;
              +                                            //ctx.fillRect(curX, curY+this.speed, this.size, this.size);
              +											
              +											// ctx.fillStyle = "#f00";
              +											ctx.beginPath();
              +											ctx.arc(curX, curY+this.speed+this.size, this.size, 0, Math.PI * 2, true);
              +											ctx.closePath();
              +											ctx.fill();
              +                                        }
              +                                        this.reset();
              +                                    }else{
              +                                        // flow to the sides
              +                                        this.speed = 1;
              +                                        this.stepSize = 0;
              +										
              +										// console.log("3");
              +
              +                                        if(parseInt(curX)+1 < this.target.width && colData[parseInt(curX)+1][parseInt(curY)+1] == undefined ){
              +                                            // go left
              +                                            this.x++;
              +                                        }else if(parseInt(curX)-1 > 0 && colData[parseInt(curX)-1][parseInt(curY)+1] == undefined ){
              +                                            // go right
              +                                            this.x--;
              +                                        }else{
              +                                            //stop
              +                                            ctx.fillStyle = "#fff";
              +											ctx.shadowOffsetX = -4;
              +											ctx.shadowOffsetY = -4;
              +											ctx.shadowColor = "#000";
              +											ctx.shadowBlur = 4;
              +                                            //ctx.fillRect(curX, curY, this.size, this.size);
              +											
              +											ctx.beginPath();
              +											ctx.arc(curX, curY+this.speed+this.size, this.size, 0, Math.PI * 2, true);
              +											ctx.closePath();
              +											ctx.fill();
              +											
              +                                            colData[parseInt(curX)][parseInt(curY)] = 1;
              +                                            this.reset();
              +                                        }
              +                                    }
              +                                }
              +                        }
              +                    }
              +
              +                    if(this.x + this.size > (elWidth) - widthOffset || this.x < widthOffset){
              +                        this.reset();
              +                    }
              +                }
              +
              +                // Resets the snowflake once it reaches one of the bounds set
              +                this.reset = function(){
              +                    this.y = 0;
              +                    this.x = random(widthOffset, elWidth - widthOffset);
              +                    this.stepSize = random(1,10) / 100;
              +                    this.size = random((options.minSize * 100), (options.maxSize * 100)) / 100;
              +                    this.element.style.width = this.size + 'px';
              +                    this.element.style.height = this.size + 'px';
              +                    this.speed = random(options.minSpeed, options.maxSpeed);
              +                }
              +            }
              +
              +            // local vars
              +            var i = 0,
              +                elHeight = $(element).height(),
              +                elWidth = $(element).width(),
              +                widthOffset = 0,
              +                snowTimeout = 0;
              +
              +            // Collection Piece ******************************
              +            if(options.collection !== false){
              +                var testElem = document.createElement('canvas');
              +                if(!!(testElem.getContext && testElem.getContext('2d'))){
              +                    var canvasCollection = [],
              +                        elements = $(options.collection),
              +                        collectionHeight = options.collectionHeight;
              +
              +                    for(var i =0; i < elements.length; i++){
              +                            var bounds = elements[i].getBoundingClientRect(),
              +                                $canvas = $('<canvas/>',
              +                                    {
              +                                        'class' : 'snowfall-canvas'
              +                                    }),
              +                                collisionData = [];
              +
              +                            if(bounds.top-collectionHeight > 0){
              +                                $('body').append($canvas);
              +
              +                                $canvas.css({
              +                                    'position' : options.flakePosition,
              +                                    'left'     : bounds.left + 'px',
              +                                    'top'      : bounds.top-collectionHeight + 'px'
              +                                })
              +                                .prop({
              +                                    width: bounds.width,
              +                                    height: collectionHeight
              +                                });
              +
              +                                for(var w = 0; w < bounds.width; w++){
              +                                    collisionData[w] = [];
              +                                }
              +
              +                                canvasCollection.push({
              +                                    element : $canvas.get(0), 
              +                                    x : bounds.left, 
              +                                    y : bounds.top-collectionHeight, 
              +                                    width : bounds.width, 
              +                                    height: collectionHeight, 
              +                                    colData : collisionData
              +                                });
              +                            }
              +                    }
              +                }else{
              +                    // Canvas element isnt supported
              +                    options.collection = false;
              +                }
              +            }
              +            // ************************************************
              +
              +            // This will reduce the horizontal scroll bar from displaying, when the effect is applied to the whole page
              +            if($(element).get(0).tagName === $(document).get(0).tagName){
              +                widthOffset = 25;
              +            }
              +
              +            // Bind the window resize event so we can get the innerHeight again
              +            $(window).bind("resize", function(){
              +                elHeight = $(element)[0].clientHeight;
              +                elWidth = $(element)[0].offsetWidth;
              +            });
              +
              +
              +            // initialize the flakes
              +            for(i = 0; i < options.flakeCount; i+=1){
              +                flakes.push(new Flake(random(widthOffset,elWidth - widthOffset), random(0, elHeight), random((options.minSize * 100), (options.maxSize * 100)) / 100, random(options.minSpeed, options.maxSpeed)));
              +            }
              +
              +            // This adds the style to make the snowflakes round via border radius property
              +            if(options.round){
              +                $('.snowfall-flakes').css({'-moz-border-radius' : options.maxSize, '-webkit-border-radius' : options.maxSize, 'border-radius' : options.maxSize});
              +            }
              +
              +            // This adds shadows just below the snowflake so they pop a bit on lighter colored web pages
              +            if(options.shadow){
              +                $('.snowfall-flakes').css({'-moz-box-shadow' : '1px 1px 1px #555', '-webkit-box-shadow' : '1px 1px 1px #555', 'box-shadow' : '1px 1px 1px #555'});
              +            }
              +
              +            // On newer Macbooks Snowflakes will fall based on deviceorientation
              +            var doRatio = false;
              +            if (options.deviceorientation) {
              +                $(window).bind('deviceorientation', function(event) {
              +                    doRatio = event.originalEvent.gamma * 0.1;
              +                });
              +            }
              +
              +            // this controls flow of the updating snow
              +            function snow(){
              +                for( i = 0; i < flakes.length; i += 1){
              +                    flakes[i].update();
              +                }
              +
              +                snowTimeout = requestAnimationFrame(function(){snow()});
              +            }
              +
              +            snow();
              +
              +            // clears the snowflakes
              +            this.clear = function(){
              +                $('.snowfall-canvas').remove();
              +                $(element).children('.snowfall-flakes').remove();
              +                cancelAnimationFrame(snowTimeout);
              +            }
              +    };
              +
              +    // Initialize the options and the plugin
              +    $.fn.snowfall = function(options){
              +        if(typeof(options) == "object" || options == undefined){
              +                 return this.each(function(i){
              +                    (new $.snowfall(this, options));
              +                });
              +        }else if (typeof(options) == "string") {
              +            return this.each(function(i){
              +                var snow = $(this).data('snowfall');
              +                if(snow){
              +                    snow.clear();
              +                }
              +            });
              +        }
              +    };
              +})(jQuery);
              \ No newline at end of file
              diff --git a/src/js/lib/split.js b/src/js/lib/split.js
              new file mode 100755
              index 00000000..87f08a49
              --- /dev/null
              +++ b/src/js/lib/split.js
              @@ -0,0 +1,375 @@
              +/** @license
              +========================================================================
              +  Split.js v1.0.7
              +  Copyright (c) 2015 Nathan Cahill
              +
              +  Permission is hereby granted, free of charge, to any person obtaining a copy
              +  of this software and associated documentation files (the "Software"), to deal
              +  in the Software without restriction, including without limitation the rights
              +  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
              +  copies of the Software, and to permit persons to whom the Software is
              +  furnished to do so, subject to the following conditions:
              +  
              +  The above copyright notice and this permission notice shall be included in
              +  all copies or substantial portions of the Software.
              +  
              +  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
              +  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
              +  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
              +  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
              +  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
              +  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
              +  THE SOFTWARE.
              +*/
              +
              +'use strict';
              +
              +(function() {
              +
              +var global = this
              +  , addEventListener = 'addEventListener'
              +  , removeEventListener = 'removeEventListener'
              +  , getBoundingClientRect = 'getBoundingClientRect'
              +  , isIE8 = global.attachEvent && !global[addEventListener]
              +  , document = global.document
              +
              +  , calc = (function () {
              +        var el
              +          , prefixes = ["", "-webkit-", "-moz-", "-o-"]
              +
              +        for (var i = 0; i < prefixes.length; i++) {
              +            el = document.createElement('div')
              +            el.style.cssText = "width:" + prefixes[i] + "calc(9px)"
              +
              +            if (el.style.length) {
              +                return prefixes[i] + "calc"
              +            }
              +        }
              +    })()
              +  , elementOrSelector = function (el) {
              +        if (typeof el === 'string' || el instanceof String) {
              +            return document.querySelector(el)
              +        } else {
              +            return el
              +        }
              +    }
              +
              +  , Split = function (ids, options) {
              +    var dimension
              +      , i
              +      , clientDimension
              +      , clientAxis
              +      , position
              +      , gutterClass
              +      , paddingA
              +      , paddingB
              +      , pairs = []
              +
              +    // Set defaults
              +
              +    options = typeof options !== 'undefined' ?  options : {}
              +
              +    if (typeof options.gutterSize === 'undefined') options.gutterSize = 10
              +    if (typeof options.minSize === 'undefined') options.minSize = 100
              +    if (typeof options.snapOffset === 'undefined') options.snapOffset = 30
              +    if (typeof options.direction === 'undefined') options.direction = 'horizontal'
              +
              +    if (options.direction == 'horizontal') {
              +        dimension = 'width'
              +        clientDimension = 'clientWidth'
              +        clientAxis = 'clientX'
              +        position = 'left'
              +        gutterClass = 'gutter gutter-horizontal'
              +        paddingA = 'paddingLeft'
              +        paddingB = 'paddingRight'
              +        if (!options.cursor) options.cursor = 'ew-resize'
              +    } else if (options.direction == 'vertical') {
              +        dimension = 'height'
              +        clientDimension = 'clientHeight'
              +        clientAxis = 'clientY'
              +        position = 'top'
              +        gutterClass = 'gutter gutter-vertical'
              +        paddingA = 'paddingTop'
              +        paddingB = 'paddingBottom'
              +        if (!options.cursor) options.cursor = 'ns-resize'
              +    }
              +
              +    // Event listeners for drag events, bound to a pair object.
              +    // Calculate the pair's position and size when dragging starts.
              +    // Prevent selection on start and re-enable it when done.
              +
              +    var startDragging = function (e) {
              +            var self = this
              +              , a = self.a
              +              , b = self.b
              +
              +            if (!self.dragging && options.onDragStart) {
              +                options.onDragStart()
              +            }
              +
              +            e.preventDefault()
              +
              +            self.dragging = true
              +            self.move = drag.bind(self)
              +            self.stop = stopDragging.bind(self)
              +
              +            global[addEventListener]('mouseup', self.stop)
              +            global[addEventListener]('touchend', self.stop)
              +            global[addEventListener]('touchcancel', self.stop)
              +
              +            self.parent[addEventListener]('mousemove', self.move)
              +            self.parent[addEventListener]('touchmove', self.move)
              +
              +            a[addEventListener]('selectstart', preventSelection)
              +            a[addEventListener]('dragstart', preventSelection)
              +            b[addEventListener]('selectstart', preventSelection)
              +            b[addEventListener]('dragstart', preventSelection)
              +
              +            a.style.userSelect = 'none'
              +            a.style.webkitUserSelect = 'none'
              +            a.style.MozUserSelect = 'none'
              +            a.style.pointerEvents = 'none'
              +
              +            b.style.userSelect = 'none'
              +            b.style.webkitUserSelect = 'none'
              +            b.style.MozUserSelect = 'none'
              +            b.style.pointerEvents = 'none'
              +
              +            self.gutter.style.cursor = options.cursor
              +            self.parent.style.cursor = options.cursor
              +
              +            calculateSizes.call(self)
              +        }
              +      , stopDragging = function () {
              +            var self = this
              +              , a = self.a
              +              , b = self.b
              +
              +            if (self.dragging && options.onDragEnd) {
              +                options.onDragEnd()
              +            }
              +
              +            self.dragging = false
              +
              +            global[removeEventListener]('mouseup', self.stop)
              +            global[removeEventListener]('touchend', self.stop)
              +            global[removeEventListener]('touchcancel', self.stop)
              +
              +            self.parent[removeEventListener]('mousemove', self.move)
              +            self.parent[removeEventListener]('touchmove', self.move)
              +
              +            delete self.stop
              +            delete self.move
              +
              +            a[removeEventListener]('selectstart', preventSelection)
              +            a[removeEventListener]('dragstart', preventSelection)
              +            b[removeEventListener]('selectstart', preventSelection)
              +            b[removeEventListener]('dragstart', preventSelection)
              +
              +            a.style.userSelect = ''
              +            a.style.webkitUserSelect = ''
              +            a.style.MozUserSelect = ''
              +            a.style.pointerEvents = ''
              +
              +            b.style.userSelect = ''
              +            b.style.webkitUserSelect = ''
              +            b.style.MozUserSelect = ''
              +            b.style.pointerEvents = ''
              +
              +            self.gutter.style.cursor = ''
              +            self.parent.style.cursor = ''
              +        }
              +      , drag = function (e) {
              +            var offset
              +
              +            if (!this.dragging) return
              +
              +            // Get the relative position of the event from the first side of the
              +            // pair.
              +
              +            if ('touches' in e) {
              +                offset = e.touches[0][clientAxis] - this.start
              +            } else {
              +                offset = e[clientAxis] - this.start
              +            }
              +
              +            // If within snapOffset of min or max, set offset to min or max
              +
              +            if (offset <=  this.aMin + options.snapOffset) {
              +                offset = this.aMin
              +            } else if (offset >= this.size - this.bMin - options.snapOffset) {
              +                offset = this.size - this.bMin
              +            }
              +
              +            adjust.call(this, offset)
              +
              +            if (options.onDrag) {
              +                options.onDrag()
              +            }
              +        }
              +      , calculateSizes = function () {
              +            // Calculate the pairs size, and percentage of the parent size
              +            var computedStyle = global.getComputedStyle(this.parent)
              +              , parentSize = this.parent[clientDimension] - parseFloat(computedStyle[paddingA]) - parseFloat(computedStyle[paddingB])
              +
              +            this.size = this.a[getBoundingClientRect]()[dimension] + this.b[getBoundingClientRect]()[dimension] + this.aGutterSize + this.bGutterSize
              +            this.percentage = Math.min(this.size / parentSize * 100, 100)
              +            this.start = this.a[getBoundingClientRect]()[position]
              +        }
              +      , adjust = function (offset) {
              +            // A size is the same as offset. B size is total size - A size.
              +            // Both sizes are calculated from the initial parent percentage.
              +
              +            this.a.style[dimension] = calc + '(' + (offset / this.size * this.percentage) + '% - ' + this.aGutterSize + 'px)'
              +            this.b.style[dimension] = calc + '(' + (this.percentage - (offset / this.size * this.percentage)) + '% - ' + this.bGutterSize + 'px)'
              +        }
              +      , fitMin = function () {
              +            var self = this
              +              , a = self.a
              +              , b = self.b
              +
              +            if (a[getBoundingClientRect]()[dimension] < self.aMin) {
              +                a.style[dimension] = (self.aMin - self.aGutterSize) + 'px'
              +                b.style[dimension] = (self.size - self.aMin - self.aGutterSize) + 'px'
              +            } else if (b[getBoundingClientRect]()[dimension] < self.bMin) {
              +                a.style[dimension] = (self.size - self.bMin - self.bGutterSize) + 'px'
              +                b.style[dimension] = (self.bMin - self.bGutterSize) + 'px'
              +            }
              +        }
              +      , fitMinReverse = function () {
              +            var self = this
              +              , a = self.a
              +              , b = self.b
              +
              +            if (b[getBoundingClientRect]()[dimension] < self.bMin) {
              +                a.style[dimension] = (self.size - self.bMin - self.bGutterSize) + 'px'
              +                b.style[dimension] = (self.bMin - self.bGutterSize) + 'px'
              +            } else if (a[getBoundingClientRect]()[dimension] < self.aMin) {
              +                a.style[dimension] = (self.aMin - self.aGutterSize) + 'px'
              +                b.style[dimension] = (self.size - self.aMin - self.aGutterSize) + 'px'
              +            }
              +        }
              +      , balancePairs = function (pairs) {
              +            for (var i = 0; i < pairs.length; i++) {
              +                calculateSizes.call(pairs[i])
              +                fitMin.call(pairs[i])
              +            }
              +
              +            for (i = pairs.length - 1; i >= 0; i--) {
              +                calculateSizes.call(pairs[i])
              +                fitMinReverse.call(pairs[i])
              +            }
              +        }
              +      , preventSelection = function () { return false }
              +      , parent = elementOrSelector(ids[0]).parentNode
              +
              +    if (!options.sizes) {
              +        var percent = 100 / ids.length
              +
              +        options.sizes = []
              +
              +        for (i = 0; i < ids.length; i++) {
              +            options.sizes.push(percent)
              +        }
              +    }
              +
              +    if (!Array.isArray(options.minSize)) {
              +        var minSizes = []
              +
              +        for (i = 0; i < ids.length; i++) {
              +            minSizes.push(options.minSize)
              +        }
              +
              +        options.minSize = minSizes
              +    }
              +
              +    for (i = 0; i < ids.length; i++) {
              +        var el = elementOrSelector(ids[i])
              +          , isFirst = (i == 1)
              +          , isLast = (i == ids.length - 1)
              +          , size
              +          , gutterSize = options.gutterSize
              +          , pair
              +
              +        if (i > 0) {
              +            pair = {
              +                a: elementOrSelector(ids[i - 1]),
              +                b: el,
              +                aMin: options.minSize[i - 1],
              +                bMin: options.minSize[i],
              +                dragging: false,
              +                parent: parent,
              +                isFirst: isFirst,
              +                isLast: isLast,
              +                direction: options.direction
              +            }
              +
              +            // For first and last pairs, first and last gutter width is half.
              +
              +            pair.aGutterSize = options.gutterSize
              +            pair.bGutterSize = options.gutterSize
              +
              +            if (isFirst) {
              +                pair.aGutterSize = options.gutterSize / 2
              +            }
              +
              +            if (isLast) {
              +                pair.bGutterSize = options.gutterSize / 2
              +            }
              +        }
              +
              +        // IE9 and above
              +        if (!isIE8) {
              +            if (i > 0) {
              +                var gutter = document.createElement('div')
              +
              +                gutter.className = gutterClass
              +                gutter.style[dimension] = options.gutterSize + 'px'
              +
              +                gutter[addEventListener]('mousedown', startDragging.bind(pair))
              +                gutter[addEventListener]('touchstart', startDragging.bind(pair))
              +
              +                parent.insertBefore(gutter, el)
              +
              +                pair.gutter = gutter
              +            }
              +
              +            if (i === 0 || i == ids.length - 1) {
              +                gutterSize = options.gutterSize / 2
              +            }
              +
              +            if (typeof options.sizes[i] === 'string' || options.sizes[i] instanceof String) {
              +                size = options.sizes[i]
              +            } else {
              +                size = calc + '(' + options.sizes[i] + '% - ' + gutterSize + 'px)'
              +            }
              +
              +        // IE8 and below
              +        } else {
              +            if (typeof options.sizes[i] === 'string' || options.sizes[i] instanceof String) {
              +                size = options.sizes[i]
              +            } else {
              +                size = options.sizes[i] + '%'
              +            }
              +        }
              +
              +        el.style[dimension] = size
              +
              +        if (i > 0) {
              +            pairs.push(pair)
              +        }
              +    }
              +
              +    balancePairs(pairs)
              +}
              +
              +if (typeof exports !== 'undefined') {
              +    if (typeof module !== 'undefined' && module.exports) {
              +        exports = module.exports = Split
              +    }
              +    exports.Split = Split
              +} else {
              +    global.Split = Split
              +}
              +
              +}).call(window);
              \ No newline at end of file
              diff --git a/src/js/lib/uas_parser.js b/src/js/lib/uas_parser.js
              new file mode 100755
              index 00000000..97f0435b
              --- /dev/null
              +++ b/src/js/lib/uas_parser.js
              @@ -0,0 +1,25817 @@
              +/** @license
              +========================================================================
              +  UAS Parser
              +  Copyright (c) 2013 Nick Muerdter
              +
              +  MIT License
              +
              +  Permission is hereby granted, free of charge, to any person obtaining
              +  a copy of this software and associated documentation files (the
              +  "Software"), to deal in the Software without restriction, including
              +  without limitation the rights to use, copy, modify, merge, publish,
              +  distribute, sublicense, and/or sell copies of the Software, and to
              +  permit persons to whom the Software is furnished to do so, subject to
              +  the following conditions:
              +
              +  The above copyright notice and this permission notice shall be
              +  included in all copies or substantial portions of the Software.
              +
              +  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
              +  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
              +  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
              +  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
              +  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
              +  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
              +  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
              +*/
              +"use strict";
              +
              +var UAS_parser = {
              +	
              +	parse: function (userAgent) {
              +		var result = {
              +			type: 'unknown',
              +			uaFamily: 'unknown',
              +			uaName: 'unknown',
              +			uaUrl: 'unknown',
              +			uaCompany: 'unknown',
              +			uaCompanyUrl: 'unknown',
              +			uaIcon: 'unknown.png',
              +			uaInfoUrl: 'unknown',
              +			osFamily: 'unknown',
              +			osName: 'unknown',
              +			osUrl: 'unknown',
              +			osCompany: 'unknown',
              +			osCompanyUrl: 'unknown',
              +			osIcon: 'unknown.png',
              +			deviceType: 'unknown',
              +			deviceIcon: 'unknown.png',
              +			deviceInfoUrl: 'unknown'
              +		};
              +		for (var i = 0; i < UAS_cache.robots.order.length; i++) {
              +			var robotId = UAS_cache.robots.order[i];
              +			var robot = UAS_cache.robots[robotId];
              +			if (robot.userAgent === userAgent) {
              +				result.type = 'Robot';
              +				result = Utils.extend(result, robot.metadata);
              +				Utils.extend(result, UAS_cache.device['1']);
              +				return result;
              +			}
              +		}
              +		var osId;
              +		for (i = 0; i < UAS_cache.browserReg.order.length; i++) {
              +			var browserRegId = UAS_cache.browserReg.order[i];
              +			var browserReg = UAS_cache.browserReg[browserRegId];
              +			var matches = userAgent.match(browserReg.regexp);
              +			if (matches) {
              +				var browser = UAS_cache.browser[browserReg.browserId];
              +				if (browser) {
              +					result = Utils.extend(result, browser.metadata);
              +					var browserType = UAS_cache.browserType[browser.typeId];
              +					if (browserType) {
              +						result.type = browserType;
              +					}
              +					result.uaName = browser.metadata.uaFamily;
              +					if (matches[1]) {
              +						result.uaName += ' ' + matches[1];
              +					}
              +				}
              +				osId = UAS_cache.browserOs[browserReg.browserId];
              +				break;
              +			}
              +		}
              +		if (!osId) {
              +			for (i = 0; i < UAS_cache.osReg.order.length; i++) {
              +				var osRegId = UAS_cache.osReg.order[i];
              +				var osReg = UAS_cache.osReg[osRegId];
              +				if (osReg.regexp.test(userAgent)) {
              +					osId = osReg.osId;
              +					break;
              +				}
              +			}
              +		}
              +		if (osId) {
              +			var os = UAS_cache.os[osId];
              +			if (os) {
              +				result = Utils.extend(result, os);
              +			}
              +		}
              +		var device;
              +		if (result.type === 'Robot') {
              +			device = UAS_cache.device['1'];
              +		} else {
              +			for (i = 0; i < UAS_cache.deviceReg.order.length; i++) {
              +				var deviceRegId = UAS_cache.deviceReg.order[i];
              +				var deviceReg = UAS_cache.deviceReg[deviceRegId];
              +				if (deviceReg.regexp.test(userAgent)) {
              +					device = UAS_cache.device[deviceReg.deviceId];
              +					break;
              +				}
              +			}
              +		}
              +		if (!device) {
              +			if ([
              +					'Other',
              +					'Library',
              +					'Validator',
              +					'Useragent Anonymizer'
              +				].indexOf(result.type) !== -1) {
              +				device = UAS_cache.device['1'];
              +			} else if ([
              +					'Mobile Browser',
              +					'Wap Browser'
              +				].indexOf(result.type) !== -1) {
              +				device = UAS_cache.device['3'];
              +			} else {
              +				device = UAS_cache.device['2'];
              +			}
              +		}
              +		if (device) {
              +			result = Utils.extend(result, device);
              +		}
              +		return result;
              +	}
              +};
              +
              +var UAS_cache = {
              +	version: '20131025-01',
              +	robots: {
              +		'3': {
              +			userAgent: 'msnbot/1.0 (+http://search.msn.com/msnbot.htm)',
              +			metadata: {
              +				uaFamily: 'MSNBot',
              +				uaName: 'MSNBot/1.0',
              +				uaUrl: 'http://search.msn.com/msnbot.htm',
              +				uaCompany: 'Microsoft Corporation',
              +				uaCompanyUrl: 'http://www.microsoft.com/',
              +				uaIcon: 'bot_msnbot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MSNBot'
              +			}
              +		},
              +		'4': {
              +			userAgent: 'Mozilla/5.0 (compatible; Yahoo! Slurp; http://help.yahoo.com/help/us/ysearch/slurp)',
              +			metadata: {
              +				uaFamily: 'Yahoo!',
              +				uaName: 'Yahoo! Slurp',
              +				uaUrl: 'http://help.yahoo.com/help/us/ysearch/slurp',
              +				uaCompany: 'Yahoo! Inc.',
              +				uaCompanyUrl: 'http://www.yahoo.com/',
              +				uaIcon: 'bot_yahoo!slurp.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Yahoo!'
              +			}
              +		},
              +		'5': {
              +			userAgent: 'Jyxobot/1',
              +			metadata: {
              +				uaFamily: 'Jyxobot',
              +				uaName: 'Jyxobot',
              +				uaUrl: '',
              +				uaCompany: 'Jyxo s.r.o.',
              +				uaCompanyUrl: 'http://jyxo.cz/',
              +				uaIcon: 'bot_Jyxobot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Jyxobot'
              +			}
              +		},
              +		'9': {
              +			userAgent: 'Scooter/3.3',
              +			metadata: {
              +				uaFamily: 'Scooter',
              +				uaName: 'Scooter/3.3',
              +				uaUrl: '',
              +				uaCompany: 'AltaVista',
              +				uaCompanyUrl: 'http://www.altavista.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Scooter'
              +			}
              +		},
              +		'14': {
              +			userAgent: 'Baiduspider+(+http://www.baidu.com/search/spider.htm)',
              +			metadata: {
              +				uaFamily: 'Baiduspider',
              +				uaName: 'Baiduspider',
              +				uaUrl: 'http://www.baidu.com/search/spider.htm',
              +				uaCompany: 'Baidu',
              +				uaCompanyUrl: 'http://www.baidu.com/',
              +				uaIcon: 'bot_baiduspider.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Baiduspider'
              +			}
              +		},
              +		'20': {
              +			userAgent: 'lmspider (lmspider@scansoft.com)',
              +			metadata: {
              +				uaFamily: 'lmspider',
              +				uaName: 'lmspider',
              +				uaUrl: 'http://www.nuance.com/',
              +				uaCompany: 'Nuance Communications, Inc.',
              +				uaCompanyUrl: 'http://www.nuance.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=lmspider'
              +			}
              +		},
              +		'25': {
              +			userAgent: 'Googlebot-Image/1.0',
              +			metadata: {
              +				uaFamily: 'Googlebot',
              +				uaName: 'Googlebot-Image/1.0',
              +				uaUrl: 'http://support.google.com/webmasters/bin/answer.py?hl=en&answer=1061943',
              +				uaCompany: 'Google Inc.',
              +				uaCompanyUrl: 'http://www.google.com/',
              +				uaIcon: 'bot_googlebot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Googlebot'
              +			}
              +		},
              +		'31': {
              +			userAgent: 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)',
              +			metadata: {
              +				uaFamily: 'Googlebot',
              +				uaName: 'Googlebot/2.1',
              +				uaUrl: 'http://support.google.com/webmasters/bin/answer.py?hl=en&answer=1061943',
              +				uaCompany: 'Google Inc.',
              +				uaCompanyUrl: 'http://www.google.com/',
              +				uaIcon: 'bot_googlebot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Googlebot'
              +			}
              +		},
              +		'32': {
              +			userAgent: 'ConveraMultiMediaCrawler/0.1 (+http://www.authoritativeweb.com/crawl)',
              +			metadata: {
              +				uaFamily: 'ConveraCrawler',
              +				uaName: 'ConveraMultiMediaCrawler/0.1',
              +				uaUrl: 'http://www.authoritativeweb.com/crawl',
              +				uaCompany: 'Convera Corporation',
              +				uaCompanyUrl: 'http://www.authoritativeweb.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ConveraCrawler'
              +			}
              +		},
              +		'37': {
              +			userAgent: 'Mozilla/2.0 (compatible; Ask Jeeves/Teoma; +http://sp.ask.com/docs/about/tech_crawling.html)',
              +			metadata: {
              +				uaFamily: 'Ask Jeeves/Teoma',
              +				uaName: 'Ask Jeeves/Teoma - b',
              +				uaUrl: 'http://about.ask.com/en/docs/about/webmasters.shtml',
              +				uaCompany: 'Ask Jeeves Inc.',
              +				uaCompanyUrl: 'http://about.ask.com/en/docs/about/index.shtml',
              +				uaIcon: 'bot_AskJeeves.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Ask Jeeves/Teoma'
              +			}
              +		},
              +		'38': {
              +			userAgent: 'NG/2.0',
              +			metadata: {
              +				uaFamily: 'NG',
              +				uaName: 'NG/2.0',
              +				uaUrl: '',
              +				uaCompany: 'Exalead',
              +				uaCompanyUrl: 'http://exalead.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=NG'
              +			}
              +		},
              +		'40': {
              +			userAgent: 'TutorGigBot/1.5 ( +http://www.tutorgig.info )',
              +			metadata: {
              +				uaFamily: 'TutorGigBot',
              +				uaName: 'TutorGigBot',
              +				uaUrl: 'http://www.tutorgig.com/help.html',
              +				uaCompany: 'TutorGig',
              +				uaCompanyUrl: 'http://www.tutorgig.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=TutorGigBot'
              +			}
              +		},
              +		'43': {
              +			userAgent: 'ZACATEK_CZ_BOT (www.zacatek.cz)',
              +			metadata: {
              +				uaFamily: 'ZACATEK_CZ',
              +				uaName: 'ZACATEK_CZ_BOT',
              +				uaUrl: 'http://www.zacatek.cz/',
              +				uaCompany: 'webprovider - Adam Haken',
              +				uaCompanyUrl: 'http://www.webprovider.cz/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ZACATEK_CZ'
              +			}
              +		},
              +		'45': {
              +			userAgent: 'Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; Girafabot; girafabot at girafa dot com; http://www.girafa.com)',
              +			metadata: {
              +				uaFamily: 'Girafabot',
              +				uaName: 'Girafabot',
              +				uaUrl: '',
              +				uaCompany: 'Girafa Inc.',
              +				uaCompanyUrl: 'http://www.girafa.com/',
              +				uaIcon: 'bot_girafabot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Girafabot'
              +			}
              +		},
              +		'47': {
              +			userAgent: 'FAST MetaWeb Crawler (helpdesk at fastsearch dot com)',
              +			metadata: {
              +				uaFamily: 'FAST MetaWeb Crawler',
              +				uaName: 'FAST MetaWeb Crawler',
              +				uaUrl: 'http://www.fast.no/glossary.aspx?m=48&amid=415',
              +				uaCompany: 'Fast Search & Transfer',
              +				uaCompanyUrl: 'http://www.fastsearch.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=FAST MetaWeb Crawler'
              +			}
              +		},
              +		'56': {
              +			userAgent: 'psbot/0.1 (+http://www.picsearch.com/bot.html)',
              +			metadata: {
              +				uaFamily: 'psbot',
              +				uaName: 'psbot/0.1',
              +				uaUrl: 'http://www.picsearch.com/bot.html',
              +				uaCompany: 'picsearch.com',
              +				uaCompanyUrl: 'http://www.picsearch.com/',
              +				uaIcon: 'bot_psbot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=psbot'
              +			}
              +		},
              +		'76': {
              +			userAgent: 'City4you/1.3 Cesky (+http://www.city4you.pl)',
              +			metadata: {
              +				uaFamily: 'City4you',
              +				uaName: 'City4you/1.3 Cesky',
              +				uaUrl: '',
              +				uaCompany: 'city4you',
              +				uaCompanyUrl: 'http://www.city4you.pl/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=City4you'
              +			}
              +		},
              +		'80': {
              +			userAgent: 'ConveraCrawler/0.9d (+http://www.authoritativeweb.com/crawl)',
              +			metadata: {
              +				uaFamily: 'ConveraCrawler',
              +				uaName: 'ConveraCrawler 0.9d',
              +				uaUrl: 'http://www.authoritativeweb.com/crawl',
              +				uaCompany: 'Convera Corporation',
              +				uaCompanyUrl: 'http://www.authoritativeweb.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ConveraCrawler'
              +			}
              +		},
              +		'81': {
              +			userAgent: 'IlTrovatore-Setaccio/1.2 (It search engine; http://www.iltrovatore.it/bot.html; bot@iltrovatore.it)',
              +			metadata: {
              +				uaFamily: 'IlTrovatore-Setaccio',
              +				uaName: 'IlTrovatore-Setaccio/1.2',
              +				uaUrl: 'http://www.iltrovatore.it/bot.html',
              +				uaCompany: 'Il Trovatore',
              +				uaCompanyUrl: 'http://www.iltrovatore.it/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=IlTrovatore-Setaccio'
              +			}
              +		},
              +		'82': {
              +			userAgent: 'NutchCVS/0.8-dev (Nutch; http://lucene.apache.org/nutch/bot.html; nutch-agent@lucene.apache.org)',
              +			metadata: {
              +				uaFamily: 'Nutch',
              +				uaName: 'NutchCSV/0.8-dev',
              +				uaUrl: 'http://www.nutch.org/docs/en/bot.html',
              +				uaCompany: 'lucene',
              +				uaCompanyUrl: 'http://lucene.apache.org/',
              +				uaIcon: 'bot_Nutch.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Nutch'
              +			}
              +		},
              +		'83': {
              +			userAgent: 'ksibot/5.2m (+http://ego.ms.mff.cuni.cz/)',
              +			metadata: {
              +				uaFamily: 'ksibot',
              +				uaName: 'ksibot/5.2m',
              +				uaUrl: 'http://ego.ms.mff.cuni.cz/',
              +				uaCompany: 'Katedra softwarov\xe9ho in\u017een\xfdrstv\xed',
              +				uaCompanyUrl: 'http://kocour.ms.mff.cuni.cz/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ksibot'
              +			}
              +		},
              +		'84': {
              +			userAgent: 'NutchCVS/0.06-dev (http://www.nutch.org/docs/en/bot.html; rhwarren+nutch@uwaterloo.ca)',
              +			metadata: {
              +				uaFamily: 'Nutch',
              +				uaName: 'NutchCVS/0.06-dev at uwaterloo.ca',
              +				uaUrl: 'http://www.nutch.org/docs/en/bot.html',
              +				uaCompany: 'lucene',
              +				uaCompanyUrl: 'http://lucene.apache.org/',
              +				uaIcon: 'bot_Nutch.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Nutch'
              +			}
              +		},
              +		'85': {
              +			userAgent: 'InfociousBot (+http://corp.infocious.com/tech_crawler.php)',
              +			metadata: {
              +				uaFamily: 'InfociousBot',
              +				uaName: 'InfociousBot b',
              +				uaUrl: 'http://corp.infocious.com/tech_craw.php',
              +				uaCompany: 'Infocious Inc.',
              +				uaCompanyUrl: 'http://corp.infocious.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=InfociousBot'
              +			}
              +		},
              +		'86': {
              +			userAgent: 'NutchCVS/0.7 (Nutch; http://lucene.apache.org/nutch/bot.html; nutch-agent@lucene.apache.org)',
              +			metadata: {
              +				uaFamily: 'Nutch',
              +				uaName: 'NutchCVS/0.7',
              +				uaUrl: 'http://www.nutch.org/docs/en/bot.html',
              +				uaCompany: 'lucene',
              +				uaCompanyUrl: 'http://lucene.apache.org/',
              +				uaIcon: 'bot_Nutch.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Nutch'
              +			}
              +		},
              +		'88': {
              +			userAgent: 'SBIder/0.7 (SBIder; http://www.sitesell.com/sbider.html; http://support.sitesell.com/contact-support.html)',
              +			metadata: {
              +				uaFamily: 'SBIder',
              +				uaName: 'SBIder/0.7',
              +				uaUrl: 'http://www.sitesell.com/sbider.html',
              +				uaCompany: 'SiteSell',
              +				uaCompanyUrl: 'http://www.sitesell.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SBIder'
              +			}
              +		},
              +		'89': {
              +			userAgent: 'appie 1.1 (www.walhello.com)',
              +			metadata: {
              +				uaFamily: 'aippie',
              +				uaName: 'appie 1.1',
              +				uaUrl: 'http://www.walhello.com/aboutgl.html',
              +				uaCompany: 'Walhello.com',
              +				uaCompanyUrl: 'http://www.walhello.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=aippie'
              +			}
              +		},
              +		'90': {
              +			userAgent: 'http://www.almaden.ibm.com/cs/crawler   [bc22]',
              +			metadata: {
              +				uaFamily: 'Almaden',
              +				uaName: 'Almaden bc22',
              +				uaUrl: 'http://www.almaden.ibm.com/cs/crawler/',
              +				uaCompany: 'IBM Almaden Research Center',
              +				uaCompanyUrl: 'http://www.almaden.ibm.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Almaden'
              +			}
              +		},
              +		'93': {
              +			userAgent: 'OmniExplorer_Bot/4.02 (+http://www.omni-explorer.com) WorldIndexer',
              +			metadata: {
              +				uaFamily: 'OmniExplorer_Bot',
              +				uaName: 'OmniExplorer_Bot/4.02',
              +				uaUrl: 'http://www.omni-explorer.com/',
              +				uaCompany: '',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=OmniExplorer_Bot'
              +			}
              +		},
              +		'96': {
              +			userAgent: 'Szukankobot /1.0 (+http://www.szukanko.pl/addurl.php)',
              +			metadata: {
              +				uaFamily: 'Szukankobot',
              +				uaName: 'Szukankobot /1.0',
              +				uaUrl: 'http://www.szukanko.pl/',
              +				uaCompany: 'szukanko.pl',
              +				uaCompanyUrl: 'http://www.szukanko.pl/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Szukankobot'
              +			}
              +		},
              +		'100': {
              +			userAgent: 'NutchOSU-VLIB/0.7 (Nutch; http://lucene.apache.org/nutch/bot.html; nutch-agent@lucene.apache.org)',
              +			metadata: {
              +				uaFamily: 'Nutch',
              +				uaName: 'NutchOSU-VLIB/0.7',
              +				uaUrl: 'http://www.nutch.org/docs/en/bot.html',
              +				uaCompany: 'lucene',
              +				uaCompanyUrl: 'http://lucene.apache.org/',
              +				uaIcon: 'bot_Nutch.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Nutch'
              +			}
              +		},
              +		'101': {
              +			userAgent: 'snap.com beta crawler v0',
              +			metadata: {
              +				uaFamily: 'snap.com',
              +				uaName: 'snap.com beta crawler v0',
              +				uaUrl: '',
              +				uaCompany: ' Idealab',
              +				uaCompanyUrl: 'http://www.idealab.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=snap.com'
              +			}
              +		},
              +		'109': {
              +			userAgent: 'Mozilla/5.0 (compatible; OnetSzukaj/5.0; +http://szukaj.onet.pl)',
              +			metadata: {
              +				uaFamily: 'OnetSzukaj',
              +				uaName: 'OnetSzukaj/5.0',
              +				uaUrl: '',
              +				uaCompany: 'Onet.pl',
              +				uaCompanyUrl: 'http://www.onet.pl/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=OnetSzukaj'
              +			}
              +		},
              +		'114': {
              +			userAgent: 'Metaspinner/0.01 (Metaspinner; http://www.meta-spinner.de/; support@meta-spinner.de/)',
              +			metadata: {
              +				uaFamily: 'Metaspinner/0.01',
              +				uaName: 'Metaspinner/0.01',
              +				uaUrl: 'http://www.meta-spinner.de/',
              +				uaCompany: 'metaspinnner media GmbH',
              +				uaCompanyUrl: 'http://www.metaspinner-media.de/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Metaspinner/0.01'
              +			}
              +		},
              +		'116': {
              +			userAgent: 'OmniExplorer_Bot/4.06 (+http://www.omni-explorer.com) WorldIndexer',
              +			metadata: {
              +				uaFamily: 'OmniExplorer_Bot',
              +				uaName: 'OmniExplorer_Bot/4.06',
              +				uaUrl: 'http://www.omni-explorer.com/',
              +				uaCompany: '',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=OmniExplorer_Bot'
              +			}
              +		},
              +		'117': {
              +			userAgent: 'e-SocietyRobot(http://www.yama.info.waseda.ac.jp/~yamana/es/)',
              +			metadata: {
              +				uaFamily: 'e-SocietyRobot',
              +				uaName: 'e-SocietyRobot',
              +				uaUrl: 'http://www.yama.info.waseda.ac.jp/~yamana/es',
              +				uaCompany: 'Waseda University Yamana Laboratory',
              +				uaCompanyUrl: 'http://www.yama.info.waseda.ac.jp/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=e-SocietyRobot'
              +			}
              +		},
              +		'118': {
              +			userAgent: 'Findexa Crawler (http://www.findexa.no/gulesider/article26548.ece)',
              +			metadata: {
              +				uaFamily: 'Findexa Crawler',
              +				uaName: 'Findexa Crawler',
              +				uaUrl: 'http://www.findexa.no/gulesider/article26548.ece',
              +				uaCompany: 'Findexa AS',
              +				uaCompanyUrl: 'http://www.findexa.no/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Findexa Crawler'
              +			}
              +		},
              +		'120': {
              +			userAgent: 'InternetArchive/0.8-dev (Nutch; http://lucene.apache.org/nutch/bot.html; nutch-agent@lucene.apache.org)',
              +			metadata: {
              +				uaFamily: 'Nutch',
              +				uaName: 'InternetArchive/0.8-dev',
              +				uaUrl: 'http://www.nutch.org/docs/en/bot.html',
              +				uaCompany: 'lucene',
              +				uaCompanyUrl: 'http://lucene.apache.org/',
              +				uaIcon: 'bot_Nutch.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Nutch'
              +			}
              +		},
              +		'123': {
              +			userAgent: 'SBIder/0.8-dev (SBIder; http://www.sitesell.com/sbider.html; http://support.sitesell.com/contact-support.html)',
              +			metadata: {
              +				uaFamily: 'SBIder',
              +				uaName: 'SBIder/0.8dev',
              +				uaUrl: 'http://www.sitesell.com/sbider.html',
              +				uaCompany: 'SiteSell',
              +				uaCompanyUrl: 'http://www.sitesell.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SBIder'
              +			}
              +		},
              +		'124': {
              +			userAgent: 'ichiro/1.0 (ichiro@nttr.co.jp)',
              +			metadata: {
              +				uaFamily: 'ichiro',
              +				uaName: 'ichiro/1.0',
              +				uaUrl: 'http://search.goo.ne.jp/option/use/sub4/sub4-1/',
              +				uaCompany: 'NTT-Resonant Inc.',
              +				uaCompanyUrl: 'http://www.nttr.co.jp/',
              +				uaIcon: 'bot_ichiro.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ichiro'
              +			}
              +		},
              +		'125': {
              +			userAgent: 'miniRank/1.2 (miniRank; http://minirank.com/; MiniRank)',
              +			metadata: {
              +				uaFamily: 'miniRank',
              +				uaName: 'miniRank/1.2',
              +				uaUrl: 'http://www.minirank.com/',
              +				uaCompany: 'TitaniumLine.com',
              +				uaCompanyUrl: 'http://titaniumline.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=miniRank'
              +			}
              +		},
              +		'128': {
              +			userAgent: 'Amfibibot/0.07 (Amfibi Robot; http://www.amfibi.com; agent@amfibi.com)',
              +			metadata: {
              +				uaFamily: 'Amfibibot',
              +				uaName: 'Amfibibot/0.07',
              +				uaUrl: 'http://www.amfibi.com/',
              +				uaCompany: 'Barcelona Internet Telecom',
              +				uaCompanyUrl: 'http://www.bcntelecom.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Amfibibot'
              +			}
              +		},
              +		'130': {
              +			userAgent: 'LinkWalker',
              +			metadata: {
              +				uaFamily: 'LinkWalker',
              +				uaName: 'LinkWalker',
              +				uaUrl: '',
              +				uaCompany: 'SEVENtwentyfour Inc.',
              +				uaCompanyUrl: 'http://www.seventwentyfour.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=LinkWalker'
              +			}
              +		},
              +		'131': {
              +			userAgent: 'Mozilla/2.0 (compatible; Ask Jeeves/Teoma)',
              +			metadata: {
              +				uaFamily: 'Ask Jeeves/Teoma',
              +				uaName: 'Ask Jeeves/Teoma',
              +				uaUrl: 'http://about.ask.com/en/docs/about/webmasters.shtml',
              +				uaCompany: 'Ask Jeeves Inc.',
              +				uaCompanyUrl: 'http://about.ask.com/en/docs/about/index.shtml',
              +				uaIcon: 'bot_AskJeeves.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Ask Jeeves/Teoma'
              +			}
              +		},
              +		'132': {
              +			userAgent: 'StackRambler/2.0 (MSIE incompatible)',
              +			metadata: {
              +				uaFamily: 'StackRambler',
              +				uaName: 'StackRambler/2.0',
              +				uaUrl: 'http://www.rambler.ru/doc/robots.shtml',
              +				uaCompany: 'Rambler Media Group',
              +				uaCompanyUrl: 'http://ramblermedia.com/',
              +				uaIcon: 'bot_stackrambler.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=StackRambler'
              +			}
              +		},
              +		'133': {
              +			userAgent: 'NutchCVS/0.7.1 (Nutch; http://lucene.apache.org/nutch/bot.html; nutch-agent@lucene.apache.org)',
              +			metadata: {
              +				uaFamily: 'Nutch',
              +				uaName: 'NutchCVS/0.7.1',
              +				uaUrl: 'http://www.nutch.org/docs/en/bot.html',
              +				uaCompany: 'lucene',
              +				uaCompanyUrl: 'http://lucene.apache.org/',
              +				uaIcon: 'bot_Nutch.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Nutch'
              +			}
              +		},
              +		'135': {
              +			userAgent: 'Mozdex/0.7.2-dev (Mozdex; http://www.mozdex.com/bot.html; spider@mozdex.com)',
              +			metadata: {
              +				uaFamily: 'mozDex',
              +				uaName: 'Mozdex/0.7.2-dev',
              +				uaUrl: 'http://www.mozdex.com/bot.html',
              +				uaCompany: 'Mozdex.com',
              +				uaCompanyUrl: 'http://www.mozdex.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=mozDex'
              +			}
              +		},
              +		'137': {
              +			userAgent: 'Gaisbot/3.0+(robot@gais.cs.ccu.edu.tw;+http://gais.cs.ccu.edu.tw/robot.php)',
              +			metadata: {
              +				uaFamily: 'Gaisbot',
              +				uaName: 'Gaisbot/3.0',
              +				uaUrl: 'http://gais.cs.ccu.edu.tw/robot.php',
              +				uaCompany: 'National Chung Cheng University',
              +				uaCompanyUrl: 'http://www.ccu.edu.tw/',
              +				uaIcon: 'bot_gaisbot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Gaisbot'
              +			}
              +		},
              +		'140': {
              +			userAgent: 'Mozilla/4.0 compatible ZyBorg/1.0 Dead Link Checker (wn.dlc@looksmart.net; http://www.WISEnutbot.com)',
              +			metadata: {
              +				uaFamily: 'ZyBorg',
              +				uaName: 'ZyBorg/1.0 Dead Link Checker',
              +				uaUrl: 'http://www.wisenutbot.com/',
              +				uaCompany: 'LookSmart, Ltd.',
              +				uaCompanyUrl: 'http://aboutus.looksmart.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ZyBorg'
              +			}
              +		},
              +		'141': {
              +			userAgent: 'Mozilla/5.0 (compatible; Pogodak.co.yu/3.1)',
              +			metadata: {
              +				uaFamily: 'Pogodak.co.yu',
              +				uaName: 'Pogodak.co.yu/3.1',
              +				uaUrl: '',
              +				uaCompany: 'Pogodak d.o.o.',
              +				uaCompanyUrl: 'http://www.pogodak.co.yu/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Pogodak.co.yu'
              +			}
              +		},
              +		'144': {
              +			userAgent: 'ichiro/2.0 (ichiro@nttr.co.jp)',
              +			metadata: {
              +				uaFamily: 'ichiro',
              +				uaName: 'ichiro/2.0',
              +				uaUrl: 'http://search.goo.ne.jp/option/use/sub4/sub4-1/',
              +				uaCompany: 'NTT-Resonant Inc.',
              +				uaCompanyUrl: 'http://www.nttr.co.jp/',
              +				uaIcon: 'bot_ichiro.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ichiro'
              +			}
              +		},
              +		'146': {
              +			userAgent: 'boitho.com-dc/0.83 ( http://www.boitho.com/dcbot.html )',
              +			metadata: {
              +				uaFamily: 'boitho.com-dc',
              +				uaName: 'boitho.com-dc/0.83',
              +				uaUrl: 'http://www.boitho.com/dcbot.html',
              +				uaCompany: 'Boitho',
              +				uaCompanyUrl: 'http://www.boitho.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=boitho.com-dc'
              +			}
              +		},
              +		'148': {
              +			userAgent: 'http://www.almaden.ibm.com/cs/crawler   [hc4]',
              +			metadata: {
              +				uaFamily: 'Almaden',
              +				uaName: 'Almaden hc4',
              +				uaUrl: 'http://www.almaden.ibm.com/cs/crawler/',
              +				uaCompany: 'IBM Almaden Research Center',
              +				uaCompanyUrl: 'http://www.almaden.ibm.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Almaden'
              +			}
              +		},
              +		'151': {
              +			userAgent: 'Sensis Web Crawler (search_comments\\at\\sensis\\dot\\com\\dot\\au)',
              +			metadata: {
              +				uaFamily: 'Sensis Web Crawler',
              +				uaName: 'Sensis Web Crawler - b',
              +				uaUrl: '',
              +				uaCompany: 'Telstra Corporation Ltd.',
              +				uaCompanyUrl: 'http://telstra.com/',
              +				uaIcon: 'bot_sensiswebcrawler.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Sensis Web Crawler'
              +			}
              +		},
              +		'153': {
              +			userAgent: 'WebMiner (Web Miner; http://64.124.122.252/feedback.html)',
              +			metadata: {
              +				uaFamily: 'WebarooBot',
              +				uaName: 'WebMiner (Web Miner)',
              +				uaUrl: 'http://www.webaroo.com/company/site-owners',
              +				uaCompany: 'Webaroo Inc.',
              +				uaCompanyUrl: 'http://www.webaroo.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=WebarooBot'
              +			}
              +		},
              +		'155': {
              +			userAgent: 'ia_archiver-web.archive.org',
              +			metadata: {
              +				uaFamily: 'ia_archiver',
              +				uaName: 'ia_archiver',
              +				uaUrl: 'http://www.alexa.com/site/help/webmasters',
              +				uaCompany: 'Alexa Internet, Inc.',
              +				uaCompanyUrl: 'http://www.alexa.com/',
              +				uaIcon: 'bot_ia_archiver.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ia_archiver'
              +			}
              +		},
              +		'159': {
              +			userAgent: 'Mozilla/4.0 compatible ZyBorg/1.0 (wn-14.zyborg@looksmart.net; http://www.WISEnutbot.com)',
              +			metadata: {
              +				uaFamily: 'ZyBorg',
              +				uaName: 'ZyBorg/1.0',
              +				uaUrl: 'http://www.wisenutbot.com/',
              +				uaCompany: 'LookSmart, Ltd.',
              +				uaCompanyUrl: 'http://aboutus.looksmart.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ZyBorg'
              +			}
              +		},
              +		'162': {
              +			userAgent: 'Accoona-AI-Agent/1.1.1 (crawler at accoona dot com)',
              +			metadata: {
              +				uaFamily: 'Accoona-AI-Agent',
              +				uaName: 'Accoona-AI-Agent/1.1.1',
              +				uaUrl: '',
              +				uaCompany: 'Accoona Corp.',
              +				uaCompanyUrl: 'http://accoona.com/',
              +				uaIcon: 'bot_accoona-ai-agent.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Accoona-AI-Agent'
              +			}
              +		},
              +		'164': {
              +			userAgent: 'oBot',
              +			metadata: {
              +				uaFamily: 'oBot',
              +				uaName: 'oBot',
              +				uaUrl: 'http://filterdb.iss.net/crawler/',
              +				uaCompany: 'IBM Germany Research & Development GmbH',
              +				uaCompanyUrl: 'http://www.ibm.com/ibm/de/de/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=oBot'
              +			}
              +		},
              +		'167': {
              +			userAgent: 'Ipselonbot/0.47-beta (Ipselon; http://www.ipselon.com/intl/en/ipselonbot.html; ipselonbot@ipselon.com)',
              +			metadata: {
              +				uaFamily: 'Ipselonbot',
              +				uaName: 'Ipselonbot/0.47-beta',
              +				uaUrl: 'http://www.ipselon.com/intl/en/ipselonbot.html',
              +				uaCompany: 'Ipselon Networks s.l.',
              +				uaCompanyUrl: 'http://www.ipselon.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Ipselonbot'
              +			}
              +		},
              +		'168': {
              +			userAgent: 'IlTrovatore-Setaccio/1.2 (Italy search engine; http://www.iltrovatore.it/bot.html; bot@iltrovatore.it)',
              +			metadata: {
              +				uaFamily: 'IlTrovatore-Setaccio',
              +				uaName: 'IlTrovatore-Setaccio/1.2 b',
              +				uaUrl: 'http://www.iltrovatore.it/bot.html',
              +				uaCompany: 'Il Trovatore',
              +				uaCompanyUrl: 'http://www.iltrovatore.it/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=IlTrovatore-Setaccio'
              +			}
              +		},
              +		'170': {
              +			userAgent: 'RufusBot (Rufus Web Miner; http://64.124.122.252/feedback.html)',
              +			metadata: {
              +				uaFamily: 'WebarooBot',
              +				uaName: 'RufusBot (Rufus Web Miner)',
              +				uaUrl: 'http://www.webaroo.com/company/site-owners',
              +				uaCompany: 'Webaroo Inc.',
              +				uaCompanyUrl: 'http://www.webaroo.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=WebarooBot'
              +			}
              +		},
              +		'177': {
              +			userAgent: 'NutchCVS/0.7.1 (Nutch; http://www.vvdb.org; voorzitter@vvdb.org)',
              +			metadata: {
              +				uaFamily: 'Nutch',
              +				uaName: 'NutchCVS/0.7.1 vvdg.org',
              +				uaUrl: 'http://www.nutch.org/docs/en/bot.html',
              +				uaCompany: 'lucene',
              +				uaCompanyUrl: 'http://lucene.apache.org/',
              +				uaIcon: 'bot_Nutch.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Nutch'
              +			}
              +		},
              +		'178': {
              +			userAgent: 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; obot)',
              +			metadata: {
              +				uaFamily: 'oBot',
              +				uaName: 'oBot - b',
              +				uaUrl: 'http://filterdb.iss.net/crawler/',
              +				uaCompany: 'IBM Germany Research & Development GmbH',
              +				uaCompanyUrl: 'http://www.ibm.com/ibm/de/de/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=oBot'
              +			}
              +		},
              +		'184': {
              +			userAgent: 'ccubee/3.2',
              +			metadata: {
              +				uaFamily: 'ccubee',
              +				uaName: 'ccubee/3.2',
              +				uaUrl: 'http://empyreum.com/technologies/platforms/ccubee/',
              +				uaCompany: 'EMPYREUM k. s.',
              +				uaCompanyUrl: 'http://empyreum.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ccubee'
              +			}
              +		},
              +		'190': {
              +			userAgent: 'genieBot (wgao@genieknows.com)',
              +			metadata: {
              +				uaFamily: 'genieBot',
              +				uaName: 'genieBot a',
              +				uaUrl: 'http://64.5.245.11/faq/faq.html',
              +				uaCompany: 'IT Interactive Services Inc.',
              +				uaCompanyUrl: 'http://www.genieknows.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=genieBot'
              +			}
              +		},
              +		'192': {
              +			userAgent: 'ejupiter.com',
              +			metadata: {
              +				uaFamily: 'ejupiter.com',
              +				uaName: 'ejupiter.com',
              +				uaUrl: 'http://robot.ejupiter.com/16/robot_privacy.html',
              +				uaCompany: 'eJupiter Inc',
              +				uaCompanyUrl: 'http://www.ejupiter.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ejupiter.com'
              +			}
              +		},
              +		'193': {
              +			userAgent: 'Mozilla/5.0 (compatible; Yahoo! Slurp China; http://misc.yahoo.com.cn/help.html)',
              +			metadata: {
              +				uaFamily: 'Yahoo!',
              +				uaName: 'Yahoo! Slurp China',
              +				uaUrl: 'http://misc.yahoo.com.cn/help.html',
              +				uaCompany: 'Yahoo! Inc.',
              +				uaCompanyUrl: 'http://www.yahoo.com/',
              +				uaIcon: 'bot_yahoo!slurp.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Yahoo!'
              +			}
              +		},
              +		'194': {
              +			userAgent: 'thumbshots-de-Bot (Version: 1.02, powered by www.thumbshots.de)',
              +			metadata: {
              +				uaFamily: 'thumbshots-de-Bot',
              +				uaName: 'thumbshots-de-Bot 1.02',
              +				uaUrl: 'http://www.thumbshots.de/content-39-seite_auszuschliessen.html',
              +				uaCompany: 'Mobile & More Mobilkommunikation GmbH',
              +				uaCompanyUrl: 'http://www.mobile-more.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=thumbshots-de-Bot'
              +			}
              +		},
              +		'195': {
              +			userAgent: 'Vespa Crawler',
              +			metadata: {
              +				uaFamily: 'Vespa Crawler',
              +				uaName: 'Vespa Crawler',
              +				uaUrl: 'http://jobs.yahoo.no/index.html',
              +				uaCompany: 'Yahoo!',
              +				uaCompanyUrl: 'http://www.yahoo.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Vespa Crawler'
              +			}
              +		},
              +		'197': {
              +			userAgent: 'Ipselonbot/1.0-beta (+; http://www.ipselon.com/intl/en/ipselonbot.html)',
              +			metadata: {
              +				uaFamily: 'Ipselonbot',
              +				uaName: 'Ipselonbot/1.0-beta',
              +				uaUrl: 'http://www.ipselon.com/intl/en/ipselonbot.html',
              +				uaCompany: 'Ipselon Networks s.l.',
              +				uaCompanyUrl: 'http://www.ipselon.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Ipselonbot'
              +			}
              +		},
              +		'200': {
              +			userAgent: 'ccubee/3.3',
              +			metadata: {
              +				uaFamily: 'ccubee',
              +				uaName: 'ccubee/3.3',
              +				uaUrl: 'http://empyreum.com/technologies/platforms/ccubee/',
              +				uaCompany: 'EMPYREUM k. s.',
              +				uaCompanyUrl: 'http://empyreum.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ccubee'
              +			}
              +		},
              +		'201': {
              +			userAgent: 'Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.7) NimbleCrawler 1.11 obeys UserAgent NimbleCrawler For problems contact: crawler_at_dataalchemy.com',
              +			metadata: {
              +				uaFamily: 'NimbleCrawler',
              +				uaName: 'NimbleCrawler/1.11',
              +				uaUrl: '',
              +				uaCompany: 'Healthline Networks, Inc.',
              +				uaCompanyUrl: 'http://www.healthline.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=NimbleCrawler'
              +			}
              +		},
              +		'204': {
              +			userAgent: 'SynooBot/0.7.1 (SynooBot; http://www.synoo.de/bot.html; webmaster@synoo.com)',
              +			metadata: {
              +				uaFamily: 'SynooBot',
              +				uaName: 'SynooBot/0.7.1',
              +				uaUrl: 'http://www.synoo.de/bot.html',
              +				uaCompany: 'Synoo',
              +				uaCompanyUrl: 'http://www.synoo.de/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SynooBot'
              +			}
              +		},
              +		'207': {
              +			userAgent: 'ccubee/3.7',
              +			metadata: {
              +				uaFamily: 'ccubee',
              +				uaName: 'ccubee/3.7',
              +				uaUrl: 'http://empyreum.com/technologies/platforms/ccubee/',
              +				uaCompany: 'EMPYREUM k. s.',
              +				uaCompanyUrl: 'http://empyreum.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ccubee'
              +			}
              +		},
              +		'208': {
              +			userAgent: 'Silk/1.0',
              +			metadata: {
              +				uaFamily: 'silk',
              +				uaName: 'silk/1.0 -a',
              +				uaUrl: 'http://www.slider.com/silk.html',
              +				uaCompany: 'Slider.com',
              +				uaCompanyUrl: 'http://www.slider.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=silk'
              +			}
              +		},
              +		'209': {
              +			userAgent: 'Mozilla/5.0 (Windows;) NimbleCrawler 1.12 obeys UserAgent NimbleCrawler For problems contact: crawler@healthline.com',
              +			metadata: {
              +				uaFamily: 'NimbleCrawler',
              +				uaName: 'NimbleCrawler/1.12',
              +				uaUrl: '',
              +				uaCompany: 'Healthline Networks, Inc.',
              +				uaCompanyUrl: 'http://www.healthline.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=NimbleCrawler'
              +			}
              +		},
              +		'214': {
              +			userAgent: 'http://www.almaden.ibm.com/cs/crawler   [bc14]',
              +			metadata: {
              +				uaFamily: 'Almaden',
              +				uaName: 'Almaden bc14',
              +				uaUrl: 'http://www.almaden.ibm.com/cs/crawler/',
              +				uaCompany: 'IBM Almaden Research Center',
              +				uaCompanyUrl: 'http://www.almaden.ibm.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Almaden'
              +			}
              +		},
              +		'215': {
              +			userAgent: 'genieBot ((http://64.5.245.11/faq/faq.html))',
              +			metadata: {
              +				uaFamily: 'genieBot',
              +				uaName: 'genieBot b',
              +				uaUrl: 'http://64.5.245.11/faq/faq.html',
              +				uaCompany: 'IT Interactive Services Inc.',
              +				uaCompanyUrl: 'http://www.genieknows.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=genieBot'
              +			}
              +		},
              +		'217': {
              +			userAgent: 'g2Crawler (nobody@airmail.net)',
              +			metadata: {
              +				uaFamily: 'g2crawler',
              +				uaName: 'g2crawler',
              +				uaUrl: 'http://g2crawler.blogspot.com/',
              +				uaCompany: '',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=g2crawler'
              +			}
              +		},
              +		'218': {
              +			userAgent: 'Mozilla/5.0 (compatible; Theophrastus/2.0; +http://users.cs.cf.ac.uk/N.A.Smith/theophrastus.php)',
              +			metadata: {
              +				uaFamily: 'Theophrastus',
              +				uaName: 'Theophrastus/2.0',
              +				uaUrl: 'http://users.cs.cf.ac.uk/N.A.Smith/theophrastus.php',
              +				uaCompany: '',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Theophrastus'
              +			}
              +		},
              +		'219': {
              +			userAgent: 'Mozilla/5.0 (compatible; OnetSzukaj/5.0; +http://szukaj.onet.pl',
              +			metadata: {
              +				uaFamily: 'OnetSzukaj',
              +				uaName: 'OnetSzukaj/5.0 b',
              +				uaUrl: '',
              +				uaCompany: 'Onet.pl',
              +				uaCompanyUrl: 'http://www.onet.pl/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=OnetSzukaj'
              +			}
              +		},
              +		'221': {
              +			userAgent: 'Sensis Web Crawler (search_comments\\\\at\\\\sensis\\\\dot\\\\com\\\\dot\\\\au)',
              +			metadata: {
              +				uaFamily: 'Sensis Web Crawler',
              +				uaName: 'Sensis Web Crawler',
              +				uaUrl: 'http://www.sensis.com.au/help.do',
              +				uaCompany: 'Telstra Corporation Ltd.',
              +				uaCompanyUrl: 'http://www.telstra.com/',
              +				uaIcon: 'bot_sensiswebcrawler.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Sensis Web Crawler'
              +			}
              +		},
              +		'222': {
              +			userAgent: 'Mozilla/4.0 (compatible; MSIE 5.0; Windows 95) VoilaBot BETA 1.2 (http://www.voila.com/)',
              +			metadata: {
              +				uaFamily: 'VoilaBot',
              +				uaName: 'VoilaBot BETA 1.2',
              +				uaUrl: 'http://www.voila.com/',
              +				uaCompany: 'France Telecom',
              +				uaCompanyUrl: 'http://www.francetelecom.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=VoilaBot'
              +			}
              +		},
              +		'223': {
              +			userAgent: 'ichiro/2.0 (http://help.goo.ne.jp/door/crawler.html)',
              +			metadata: {
              +				uaFamily: 'ichiro',
              +				uaName: 'ichiro/2.0',
              +				uaUrl: 'http://search.goo.ne.jp/option/use/sub4/sub4-1/',
              +				uaCompany: 'NTT-Resonant Inc.',
              +				uaCompanyUrl: 'http://www.nttr.co.jp/',
              +				uaIcon: 'bot_ichiro.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ichiro'
              +			}
              +		},
              +		'225': {
              +			userAgent: 'VORTEX/1.2 (+http://marty.anstey.ca/robots/vortex/)',
              +			metadata: {
              +				uaFamily: 'VORTEX',
              +				uaName: 'VORTEX/1.2',
              +				uaUrl: 'http://marty.anstey.ca/projects/robots/vortex/',
              +				uaCompany: 'Marty Anstey',
              +				uaCompanyUrl: 'http://marty.anstey.ca/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=VORTEX'
              +			}
              +		},
              +		'226': {
              +			userAgent: 'GOFORITBOT ( http://www.goforit.com/about/ )',
              +			metadata: {
              +				uaFamily: 'GOFORITBOT',
              +				uaName: 'GOFORITBOT',
              +				uaUrl: 'http://www.goforit.com/about/',
              +				uaCompany: 'GoForIt Entertainment LLC',
              +				uaCompanyUrl: 'http://www.goforit.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=GOFORITBOT'
              +			}
              +		},
              +		'227': {
              +			userAgent: 'silk/1.0 (+http://www.slider.com/silk.htm)/3.7',
              +			metadata: {
              +				uaFamily: 'silk',
              +				uaName: 'silk/1.0',
              +				uaUrl: 'http://www.slider.com/silk.htm',
              +				uaCompany: 'Slider.com',
              +				uaCompanyUrl: 'http://www.slider.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=silk'
              +			}
              +		},
              +		'232': {
              +			userAgent: 'miniRank/1.5 (miniRank; www.minirank.com; robot)',
              +			metadata: {
              +				uaFamily: 'miniRank',
              +				uaName: 'miniRank/1.5',
              +				uaUrl: 'http://www.minirank.com/',
              +				uaCompany: 'TitaniumLine.com',
              +				uaCompanyUrl: 'http://titaniumline.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=miniRank'
              +			}
              +		},
              +		'235': {
              +			userAgent: 'SurveyBot/2.3 (Whois Source)',
              +			metadata: {
              +				uaFamily: 'SurveyBot',
              +				uaName: 'SurveyBot/2.3',
              +				uaUrl: 'http://www.whois.sc/info/webmasters/surveybot.html',
              +				uaCompany: 'Name Intelligence, Inc.',
              +				uaCompanyUrl: 'http://www.nameintelligence.com/',
              +				uaIcon: 'bot_surveybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SurveyBot'
              +			}
              +		},
              +		'236': {
              +			userAgent: 'http://www.almaden.ibm.com/cs/crawler   [bc5]',
              +			metadata: {
              +				uaFamily: 'Almaden',
              +				uaName: 'Almaden bc5',
              +				uaUrl: 'http://www.almaden.ibm.com/cs/crawler/',
              +				uaCompany: 'IBM Almaden Research Center',
              +				uaCompanyUrl: 'http://www.almaden.ibm.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Almaden'
              +			}
              +		},
              +		'237': {
              +			userAgent: 'btbot/0.4 (+http://www.btbot.com/btbot.html)',
              +			metadata: {
              +				uaFamily: 'btbot',
              +				uaName: 'btbot/0.4',
              +				uaUrl: 'http://www.btbot.com/btbot.html',
              +				uaCompany: 'btbot.com',
              +				uaCompanyUrl: 'http://www.btbot.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=btbot'
              +			}
              +		},
              +		'238': {
              +			userAgent: 'WIRE/0.10 (Linux; i686; Bot,Robot,Spider,Crawler)',
              +			metadata: {
              +				uaFamily: 'WIRE',
              +				uaName: 'WIRE/0.10',
              +				uaUrl: 'http://www.cwr.cl/projects/WIRE/',
              +				uaCompany: 'Universidad de Chile',
              +				uaCompanyUrl: 'http://www.dcc.uchile.cl/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=WIRE'
              +			}
              +		},
              +		'242': {
              +			userAgent: 'IRLbot/2.0 (+http://irl.cs.tamu.edu/crawler)',
              +			metadata: {
              +				uaFamily: 'IRLbot',
              +				uaName: 'IRLbot/2.0',
              +				uaUrl: 'http://irl.cs.tamu.edu/crawler/',
              +				uaCompany: 'Texas A&M University',
              +				uaCompanyUrl: 'http://www.tamu.edu/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=IRLbot'
              +			}
              +		},
              +		'252': {
              +			userAgent: 'MSRBOT',
              +			metadata: {
              +				uaFamily: 'MSRBOT',
              +				uaName: 'MSRBOT',
              +				uaUrl: 'http://research.microsoft.com/research/sv/msrbot/',
              +				uaCompany: 'Microsoft Corporation',
              +				uaCompanyUrl: 'http://www.microsoft.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MSRBOT'
              +			}
              +		},
              +		'253': {
              +			userAgent: 'PageBitesHyperBot/600 (http://www.pagebites.com/)',
              +			metadata: {
              +				uaFamily: 'PageBitesHyperBot',
              +				uaName: 'PageBitesHyperBot/600',
              +				uaUrl: '',
              +				uaCompany: 'PageBites Inc.',
              +				uaCompanyUrl: 'http://www.pagebites.com/',
              +				uaIcon: 'bot_pagebiteshyperbot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=PageBitesHyperBot'
              +			}
              +		},
              +		'262': {
              +			userAgent: 'Shim-Crawler(Mozilla-compatible; http://www.logos.ic.i.u-tokyo.ac.jp/crawler/; crawl@logos.ic.i.u-tokyo.ac.jp)',
              +			metadata: {
              +				uaFamily: 'Shim-Crawler',
              +				uaName: 'Shim-Crawler',
              +				uaUrl: 'http://www.logos.ic.i.u-tokyo.ac.jp/crawler/index.en.html',
              +				uaCompany: 'Chikayama-Taura Lab, The University of Tokyo',
              +				uaCompanyUrl: 'http://www.logos.ic.i.u-tokyo.ac.jp/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Shim-Crawler'
              +			}
              +		},
              +		'263': {
              +			userAgent: 'ccubee/4.0',
              +			metadata: {
              +				uaFamily: 'ccubee',
              +				uaName: 'ccubee/4.0',
              +				uaUrl: 'http://empyreum.com/technologies/platforms/ccubee/',
              +				uaCompany: 'EMPYREUM k. s.',
              +				uaCompanyUrl: 'http://empyreum.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ccubee'
              +			}
              +		},
              +		'266': {
              +			userAgent: 'ksibot/7.0d (+http://ego.ms.mff.cuni.cz/)',
              +			metadata: {
              +				uaFamily: 'ksibot',
              +				uaName: 'ksibot/7.0d',
              +				uaUrl: 'http://ego.ms.mff.cuni.cz/',
              +				uaCompany: 'Katedra softwarov\xe9ho in\u017een\xfdrstv\xed',
              +				uaCompanyUrl: 'http://kocour.ms.mff.cuni.cz/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ksibot'
              +			}
              +		},
              +		'267': {
              +			userAgent: 'IRLbot/2.0 (compatible; MSIE 6.0; http://irl.cs.tamu.edu/crawler)',
              +			metadata: {
              +				uaFamily: 'IRLbot',
              +				uaName: 'IRLbot/2.0 b',
              +				uaUrl: 'http://irl.cs.tamu.edu/crawler/',
              +				uaCompany: 'Texas A&M University',
              +				uaCompanyUrl: 'http://www.tamu.edu/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=IRLbot'
              +			}
              +		},
              +		'278': {
              +			userAgent: 'http://www.almaden.ibm.com/cs/crawler   [fc13]',
              +			metadata: {
              +				uaFamily: 'Almaden',
              +				uaName: 'Almaden fc13',
              +				uaUrl: 'http://www.almaden.ibm.com/cs/crawler/',
              +				uaCompany: 'IBM Almaden Research Center',
              +				uaCompanyUrl: 'http://www.almaden.ibm.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Almaden'
              +			}
              +		},
              +		'281': {
              +			userAgent: 'HooWWWer/2.1.3 (debugging run) (+http://cosco.hiit.fi/search/hoowwwer/ | mailto:crawler-info<at>hiit.fi)',
              +			metadata: {
              +				uaFamily: 'HooWWWer',
              +				uaName: 'HooWWWer/2.1.3',
              +				uaUrl: 'http://cosco.hiit.fi/search/hoowwwer/',
              +				uaCompany: 'CoSCo',
              +				uaCompanyUrl: 'http://cosco.hiit.fi/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=HooWWWer'
              +			}
              +		},
              +		'282': {
              +			userAgent: 'Mozilla/5.0 (Windows;) NimbleCrawler 1.13 obeys UserAgent NimbleCrawler For problems contact: crawler@healthline.com',
              +			metadata: {
              +				uaFamily: 'NimbleCrawler',
              +				uaName: 'NimbleCrawler/1.13',
              +				uaUrl: '',
              +				uaCompany: 'Healthline Networks, Inc.',
              +				uaCompanyUrl: 'http://www.healthline.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=NimbleCrawler'
              +			}
              +		},
              +		'285': {
              +			userAgent: 'Mozilla/5.0 (compatible; BecomeBot/2.3; MSIE 6.0 compatible; +http://www.become.com/site_owners.html)',
              +			metadata: {
              +				uaFamily: 'BecomeBot',
              +				uaName: 'BecomeBot/2.3',
              +				uaUrl: 'http://www.become.com/site_owners.html',
              +				uaCompany: 'Become, Inc.',
              +				uaCompanyUrl: 'http://www.become.com/',
              +				uaIcon: 'bot_becomebot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=BecomeBot'
              +			}
              +		},
              +		'290': {
              +			userAgent: 'Mozilla/5.0 (Windows;) NimbleCrawler 1.14 obeys UserAgent NimbleCrawler For problems contact: crawler@healthline.com',
              +			metadata: {
              +				uaFamily: 'NimbleCrawler',
              +				uaName: 'NimbleCrawler/1.14',
              +				uaUrl: '',
              +				uaCompany: 'Healthline Networks, Inc.',
              +				uaCompanyUrl: 'http://www.healthline.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=NimbleCrawler'
              +			}
              +		},
              +		'294': {
              +			userAgent: 'Mozilla/5.0 (Windows;) NimbleCrawler 1.15 obeys UserAgent NimbleCrawler For problems contact: crawler@healthline.com',
              +			metadata: {
              +				uaFamily: 'NimbleCrawler',
              +				uaName: 'NimbleCrawler/1.15',
              +				uaUrl: '',
              +				uaCompany: 'Healthline Networks, Inc.',
              +				uaCompanyUrl: 'http://www.healthline.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=NimbleCrawler'
              +			}
              +		},
              +		'295': {
              +			userAgent: 'MetaTagRobot/1.6 (http://www.widexl.com/remote/search-engines/metatag-analyzer.html)',
              +			metadata: {
              +				uaFamily: 'MetaTagRobot',
              +				uaName: 'MetaTagRobot/1.6',
              +				uaUrl: 'http://www.widexl.com/remote/search-engines/metatag-analyzer.html',
              +				uaCompany: 'widexl.com',
              +				uaCompanyUrl: 'http://www.widexl.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MetaTagRobot'
              +			}
              +		},
              +		'296': {
              +			userAgent: 'sproose/0.1-alpha (sproose crawler; http://www.sproose.com/bot.html; crawler@sproose.com)',
              +			metadata: {
              +				uaFamily: 'sproose',
              +				uaName: 'sproose/0.1-alpha',
              +				uaUrl: 'http://www.sproose.com/bot.html',
              +				uaCompany: 'Sproose, Inc.',
              +				uaCompanyUrl: 'http://www.sproose.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=sproose'
              +			}
              +		},
              +		'301': {
              +			userAgent: 'Search Engine World Robots.txt Validator at http://www.searchengineworld.com/cgi-bin/robotcheck.cgi',
              +			metadata: {
              +				uaFamily: 'Search Engine World Robots.txt Validator',
              +				uaName: 'Search Engine World Robots.txt Validator',
              +				uaUrl: 'http://www.searchengineworld.com/cgi-bin/robotcheck.cgi',
              +				uaCompany: 'searchengineworld',
              +				uaCompanyUrl: 'http://www.searchengineworld.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Search Engine World Robots.txt Validator'
              +			}
              +		},
              +		'303': {
              +			userAgent: 'Gaisbot/3.0+(robot06@gais.cs.ccu.edu.tw;+http://gais.cs.ccu.edu.tw/robot.php)',
              +			metadata: {
              +				uaFamily: 'Gaisbot',
              +				uaName: 'Gaisbot/3.0 - 06',
              +				uaUrl: 'http://gais.cs.ccu.edu.tw/robot.php',
              +				uaCompany: 'National Chung Cheng University',
              +				uaCompanyUrl: 'http://www.ccu.edu.tw/',
              +				uaIcon: 'bot_gaisbot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Gaisbot'
              +			}
              +		},
              +		'306': {
              +			userAgent: 'Forschungsportal/0.8-dev (Testinstallation; http://www.forschungsportal.net/; fpcrawler@rrzn.uni-hannover.de)',
              +			metadata: {
              +				uaFamily: 'Forschungsportal',
              +				uaName: 'Forschungsportal/0.8-dev',
              +				uaUrl: 'http://www.forschungsportal.net/',
              +				uaCompany: 'Bundesministerium f\xfcr Bildung und Forschung',
              +				uaCompanyUrl: 'http://www.bmbf.de/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Forschungsportal'
              +			}
              +		},
              +		'307': {
              +			userAgent: 'HooWWWer/2.2.0 (debugging run) (+http://cosco.hiit.fi/search/hoowwwer/ | mailto:crawler-info<at>hiit.fi)',
              +			metadata: {
              +				uaFamily: 'HooWWWer',
              +				uaName: 'HooWWWer/2.2.0',
              +				uaUrl: 'http://cosco.hiit.fi/search/hoowwwer/',
              +				uaCompany: 'CoSCo',
              +				uaCompanyUrl: 'http://cosco.hiit.fi/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=HooWWWer'
              +			}
              +		},
              +		'308': {
              +			userAgent: 'OmniExplorer_Bot/6.47 (+http://www.omni-explorer.com) WorldIndexer',
              +			metadata: {
              +				uaFamily: 'OmniExplorer_Bot',
              +				uaName: 'OmniExplorer_Bot/6.47',
              +				uaUrl: 'http://www.omni-explorer.com/',
              +				uaCompany: '',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=OmniExplorer_Bot'
              +			}
              +		},
              +		'310': {
              +			userAgent: 'Orbiter (+http://www.dailyorbit.com/bot.htm)',
              +			metadata: {
              +				uaFamily: 'Orbiter',
              +				uaName: 'Orbiter',
              +				uaUrl: 'http://www.dailyorbit.com/bot.htm',
              +				uaCompany: 'DailyOrbit.com',
              +				uaCompanyUrl: 'http://www.dailyorbit.com/',
              +				uaIcon: 'bot_orbiter.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Orbiter'
              +			}
              +		},
              +		'312': {
              +			userAgent: 'FAST Enterprise Crawler/6.4 (crawler@fast.no)',
              +			metadata: {
              +				uaFamily: 'FAST Enterprise Crawler',
              +				uaName: 'FAST Enterprise Crawler/6.4',
              +				uaUrl: 'http://www.fast.no/glossary.aspx?m=48&amid=415',
              +				uaCompany: 'Fast Search & Transfer',
              +				uaCompanyUrl: 'http://www.fastsearch.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=FAST Enterprise Crawler'
              +			}
              +		},
              +		'317': {
              +			userAgent: 'csci_b659/0.13',
              +			metadata: {
              +				uaFamily: 'csci_b659',
              +				uaName: 'csci_b659/0.13',
              +				uaUrl: 'http://informatics.indiana.edu/fil/Class/b659/',
              +				uaCompany: 'Indiana University',
              +				uaCompanyUrl: 'http://www.indiana.edu/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=csci_b659'
              +			}
              +		},
              +		'321': {
              +			userAgent: 'NutchCVS/0.06-dev (Nutch; http://www.nutch.org/docs/en/bot.html; nutch-agent@lists.sourceforge.net)',
              +			metadata: {
              +				uaFamily: 'Nutch',
              +				uaName: 'NutchCVS/0.06-dev',
              +				uaUrl: 'http://www.nutch.org/docs/en/bot.html',
              +				uaCompany: 'lucene',
              +				uaCompanyUrl: 'http://lucene.apache.org/',
              +				uaIcon: 'bot_Nutch.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Nutch'
              +			}
              +		},
              +		'323': {
              +			userAgent: 'NutchCVS/0.7.1 (Nutch running at UW; http://www.nutch.org/docs/en/bot.html; sycrawl@cs.washington.edu)',
              +			metadata: {
              +				uaFamily: 'Nutch',
              +				uaName: 'NutchCVS/0.7.1 at washihinton.edu',
              +				uaUrl: 'http://www.nutch.org/docs/en/bot.html',
              +				uaCompany: 'lucene',
              +				uaCompanyUrl: 'http://lucene.apache.org/',
              +				uaIcon: 'bot_Nutch.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Nutch'
              +			}
              +		},
              +		'326': {
              +			userAgent: 'miniRank/1.6 (Website ranking; www.minirank.com; robot)',
              +			metadata: {
              +				uaFamily: 'miniRank',
              +				uaName: 'miniRank/1.6',
              +				uaUrl: 'http://www.minirank.com/',
              +				uaCompany: 'TitaniumLine.com',
              +				uaCompanyUrl: 'http://titaniumline.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=miniRank'
              +			}
              +		},
              +		'327': {
              +			userAgent: 'ccubee/3.5',
              +			metadata: {
              +				uaFamily: 'ccubee',
              +				uaName: 'ccubee/3.5',
              +				uaUrl: 'http://empyreum.com/technologies/platforms/ccubee/',
              +				uaCompany: 'EMPYREUM k. s.',
              +				uaCompanyUrl: 'http://empyreum.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ccubee'
              +			}
              +		},
              +		'328': {
              +			userAgent: 'boitho.com-dc/0.79 ( http://www.boitho.com/dcbot.html )',
              +			metadata: {
              +				uaFamily: 'boitho.com-dc',
              +				uaName: 'boitho.com-dc/0.79',
              +				uaUrl: 'http://www.boitho.com/dcbot.html',
              +				uaCompany: 'Boitho',
              +				uaCompanyUrl: 'http://www.boitho.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=boitho.com-dc'
              +			}
              +		},
              +		'329': {
              +			userAgent: 'Mozilla/5.0 (compatible; Vermut +http://vermut.aol.com)',
              +			metadata: {
              +				uaFamily: 'Vermut',
              +				uaName: 'Vermut',
              +				uaUrl: 'http://vermut.aol.com/',
              +				uaCompany: 'America Online, Inc.',
              +				uaCompanyUrl: 'http://www.aol.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Vermut'
              +			}
              +		},
              +		'333': {
              +			userAgent: 'SynooBot (compatible; Synoobot/0.7.1; http://www.synoo.com/search/bot.html)',
              +			metadata: {
              +				uaFamily: 'SynooBot',
              +				uaName: 'SynooBot/0.7.1 com',
              +				uaUrl: ' http://www.synoo.com/search/bot.html',
              +				uaCompany: 'Synoo',
              +				uaCompanyUrl: 'http://www.synoo.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SynooBot'
              +			}
              +		},
              +		'335': {
              +			userAgent: 'NuSearch Spider (compatible; MSIE 6.0)',
              +			metadata: {
              +				uaFamily: 'NuSearch Spider',
              +				uaName: 'NuSearch Spider',
              +				uaUrl: 'http://www.nusearch.com/',
              +				uaCompany: 'nusearch.com',
              +				uaCompanyUrl: 'http://www.nusearch.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=NuSearch Spider'
              +			}
              +		},
              +		'337': {
              +			userAgent: 'Robo Crawler 6.4.5 (robocrawler@bb.softbank.co.jp)',
              +			metadata: {
              +				uaFamily: 'Robo Crawler',
              +				uaName: 'Robo Crawler 6.4.5',
              +				uaUrl: 'http://www.softbank.co.jp/',
              +				uaCompany: 'SOFTBANK CORP.',
              +				uaCompanyUrl: 'http://www.softbank.co.jp/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Robo Crawler'
              +			}
              +		},
              +		'338': {
              +			userAgent: 'NutchCVS/0.7.1 (Nutch running at UW; http://crawlers.cs.washington.edu/; sycrawl@cs.washington.edu)',
              +			metadata: {
              +				uaFamily: 'Nutch',
              +				uaName: 'NutchCVS/0.7.1 at UW',
              +				uaUrl: 'http://www.nutch.org/docs/en/bot.html',
              +				uaCompany: 'lucene',
              +				uaCompanyUrl: 'http://lucene.apache.org/',
              +				uaIcon: 'bot_Nutch.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Nutch'
              +			}
              +		},
              +		'340': {
              +			userAgent: 'XML Sitemaps Generator 1.0',
              +			metadata: {
              +				uaFamily: 'XML Sitemaps Generator',
              +				uaName: 'XML Sitemaps Generator 1.0',
              +				uaUrl: 'http://www.xml-sitemaps.com/',
              +				uaCompany: 'XML-Sitemaps.com',
              +				uaCompanyUrl: 'http://www.xml-sitemaps.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=XML Sitemaps Generator'
              +			}
              +		},
              +		'341': {
              +			userAgent: 'Mozilla/5.0 (Windows;) NimbleCrawler 2.0.0 obeys UserAgent NimbleCrawler For problems contact: crawler@healthline.com',
              +			metadata: {
              +				uaFamily: 'NimbleCrawler',
              +				uaName: 'NimbleCrawler/2.0.0',
              +				uaUrl: '',
              +				uaCompany: 'Healthline Networks, Inc.',
              +				uaCompanyUrl: 'http://www.healthline.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=NimbleCrawler'
              +			}
              +		},
              +		'343': {
              +			userAgent: 'NutchCVS/0.7.2 (Nutch; http://lucene.apache.org/nutch/bot.html; nutch-agent@lucene.apache.org)',
              +			metadata: {
              +				uaFamily: 'Nutch',
              +				uaName: 'NutchCVS/0.7.2',
              +				uaUrl: 'http://www.nutch.org/docs/en/bot.html',
              +				uaCompany: 'lucene',
              +				uaCompanyUrl: 'http://lucene.apache.org/',
              +				uaIcon: 'bot_Nutch.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Nutch'
              +			}
              +		},
              +		'345': {
              +			userAgent: 'updated/0.1-beta (updated; http://www.updated.com; crawler@updated.com)',
              +			metadata: {
              +				uaFamily: 'updated',
              +				uaName: 'updated/0.1-beta',
              +				uaUrl: '',
              +				uaCompany: 'Updated.com Inc.',
              +				uaCompanyUrl: 'http://www.updated.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=updated'
              +			}
              +		},
              +		'349': {
              +			userAgent: 'noyona_0_1',
              +			metadata: {
              +				uaFamily: 'noyona',
              +				uaName: 'noyona_0_1',
              +				uaUrl: 'http://www.noyona.com/',
              +				uaCompany: '',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=noyona'
              +			}
              +		},
              +		'350': {
              +			userAgent: 'Mozdex/0.7.2 (Mozdex; http://www.mozdex.com/bot.html; spider@mozdex.com)',
              +			metadata: {
              +				uaFamily: 'mozDex',
              +				uaName: 'Mozdex/0.7.2',
              +				uaUrl: 'http://www.mozdex.com/bot.html',
              +				uaCompany: 'Mozdex.com',
              +				uaCompanyUrl: 'http://www.mozdex.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=mozDex'
              +			}
              +		},
              +		'352': {
              +			userAgent: 'TeragramCrawler',
              +			metadata: {
              +				uaFamily: 'TeragramCrawler',
              +				uaName: 'TeragramCrawler',
              +				uaUrl: '',
              +				uaCompany: 'Teragram Corporation',
              +				uaCompanyUrl: 'http://www.teragram.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=TeragramCrawler'
              +			}
              +		},
              +		'355': {
              +			userAgent: 'Openfind data gatherer, Openbot/3.0+(robot-response@openfind.com.tw;+http://www.openfind.com.tw/robot.html)',
              +			metadata: {
              +				uaFamily: 'Openbot',
              +				uaName: 'Openbot/3.0',
              +				uaUrl: 'http://www.openfind.com.tw/robot.html',
              +				uaCompany: 'Openfind Information Technology INC.',
              +				uaCompanyUrl: 'http://www.openfind.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Openbot'
              +			}
              +		},
              +		'360': {
              +			userAgent: 'Mozilla/5.0 (compatible; BecomeBot/3.0; MSIE 6.0 compatible; +http://www.become.com/site_owners.html)',
              +			metadata: {
              +				uaFamily: 'BecomeBot',
              +				uaName: 'BecomeBot/3.0',
              +				uaUrl: 'http://www.become.com/site_owners.html',
              +				uaCompany: 'Become, Inc.',
              +				uaCompanyUrl: 'http://www.become.com/',
              +				uaIcon: 'bot_becomebot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=BecomeBot'
              +			}
              +		},
              +		'364': {
              +			userAgent: 'wwwster/1.4 (Beta, mailto:gue@cis.uni-muenchen.de)',
              +			metadata: {
              +				uaFamily: 'wwwster',
              +				uaName: 'wwwster/1.4 Beta',
              +				uaUrl: '',
              +				uaCompany: 'CIS',
              +				uaCompanyUrl: 'http://www.cis.uni-muenchen.de/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=wwwster'
              +			}
              +		},
              +		'366': {
              +			userAgent: 'NPBot/3 (NPBot; http://www.nameprotect.com; npbot@nameprotect.com)',
              +			metadata: {
              +				uaFamily: 'NPBot',
              +				uaName: 'NPBot/3',
              +				uaUrl: 'http://www.nameprotect.com/botinfo.html',
              +				uaCompany: 'NameProtect Inc.',
              +				uaCompanyUrl: 'http://www.nameprotect.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=NPBot'
              +			}
              +		},
              +		'368': {
              +			userAgent: 'NetWhatCrawler/0.06-dev (NetWhatCrawler from NetWhat.com; http://www.netwhat.com; support@netwhat.com)',
              +			metadata: {
              +				uaFamily: 'NetWhatCrawler',
              +				uaName: 'NetWhatCrawler/0.06-dev',
              +				uaUrl: '',
              +				uaCompany: 'GreenWave Online, Inc.',
              +				uaCompanyUrl: 'http://www.sonicrun.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=NetWhatCrawler'
              +			}
              +		},
              +		'376': {
              +			userAgent: 'virus_detector (virus_harvester@securecomputing.com)',
              +			metadata: {
              +				uaFamily: 'virus_detector',
              +				uaName: 'virus_detector',
              +				uaUrl: 'http://www.securecomputing.com/sg2_antivirus.cfm?menu=solutions',
              +				uaCompany: 'Secure Computing Corporation.',
              +				uaCompanyUrl: 'http://www.securecomputing.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=virus_detector'
              +			}
              +		},
              +		'378': {
              +			userAgent: 'IlTrovatore/1.2 (IlTrovatore; http://www.iltrovatore.it/bot.html; bot@iltrovatore.it)',
              +			metadata: {
              +				uaFamily: 'IlTrovatore',
              +				uaName: 'IlTrovatore/1.2',
              +				uaUrl: 'http://www.iltrovatore.it/bot.html',
              +				uaCompany: 'Il Trovatore',
              +				uaCompanyUrl: 'http://www.iltrovatore.it/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=IlTrovatore'
              +			}
              +		},
              +		'382': {
              +			userAgent: 'NutchCVS/0.8-dev (Nutch running at UW; http://www.nutch.org/docs/en/bot.html; sycrawl@cs.washington.edu)',
              +			metadata: {
              +				uaFamily: 'Nutch',
              +				uaName: 'NutchCSV/0.8-dev at UW',
              +				uaUrl: 'http://www.nutch.org/docs/en/bot.html',
              +				uaCompany: 'lucene',
              +				uaCompanyUrl: 'http://lucene.apache.org/',
              +				uaIcon: 'bot_Nutch.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Nutch'
              +			}
              +		},
              +		'391': {
              +			userAgent: 'kakle-spider/0.1 (kakle-spider; http://www.kakle.com/bot.html; support@kakle.com)',
              +			metadata: {
              +				uaFamily: 'Kakle Bot',
              +				uaName: 'kakle-spider/0.1',
              +				uaUrl: 'http://www.kakle.com/bot.html',
              +				uaCompany: 'Kakle Inc.',
              +				uaCompanyUrl: 'http://www.kakle.com',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Kakle Bot'
              +			}
              +		},
              +		'392': {
              +			userAgent: 'SrevBot/2.0 (SrevBot; http://winsrev.com/bot.html; bot@winsrev.com)',
              +			metadata: {
              +				uaFamily: 'SrevBot',
              +				uaName: 'SrevBot/2.0',
              +				uaUrl: 'http://www.winsrev.com/',
              +				uaCompany: '',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SrevBot'
              +			}
              +		},
              +		'393': {
              +			userAgent: 'CJB.NET Proxy',
              +			metadata: {
              +				uaFamily: 'CJB.NET Proxy',
              +				uaName: 'CJB.NET Proxy',
              +				uaUrl: 'http://proxy.cjb.net/',
              +				uaCompany: 'CJB.NET',
              +				uaCompanyUrl: 'http://www.cjb.net/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=CJB.NET Proxy'
              +			}
              +		},
              +		'394': {
              +			userAgent: 'http://www.almaden.ibm.com/cs/crawler   [bc6]',
              +			metadata: {
              +				uaFamily: 'Almaden',
              +				uaName: 'Almaden bc6',
              +				uaUrl: 'http://www.almaden.ibm.com/cs/crawler/',
              +				uaCompany: 'IBM Almaden Research Center',
              +				uaCompanyUrl: 'http://www.almaden.ibm.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Almaden'
              +			}
              +		},
              +		'396': {
              +			userAgent: 'Krugle/Krugle,Nutch/0.8+ (Krugle web crawler; http://www.krugle.com/crawler/info.html; webcrawler@krugle.com)',
              +			metadata: {
              +				uaFamily: 'Krugle',
              +				uaName: 'Krugle (Nutch/0.8+)',
              +				uaUrl: 'http://corp.krugle.com/crawler/info.html',
              +				uaCompany: 'Steve Larsen',
              +				uaCompanyUrl: 'http://blog.krugle.com/?page_id=5',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Krugle'
              +			}
              +		},
              +		'398': {
              +			userAgent: 'page_verifier (http://www.securecomputing.com/goto/pv)',
              +			metadata: {
              +				uaFamily: 'page_verifier',
              +				uaName: 'page_verifier',
              +				uaUrl: 'http://www.securecomputing.com/goto/pv',
              +				uaCompany: 'Secure Computing Corporation',
              +				uaCompanyUrl: 'http://www.securecomputing.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=page_verifier'
              +			}
              +		},
              +		'401': {
              +			userAgent: 'Mozilla/4.0 compatible ZyBorg/1.0 (wn-16.zyborg@looksmart.net; http://www.WISEnutbot.com)',
              +			metadata: {
              +				uaFamily: 'ZyBorg',
              +				uaName: 'ZyBorg/1.0 - b',
              +				uaUrl: 'http://www.wisenutbot.com/',
              +				uaCompany: 'LookSmart, Ltd.',
              +				uaCompanyUrl: 'http://aboutus.looksmart.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ZyBorg'
              +			}
              +		},
              +		'405': {
              +			userAgent: 'ksibot/8.0a (+http://ego.ms.mff.cuni.cz/)',
              +			metadata: {
              +				uaFamily: 'ksibot',
              +				uaName: 'ksibot/8.0a',
              +				uaUrl: 'http://ego.ms.mff.cuni.cz/',
              +				uaCompany: 'Katedra softwarov\xe9ho in\u017een\xfdrstv\xed',
              +				uaCompanyUrl: 'http://kocour.ms.mff.cuni.cz/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ksibot'
              +			}
              +		},
              +		'406': {
              +			userAgent: 'WinkBot/0.06 (Wink.com search engine web crawler; http://www.wink.com/Wink:WinkBot; winkbot@wink.com)',
              +			metadata: {
              +				uaFamily: 'WinkBot',
              +				uaName: 'WinkBot/0.06',
              +				uaUrl: 'http://www.wink.com/Wink:WinkBot',
              +				uaCompany: 'Wink Technologies, Inc',
              +				uaCompanyUrl: 'http://www.wink.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=WinkBot'
              +			}
              +		},
              +		'408': {
              +			userAgent: 'Snapbot/1.0',
              +			metadata: {
              +				uaFamily: 'Snapbot',
              +				uaName: 'Snapbot/1.0',
              +				uaUrl: '',
              +				uaCompany: 'Snap',
              +				uaCompanyUrl: 'http://www.snap.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Snapbot'
              +			}
              +		},
              +		'410': {
              +			userAgent: 'SrevBot/1.2 (SrevBot; http://winsrev.com/bot.html; bot@winsrev.comg)',
              +			metadata: {
              +				uaFamily: 'SrevBot',
              +				uaName: 'SrevBot/1.2',
              +				uaUrl: 'http://www.winsrev.com/',
              +				uaCompany: '',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SrevBot'
              +			}
              +		},
              +		'411': {
              +			userAgent: 'Mozilla/2.0 (compatible; Ask Jeeves/Teoma; +http://about.ask.com/en/docs/about/webmasters.shtml)',
              +			metadata: {
              +				uaFamily: 'Ask Jeeves/Teoma',
              +				uaName: 'Ask Jeeves/Teoma - c',
              +				uaUrl: 'http://about.ask.com/en/docs/about/webmasters.shtml',
              +				uaCompany: 'Ask Jeeves Inc.',
              +				uaCompanyUrl: 'http://about.ask.com/en/docs/about/index.shtml',
              +				uaIcon: 'bot_AskJeeves.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Ask Jeeves/Teoma'
              +			}
              +		},
              +		'412': {
              +			userAgent: 'textractor.queuekeeper/0.1 (+http://ufal.mff.cuni.cz/project/textractor/, textractor@ufal.mff.cuni.cz)',
              +			metadata: {
              +				uaFamily: 'textractor',
              +				uaName: 'textractor.queuekeeper/0.1',
              +				uaUrl: 'http://ufal.mff.cuni.cz/project/textractor/',
              +				uaCompany: 'Institute of Formal and Applied Linguistics (\xdaFAL)',
              +				uaCompanyUrl: 'http://ufal.mff.cuni.cz/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=textractor'
              +			}
              +		},
              +		'415': {
              +			userAgent: 'WIRE/0.11 (Linux; i686; Bot,Robot,Spider,Crawler,aromano@cli.di.unipi.it)',
              +			metadata: {
              +				uaFamily: 'WIRE',
              +				uaName: 'WIRE/0.11',
              +				uaUrl: 'http://www.cwr.cl/projects/WIRE/',
              +				uaCompany: 'Universidad de Chile',
              +				uaCompanyUrl: 'http://www.dcc.uchile.cl/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=WIRE'
              +			}
              +		},
              +		'416': {
              +			userAgent: 'MQbot metaquerier.cs.uiuc.edu/crawler',
              +			metadata: {
              +				uaFamily: 'MQbot',
              +				uaName: 'MQbot',
              +				uaUrl: 'http://metaquerier.cs.uiuc.edu/crawler/',
              +				uaCompany: 'University of Illinois at Urbana-Champaign',
              +				uaCompanyUrl: 'http://www.uiuc.edu/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MQbot'
              +			}
              +		},
              +		'422': {
              +			userAgent: 'DataparkSearch/4.40.1 (+http://www.dataparksearch.org/)',
              +			metadata: {
              +				uaFamily: 'DataparkSearch',
              +				uaName: 'DataparkSearch/4.40',
              +				uaUrl: 'http://www.dataparksearch.org/',
              +				uaCompany: 'DataPark',
              +				uaCompanyUrl: 'http://www.datapark.ru/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=DataparkSearch'
              +			}
              +		},
              +		'425': {
              +			userAgent: 'exactseek.com',
              +			metadata: {
              +				uaFamily: 'ExactSEEK',
              +				uaName: 'ExactSEEK',
              +				uaUrl: 'http://www.exactseek.com/',
              +				uaCompany: 'Jayde Online, Inc.',
              +				uaCompanyUrl: 'http://www.jaydeonlineinc.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ExactSEEK'
              +			}
              +		},
              +		'431': {
              +			userAgent: 'Mozilla/5.0 (Windows;) NimbleCrawler 2.0.1 obeys UserAgent NimbleCrawler For problems contact: crawler@healthline.com',
              +			metadata: {
              +				uaFamily: 'NimbleCrawler',
              +				uaName: 'NimbleCrawler/2.0.1',
              +				uaUrl: '',
              +				uaCompany: 'Healthline Networks, Inc.',
              +				uaCompanyUrl: 'http://www.healthline.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=NimbleCrawler'
              +			}
              +		},
              +		'435': {
              +			userAgent: 'sproose/0.1 (sproose bot; http://www.sproose.com/bot.html; crawler@sproose.com)',
              +			metadata: {
              +				uaFamily: 'sproose',
              +				uaName: 'sproose/0.1',
              +				uaUrl: 'http://www.sproose.com/bot.html',
              +				uaCompany: 'Sproose, Inc.',
              +				uaCompanyUrl: 'http://www.sproose.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=sproose'
              +			}
              +		},
              +		'437': {
              +			userAgent: 'updated/0.1-alpha (updated crawler; http://www.updated.com; crawler@updated.com)',
              +			metadata: {
              +				uaFamily: 'updated',
              +				uaName: 'updated/0.1-alpha',
              +				uaUrl: '',
              +				uaCompany: 'Updated.com Inc.',
              +				uaCompanyUrl: 'http://www.updated.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=updated'
              +			}
              +		},
              +		'439': {
              +			userAgent: 'Vagabondo/3.0 (webagent at wise-guys dot nl)',
              +			metadata: {
              +				uaFamily: 'Vagabondo',
              +				uaName: 'Vagabondo/3.0',
              +				uaUrl: 'http://webagent.wise-guys.nl/',
              +				uaCompany: 'WiseGuys Internet BV',
              +				uaCompanyUrl: 'http://www.wise-guys.nl/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Vagabondo'
              +			}
              +		},
              +		'442': {
              +			userAgent: 'Mozilla/4.0 (compatible; MyFamilyBot/1.0; http://www.myfamilyinc.com)',
              +			metadata: {
              +				uaFamily: 'MyFamilyBot',
              +				uaName: 'MyFamilyBot/1.0',
              +				uaUrl: 'http://www.ancestry.com/learn/bot.aspx',
              +				uaCompany: 'MyFamily.com, Inc.',
              +				uaCompanyUrl: 'http://www.myfamilyinc.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MyFamilyBot'
              +			}
              +		},
              +		'445': {
              +			userAgent: 'textractor.harvester/h7/1.0 (+http://ufal.mff.cuni.cz/project/textractor/, textractor@ufal.mff.cuni.cz)',
              +			metadata: {
              +				uaFamily: 'textractor',
              +				uaName: 'textractor.harvester/h7/1.0',
              +				uaUrl: 'http://ufal.mff.cuni.cz/project/textractor/',
              +				uaCompany: 'Institute of Formal and Applied Linguistics (\xdaFAL)',
              +				uaCompanyUrl: 'http://ufal.mff.cuni.cz/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=textractor'
              +			}
              +		},
              +		'447': {
              +			userAgent: 'textractor.harvester/h3/1.0 (+http://ufal.mff.cuni.cz/project/textractor/, textractor@ufal.mff.cuni.cz)',
              +			metadata: {
              +				uaFamily: 'textractor',
              +				uaName: 'textractor.harvester/h3/1.0',
              +				uaUrl: 'http://ufal.mff.cuni.cz/project/textractor/',
              +				uaCompany: 'Institute of Formal and Applied Linguistics (\xdaFAL)',
              +				uaCompanyUrl: 'http://ufal.mff.cuni.cz/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=textractor'
              +			}
              +		},
              +		'452': {
              +			userAgent: 'WIRE/0.11 (Linux; i686; Robot,Spider,Crawler,aromano@cli.di.unipi.it)',
              +			metadata: {
              +				uaFamily: 'WIRE',
              +				uaName: 'WIRE/0.11 b',
              +				uaUrl: 'http://www.cwr.cl/projects/WIRE/',
              +				uaCompany: 'Universidad de Chile',
              +				uaCompanyUrl: 'http://www.dcc.uchile.cl/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=WIRE'
              +			}
              +		},
              +		'456': {
              +			userAgent: 'boitho.com-dc/0.85 ( http://www.boitho.com/dcbot.html )',
              +			metadata: {
              +				uaFamily: 'boitho.com-dc',
              +				uaName: 'boitho.com-dc/0.85',
              +				uaUrl: 'http://www.boitho.com/dcbot.html',
              +				uaCompany: 'Boitho',
              +				uaCompanyUrl: 'http://www.boitho.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=boitho.com-dc'
              +			}
              +		},
              +		'462': {
              +			userAgent: 'schibstedsokbot (compatible; Mozilla/5.0; MSIE 5.0; FAST FreshCrawler 6; +http://www.schibstedsok.no/bot/)',
              +			metadata: {
              +				uaFamily: 'schibstedsokbot',
              +				uaName: 'schibstedsokbot',
              +				uaUrl: '',
              +				uaCompany: 'Schibsted ASA',
              +				uaCompanyUrl: 'http://www.schibsted.no/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=schibstedsokbot'
              +			}
              +		},
              +		'465': {
              +			userAgent: 'NG-Search/0.90 (NG-SearchBot; http://www.ng-search.com;  )',
              +			metadata: {
              +				uaFamily: 'NG-Search',
              +				uaName: 'NG-Search/0.90',
              +				uaUrl: '',
              +				uaCompany: 'NG-Marketing',
              +				uaCompanyUrl: 'http://www.ng-search.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=NG-Search'
              +			}
              +		},
              +		'469': {
              +			userAgent: 'WebRankSpider/1.37 (+http://ulm191.server4you.de/crawler/)',
              +			metadata: {
              +				uaFamily: 'WebRankSpider',
              +				uaName: 'WebRankSpider/1.37',
              +				uaUrl: 'http://ulm191.server4you.de/crawler/',
              +				uaCompany: '',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=WebRankSpider'
              +			}
              +		},
              +		'470': {
              +			userAgent: 'Szukacz/1.5 (robot; www.szukacz.pl/html/jak_dziala_robot.html; info@szukacz.pl)',
              +			metadata: {
              +				uaFamily: 'Szukacz',
              +				uaName: 'Szukacz/1.5',
              +				uaUrl: 'http://www.szukacz.pl/jakdzialarobot.html',
              +				uaCompany: '24 Godziny Sp. z o.o.',
              +				uaCompanyUrl: 'http://www.szukacz.pl/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Szukacz'
              +			}
              +		},
              +		'471': {
              +			userAgent: 'http://www.almaden.ibm.com/cs/crawler   [bc12]',
              +			metadata: {
              +				uaFamily: 'Almaden',
              +				uaName: 'Almaden bc12',
              +				uaUrl: 'http://www.almaden.ibm.com/cs/crawler/',
              +				uaCompany: 'IBM Almaden Research Center',
              +				uaCompanyUrl: 'http://www.almaden.ibm.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Almaden'
              +			}
              +		},
              +		'479': {
              +			userAgent: 'KRetrieve/1.1/dbsearchexpert.com',
              +			metadata: {
              +				uaFamily: 'KRetrieve',
              +				uaName: 'KRetrieve/1.1',
              +				uaUrl: 'http://www.dbsearchexpert.com/',
              +				uaCompany: '',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=KRetrieve'
              +			}
              +		},
              +		'480': {
              +			userAgent: 'Nusearch Spider (www.nusearch.com)',
              +			metadata: {
              +				uaFamily: 'NuSearch Spider',
              +				uaName: 'NuSearch Spider - b',
              +				uaUrl: 'http://www.nusearch.com/',
              +				uaCompany: 'nusearch.com',
              +				uaCompanyUrl: 'http://www.nusearch.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=NuSearch Spider'
              +			}
              +		},
              +		'481': {
              +			userAgent: 'Link Valet Online 1.1',
              +			metadata: {
              +				uaFamily: 'Link Valet Online',
              +				uaName: 'Link Valet Online 1.1',
              +				uaUrl: 'http://valet.htmlhelp.com/',
              +				uaCompany: 'Web Design Group',
              +				uaCompanyUrl: 'http://www.htmlhelp.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Link Valet Online'
              +			}
              +		},
              +		'482': {
              +			userAgent: 'asked/Nutch-0.8 (web crawler; http://asked.jp; epicurus at gmail dot com)',
              +			metadata: {
              +				uaFamily: 'Nutch',
              +				uaName: 'Nutch/0.8 at asked.jp',
              +				uaUrl: 'http://www.nutch.org/docs/en/bot.html',
              +				uaCompany: 'lucene',
              +				uaCompanyUrl: 'http://lucene.apache.org/',
              +				uaIcon: 'bot_Nutch.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Nutch'
              +			}
              +		},
              +		'483': {
              +			userAgent: 'Link Valet Online 1.2',
              +			metadata: {
              +				uaFamily: 'Link Valet Online',
              +				uaName: 'Link Valet Online 1.2',
              +				uaUrl: 'http://valet.htmlhelp.com/',
              +				uaCompany: 'Web Design Group',
              +				uaCompanyUrl: 'http://www.htmlhelp.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Link Valet Online'
              +			}
              +		},
              +		'484': {
              +			userAgent: "HouxouCrawler/Nutch-0.9-dev (houxou.com's nutch-based crawler which serves special interest on-line communities; http://www.houxou.com/crawler; crawler at houxou dot com)",
              +			metadata: {
              +				uaFamily: 'Nutch',
              +				uaName: 'Nutch/0.9-dev at houxou.com',
              +				uaUrl: 'http://www.nutch.org/docs/en/bot.html',
              +				uaCompany: 'lucene',
              +				uaCompanyUrl: 'http://lucene.apache.org/',
              +				uaIcon: 'bot_Nutch.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Nutch'
              +			}
              +		},
              +		'485': {
              +			userAgent: 'BilgiBetaBot/0.8-dev (bilgi.com (Beta) ; http://lucene.apache.org/nutch/bot.html; nutch-agent@lucene.apache.org)',
              +			metadata: {
              +				uaFamily: 'Nutch',
              +				uaName: 'Nutch/0.8-dev at bilgi.com',
              +				uaUrl: 'http://www.nutch.org/docs/en/bot.html',
              +				uaCompany: 'lucene',
              +				uaCompanyUrl: 'http://lucene.apache.org/',
              +				uaIcon: 'bot_Nutch.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Nutch'
              +			}
              +		},
              +		'488': {
              +			userAgent: 'egothor/8.0f (+http://ego.ms.mff.cuni.cz/)',
              +			metadata: {
              +				uaFamily: 'egothor',
              +				uaName: 'egothor/8.0f',
              +				uaUrl: 'http://ego.ms.mff.cuni.cz/',
              +				uaCompany: 'Katedra softwarov\xe9ho in\u017een\xfdrstv\xed Univerzity Karlovi',
              +				uaCompanyUrl: 'http://kocour.ms.mff.cuni.cz/cs/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=egothor'
              +			}
              +		},
              +		'489': {
              +			userAgent: 'TurnitinBot/2.0 (http://www.turnitin.com/robot/crawlerinfo.html)',
              +			metadata: {
              +				uaFamily: 'TurnitinBot',
              +				uaName: 'TurnitinBot/2.0',
              +				uaUrl: 'http://www.turnitin.com/robot/crawlerinfo.html',
              +				uaCompany: 'iParadigms, LLC.',
              +				uaCompanyUrl: 'http://www.iparadigms.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=TurnitinBot'
              +			}
              +		},
              +		'491': {
              +			userAgent: "HouxouCrawler/Nutch-0.8 (houxou.com's nutch-based crawler which serves special interest on-line communities; http://www.houxou.com/crawler; crawler at houxou dot com)",
              +			metadata: {
              +				uaFamily: 'Nutch',
              +				uaName: 'Nutch/0.8 at houxou.com',
              +				uaUrl: 'http://www.nutch.org/docs/en/bot.html',
              +				uaCompany: 'lucene',
              +				uaCompanyUrl: 'http://lucene.apache.org/',
              +				uaIcon: 'bot_Nutch.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Nutch'
              +			}
              +		},
              +		'493': {
              +			userAgent: 'NutchCVS/0.7.1 (Nutch; http://lucene.apache.org/nutch/bot.html; raphael@unterreuth.de)',
              +			metadata: {
              +				uaFamily: 'Nutch',
              +				uaName: 'NutchCVS/0.7.1 at unterreuth.de',
              +				uaUrl: 'http://www.nutch.org/docs/en/bot.html',
              +				uaCompany: 'lucene',
              +				uaCompanyUrl: 'http://lucene.apache.org/',
              +				uaIcon: 'bot_Nutch.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Nutch'
              +			}
              +		},
              +		'494': {
              +			userAgent: 'www.adressendeutschland.de',
              +			metadata: {
              +				uaFamily: 'adressendeutschland.de',
              +				uaName: 'adressendeutschland.de',
              +				uaUrl: 'http://www.adressendeutschland.de/konzept.html',
              +				uaCompany: 'http://www.arktosmedia.de/',
              +				uaCompanyUrl: 'Arktos MEDIA GmbH',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=adressendeutschland.de'
              +			}
              +		},
              +		'496': {
              +			userAgent: 'MetaTagRobot/2.1 (http://www.widexl.com/remote/search-engines/metatag-analyzer.html)',
              +			metadata: {
              +				uaFamily: 'MetaTagRobot',
              +				uaName: 'MetaTagRobot/2.1',
              +				uaUrl: 'http://www.widexl.com/remote/search-engines/metatag-analyzer.html',
              +				uaCompany: '',
              +				uaCompanyUrl: 'http://www.widexl.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MetaTagRobot'
              +			}
              +		},
              +		'499': {
              +			userAgent: 'Cazoodle/Nutch-0.9-dev (Cazoodle Nutch Crawler; http://www.cazoodle.com; mqbot@cazoodle.com)',
              +			metadata: {
              +				uaFamily: 'CazoodleBot',
              +				uaName: 'CazoodleBot a',
              +				uaUrl: 'http://www.cazoodle.com/cazoodlebot.php',
              +				uaCompany: 'Cazoodle Inc.',
              +				uaCompanyUrl: 'http://www.cazoodle.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=CazoodleBot'
              +			}
              +		},
              +		'501': {
              +			userAgent: 'Mozilla/3.0 (compatible; ScollSpider; http://www.webwobot.com)',
              +			metadata: {
              +				uaFamily: 'ScollSpider',
              +				uaName: 'ScollSpider',
              +				uaUrl: 'http://www.webwobot.com/ScollSpider.php',
              +				uaCompany: 'WebWoBot.com',
              +				uaCompanyUrl: 'http://www.webwobot.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ScollSpider'
              +			}
              +		},
              +		'512': {
              +			userAgent: 'Accoona-AI-Agent/1.1.2 (aicrawler at accoonabot dot com)',
              +			metadata: {
              +				uaFamily: 'Accoona-AI-Agent',
              +				uaName: 'Accoona-AI-Agent/1.1.2',
              +				uaUrl: '',
              +				uaCompany: 'Accoona Corp.',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_accoona-ai-agent.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Accoona-AI-Agent'
              +			}
              +		},
              +		'515': {
              +			userAgent: 'NG-Search/0.9.8 (NG-SearchBot; http://www.ng-search.com)',
              +			metadata: {
              +				uaFamily: 'NG-Search',
              +				uaName: 'NG-Search/0.9.8',
              +				uaUrl: '',
              +				uaCompany: 'NG-Marketing',
              +				uaCompanyUrl: 'http://www.ng-search.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=NG-Search'
              +			}
              +		},
              +		'517': {
              +			userAgent: 'holmes/3.9 (onet.pl)',
              +			metadata: {
              +				uaFamily: 'Holmes',
              +				uaName: 'holmes/3.9 - onet.pl',
              +				uaUrl: 'http://www.ucw.cz/holmes/',
              +				uaCompany: 'Martin Mare\u0161 and Robert \u0160palek',
              +				uaCompanyUrl: 'http://www.ucw.cz/holmes/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Holmes'
              +			}
              +		},
              +		'520': {
              +			userAgent: 'miniRank/2.0 (miniRank; http://minirank.com/; website ranking engine)',
              +			metadata: {
              +				uaFamily: 'miniRank',
              +				uaName: 'miniRank/2.0',
              +				uaUrl: 'http://www.minirank.com/',
              +				uaCompany: 'TitaniumLine.com',
              +				uaCompanyUrl: 'http://titaniumline.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=miniRank'
              +			}
              +		},
              +		'523': {
              +			userAgent: 'sogou spider',
              +			metadata: {
              +				uaFamily: 'sogou spider',
              +				uaName: 'sogou spider',
              +				uaUrl: 'http://www.sogou.com/docs/help/webmasters.htm#07',
              +				uaCompany: 'SOGOU.COM',
              +				uaCompanyUrl: 'http://www.sogou.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=sogou spider'
              +			}
              +		},
              +		'525': {
              +			userAgent: 'Megatext/Nutch-0.8.1 (Beta; http://www.megatext.cz/; microton@microton.cz)',
              +			metadata: {
              +				uaFamily: 'Megatext',
              +				uaName: 'Megatext-0.8.1 beta',
              +				uaUrl: '',
              +				uaCompany: 'Microton, s.r.o.',
              +				uaCompanyUrl: 'http://www.microton.cz/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Megatext'
              +			}
              +		},
              +		'528': {
              +			userAgent: 'Mozilla/4.0 (compatible; MyFamilyBot/1.0; http://www.ancestry.com/learn/bot.aspx)',
              +			metadata: {
              +				uaFamily: 'MyFamilyBot',
              +				uaName: 'MyFamilyBot/1.0 b',
              +				uaUrl: 'http://www.ancestry.com/learn/bot.aspx',
              +				uaCompany: 'MyFamily.com, Inc.',
              +				uaCompanyUrl: 'http://www.myfamilyinc.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MyFamilyBot'
              +			}
              +		},
              +		'531': {
              +			userAgent: 'Mozilla/4.0 compatible FurlBot/Furl Search 2.0 (FurlBot; http://www.furl.net; wn.furlbot@looksmart.net)',
              +			metadata: {
              +				uaFamily: 'FurlBot',
              +				uaName: 'FurlBot/Furl Search 2.0',
              +				uaUrl: '',
              +				uaCompany: 'LookSmart, Ltd.',
              +				uaCompanyUrl: 'http://search.looksmart.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=FurlBot'
              +			}
              +		},
              +		'536': {
              +			userAgent: 'Shim-Crawler(Mozilla-compatible; http://www.logos.ic.i.u-tokyo.ac.jp/crawl/; crawl@logos.ic.i.u-tokyo.ac.jp)',
              +			metadata: {
              +				uaFamily: 'Shim-Crawler',
              +				uaName: 'Shim-Crawler - b',
              +				uaUrl: 'http://www.logos.ic.i.u-tokyo.ac.jp/crawler/index.en.html',
              +				uaCompany: 'Chikayama-Taura Lab, The University of Tokyo',
              +				uaCompanyUrl: 'http://www.logos.ic.i.u-tokyo.ac.jp/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Shim-Crawler'
              +			}
              +		},
              +		'538': {
              +			userAgent: 'Motoricerca-Robots.txt-Checker/1.0 (http://tool.motoricerca.info/robots-checker.phtml)',
              +			metadata: {
              +				uaFamily: 'Motoricerca-Robots.txt-Checker',
              +				uaName: 'Motoricerca-Robots.txt-Checker/1.0',
              +				uaUrl: 'http://tool.motoricerca.info/robots-checker.phtml',
              +				uaCompany: 'Motoricerca.info',
              +				uaCompanyUrl: 'http://www.motoricerca.info/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Motoricerca-Robots.txt-Checker'
              +			}
              +		},
              +		'539': {
              +			userAgent: 'Kongulo v0.1 personal web crawler',
              +			metadata: {
              +				uaFamily: 'Kongulo',
              +				uaName: 'Kongulo v0.1',
              +				uaUrl: 'http://goog-kongulo.sourceforge.net/',
              +				uaCompany: 'Google Inc.',
              +				uaCompanyUrl: 'http://www.google.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Kongulo'
              +			}
              +		},
              +		'540': {
              +			userAgent: 'ichiro/2.01 (http://help.goo.ne.jp/door/crawler.html)',
              +			metadata: {
              +				uaFamily: 'ichiro',
              +				uaName: 'ichiro/2.01',
              +				uaUrl: 'http://search.goo.ne.jp/option/use/sub4/sub4-1/',
              +				uaCompany: 'NTT-Resonant Inc.',
              +				uaCompanyUrl: 'http://www.nttr.co.jp/',
              +				uaIcon: 'bot_ichiro.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ichiro'
              +			}
              +		},
              +		'545': {
              +			userAgent: 'sproose/1.0beta (sproose bot; http://www.sproose.com/bot.html; crawler@sproose.com)',
              +			metadata: {
              +				uaFamily: 'Sproose',
              +				uaName: 'Sproose/1.0beta',
              +				uaUrl: 'http://www.sproose.com/bot.html',
              +				uaCompany: 'Sproose, Inc.',
              +				uaCompanyUrl: 'http://www.sproose.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Sproose'
              +			}
              +		},
              +		'546': {
              +			userAgent: 'MSRBOT (http://research.microsoft.com/research/sv/msrbot/)',
              +			metadata: {
              +				uaFamily: 'MSRBOT',
              +				uaName: 'MSRBOT b',
              +				uaUrl: 'http://research.microsoft.com/research/sv/msrbot/',
              +				uaCompany: 'Microsoft Corporation',
              +				uaCompanyUrl: 'http://www.microsoft.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MSRBOT'
              +			}
              +		},
              +		'547': {
              +			userAgent: 'envolk/1.7 (+http://www.envolk.com/envolkspiderinfo.html)',
              +			metadata: {
              +				uaFamily: 'envolk',
              +				uaName: 'envolk/1.7',
              +				uaUrl: 'http://www.envolk.com/envolkspiderinfo.html',
              +				uaCompany: 'Envolk',
              +				uaCompanyUrl: 'http://www.envolk.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=envolk'
              +			}
              +		},
              +		'548': {
              +			userAgent: 'Blaiz-Bee/2.00.5622 (+http://www.blaiz.net)',
              +			metadata: {
              +				uaFamily: 'Blaiz-Bee',
              +				uaName: 'Blaiz-Bee/2.00.5622',
              +				uaUrl: 'http://www.rawgrunt.com/index.html',
              +				uaCompany: 'Blaiz Enterprises',
              +				uaCompanyUrl: 'http://www.blaiz.net/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Blaiz-Bee'
              +			}
              +		},
              +		'554': {
              +			userAgent: 'holmes/3.9 (OnetSzukaj/5.0; +http://szukaj.onet.pl)',
              +			metadata: {
              +				uaFamily: 'Holmes',
              +				uaName: 'holmes/3.9 - onet.pl b',
              +				uaUrl: 'http://www.ucw.cz/holmes/',
              +				uaCompany: 'Martin Mare\u0161 and Robert \u0160palek',
              +				uaCompanyUrl: 'http://www.ucw.cz/holmes/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Holmes'
              +			}
              +		},
              +		'556': {
              +			userAgent: 'EDI/1.6.5 (Edacious & Intelligent Web Robot, Daum Communications Corp.)',
              +			metadata: {
              +				uaFamily: 'EDI',
              +				uaName: 'EDI/1.6.5',
              +				uaUrl: '',
              +				uaCompany: 'Daum Communications Corp.',
              +				uaCompanyUrl: 'http://info.daum.net/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=EDI'
              +			}
              +		},
              +		'560': {
              +			userAgent: 'ccubee/9.0',
              +			metadata: {
              +				uaFamily: 'ccubee',
              +				uaName: 'ccubee/9.0',
              +				uaUrl: 'http://empyreum.com/technologies/platforms/ccubee/',
              +				uaCompany: 'EMPYREUM k. s.',
              +				uaCompanyUrl: 'http://empyreum.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ccubee'
              +			}
              +		},
              +		'562': {
              +			userAgent: 'MQBOT/Nutch-0.9-dev (MQBOT Nutch Crawler; http://falcon.cs.uiuc.edu; mqbot@cs.uiuc.edu)',
              +			metadata: {
              +				uaFamily: 'MQbot',
              +				uaName: 'MQBOT/Nutch-0.9-dev',
              +				uaUrl: 'http://metaquerier.cs.uiuc.edu/crawler/',
              +				uaCompany: 'University of Illinois at Urbana-Champaign',
              +				uaCompanyUrl: 'http://www.uiuc.edu/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MQbot'
              +			}
              +		},
              +		'563': {
              +			userAgent: 'Mozilla/5.0 (compatible; nextthing.org/1.0; +http://www.nextthing.org/bot)',
              +			metadata: {
              +				uaFamily: 'nextthing.org',
              +				uaName: 'nextthing.org/1.0',
              +				uaUrl: 'http://www.nextthing.org/bot/',
              +				uaCompany: 'Andrew Wooster',
              +				uaCompanyUrl: 'http://www.cs.hmc.edu/~awooster/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=nextthing.org'
              +			}
              +		},
              +		'564': {
              +			userAgent: 'crawler43.ejupiter.com',
              +			metadata: {
              +				uaFamily: 'ejupiter.com',
              +				uaName: 'ejupiter.com 43',
              +				uaUrl: 'http://robot.ejupiter.com/16/robot_privacy.html',
              +				uaCompany: 'eJupiter Inc',
              +				uaCompanyUrl: 'http://www.ejupiter.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ejupiter.com'
              +			}
              +		},
              +		'565': {
              +			userAgent: 'Szukacz/1.5 (robot; www.szukacz.pl/jakdzialarobot.html; info@szukacz.pl)',
              +			metadata: {
              +				uaFamily: 'Szukacz',
              +				uaName: 'Szukacz/1.5 b',
              +				uaUrl: 'http://www.szukacz.pl/jakdzialarobot.html',
              +				uaCompany: '24 Godziny Sp. z o.o.',
              +				uaCompanyUrl: 'http://www.szukacz.pl/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Szukacz'
              +			}
              +		},
              +		'566': {
              +			userAgent: 'Mozilla/5.0 (compatible; BecomeBot/3.0; +http://www.become.com/site_owners.html)',
              +			metadata: {
              +				uaFamily: 'BecomeBot',
              +				uaName: 'BecomeBot/3.0 b',
              +				uaUrl: 'http://www.become.com/site_owners.html',
              +				uaCompany: 'Become, Inc.',
              +				uaCompanyUrl: 'http://www.become.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=BecomeBot'
              +			}
              +		},
              +		'567': {
              +			userAgent: 'Steeler/3.2 (http://www.tkl.iis.u-tokyo.ac.jp/~crawler/)',
              +			metadata: {
              +				uaFamily: 'Steeler',
              +				uaName: 'Steeler/3.2',
              +				uaUrl: 'http://www.tkl.iis.u-tokyo.ac.jp/~crawler/',
              +				uaCompany: 'Kitsuregawa Laboratory, The University of Tokyo',
              +				uaCompanyUrl: 'http://www.tkl.iis.u-tokyo.ac.jp/',
              +				uaIcon: 'bot_Steeler.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Steeler'
              +			}
              +		},
              +		'569': {
              +			userAgent: 'Mozilla/4.0 (compatible; EDI/1.6.6; Edacious & Intelligent Web Robot; Daum Communications Corp., Korea)',
              +			metadata: {
              +				uaFamily: 'EDI',
              +				uaName: 'EDI/1.6.6',
              +				uaUrl: '',
              +				uaCompany: 'Daum Communications Corp.',
              +				uaCompanyUrl: 'http://info.daum.net/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=EDI'
              +			}
              +		},
              +		'580': {
              +			userAgent: 'Blaiz-Bee/2.00.5655 (+http://www.blaiz.net)',
              +			metadata: {
              +				uaFamily: 'Blaiz-Bee',
              +				uaName: 'Blaiz-Bee/2.00.5655',
              +				uaUrl: 'http://www.rawgrunt.com/index.html',
              +				uaCompany: 'Blaiz Enterprises',
              +				uaCompanyUrl: 'http://www.blaiz.net/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Blaiz-Bee'
              +			}
              +		},
              +		'581': {
              +			userAgent: "Zeusbot/0.07 (Ulysseek's web-crawling robot; http://www.zeusbot.com; agent@zeusbot.com)",
              +			metadata: {
              +				uaFamily: 'Zeusbot',
              +				uaName: 'Zeusbot/0.07',
              +				uaUrl: 'http://www.zeusbot.com/',
              +				uaCompany: 'Ulysseek',
              +				uaCompanyUrl: 'http://www.ulysseek.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Zeusbot'
              +			}
              +		},
              +		'587': {
              +			userAgent: 'MQBOT/Nutch-0.9-dev (MQBOT Crawler; http://falcon.cs.uiuc.edu; mqbot@cs.uiuc.edu)',
              +			metadata: {
              +				uaFamily: 'MQbot',
              +				uaName: 'MQBOT/Nutch-0.9-dev b',
              +				uaUrl: 'http://metaquerier.cs.uiuc.edu/crawler/',
              +				uaCompany: 'University of Illinois at Urbana-Champaign',
              +				uaCompanyUrl: 'http://www.uiuc.edu/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MQbot'
              +			}
              +		},
              +		'588': {
              +			userAgent: 'CazoodleBot/Nutch-0.9-dev (CazoodleBot Crawler; http://www.cazoodle.com; mqbot@cazoodle.com)',
              +			metadata: {
              +				uaFamily: 'CazoodleBot',
              +				uaName: 'CazoodleBot d',
              +				uaUrl: 'http://www.cazoodle.com/cazoodlebot.php',
              +				uaCompany: 'Cazoodle Inc.',
              +				uaCompanyUrl: 'http://www.cazoodle.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=CazoodleBot'
              +			}
              +		},
              +		'594': {
              +			userAgent: 'ccubee/10.0',
              +			metadata: {
              +				uaFamily: 'ccubee',
              +				uaName: 'ccubee/10.0',
              +				uaUrl: 'http://empyreum.com/technologies/platforms/ccubee/',
              +				uaCompany: 'EMPYREUM k. s.',
              +				uaCompanyUrl: 'http://empyreum.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ccubee'
              +			}
              +		},
              +		'597': {
              +			userAgent: 'Mozilla/5.0 (compatible; egothor/8.0g; +http://ego.ms.mff.cuni.cz/)',
              +			metadata: {
              +				uaFamily: 'egothor',
              +				uaName: 'egothor/8.0g',
              +				uaUrl: 'http://ego.ms.mff.cuni.cz/',
              +				uaCompany: 'Katedra softwarov\xe9ho in\u017een\xfdrstv\xed Univerzity Karlovi',
              +				uaCompanyUrl: 'http://kocour.ms.mff.cuni.cz/cs/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=egothor'
              +			}
              +		},
              +		'600': {
              +			userAgent: 'Mozilla/4.0 (compatible; MSIE is not me; EDI/1.6.6; Edacious & Intelligent Web Robot; Daum Communications Corp., Korea)',
              +			metadata: {
              +				uaFamily: 'EDI',
              +				uaName: 'EDI/1.6.6 b',
              +				uaUrl: '',
              +				uaCompany: 'Daum Communications Corp.',
              +				uaCompanyUrl: 'http://info.daum.net/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=EDI'
              +			}
              +		},
              +		'602': {
              +			userAgent: 'Bigsearch.ca/Nutch-0.9-dev (Bigsearch.ca Internet Spider; http://www.bigsearch.ca/; info@enhancededge.com)',
              +			metadata: {
              +				uaFamily: 'Bigsearch.ca',
              +				uaName: 'Bigsearch.ca/Nutch-0.9-dev',
              +				uaUrl: '',
              +				uaCompany: 'bigsearch.ca',
              +				uaCompanyUrl: 'http://www.bigsearch.ca/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Bigsearch.ca'
              +			}
              +		},
              +		'605': {
              +			userAgent: 'Yandex/1.01.001 (compatible; Win16; I)',
              +			metadata: {
              +				uaFamily: 'YandexBot',
              +				uaName: 'Yandex/1.01.001',
              +				uaUrl: 'http://yandex.com/bots',
              +				uaCompany: 'Yandex LLC',
              +				uaCompanyUrl: 'http://company.yandex.com/',
              +				uaIcon: 'bot_Yandex.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=YandexBot'
              +			}
              +		},
              +		'606': {
              +			userAgent: 'SBIder/SBIder-0.8.2-dev (http://www.sitesell.com/sbider.html)',
              +			metadata: {
              +				uaFamily: 'SBIder',
              +				uaName: 'SBIder-0.8.2-dev',
              +				uaUrl: 'http://www.sitesell.com/sbider.html',
              +				uaCompany: 'SiteSell Inc.',
              +				uaCompanyUrl: 'http://www.sitesell.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SBIder'
              +			}
              +		},
              +		'608': {
              +			userAgent: 'Combine/3 http://combine.it.lth.se/',
              +			metadata: {
              +				uaFamily: 'Combine',
              +				uaName: 'Combine/3',
              +				uaUrl: 'http://combine.it.lth.se/',
              +				uaCompany: 'Lunds universitet',
              +				uaCompanyUrl: 'http://www.lu.se/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Combine'
              +			}
              +		},
              +		'609': {
              +			userAgent: 'Megatext/Megatext-0.5 (beta; http://www.megatext.cz/; microton@microton.cz)',
              +			metadata: {
              +				uaFamily: 'Megatext',
              +				uaName: 'Megatext-0.5 beta',
              +				uaUrl: '',
              +				uaCompany: 'Microton, s.r.o.',
              +				uaCompanyUrl: 'http://www.microton.cz/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Megatext'
              +			}
              +		},
              +		'612': {
              +			userAgent: 'VMBot/0.7.2 (VMBot; http://www.VerticalMatch.com/; vmbot@tradedot.com)',
              +			metadata: {
              +				uaFamily: 'VMBot',
              +				uaName: 'VMBot/0.7.2',
              +				uaUrl: '',
              +				uaCompany: 'Vertical Search Engine (China)',
              +				uaCompanyUrl: 'http://www.verticalmatch.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=VMBot'
              +			}
              +		},
              +		'616': {
              +			userAgent: 'Mozilla/5.0 (compatible; polixea.de-Robot +http://www.polixea.de)',
              +			metadata: {
              +				uaFamily: 'polixea.de',
              +				uaName: 'polixea.de',
              +				uaUrl: '',
              +				uaCompany: 'POLIXEA AG',
              +				uaCompanyUrl: 'http://www.polixea.net/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=polixea.de'
              +			}
              +		},
              +		'623': {
              +			userAgent: 'HiddenMarket-1.0-beta (www.hiddenmarket.net/crawler.php)',
              +			metadata: {
              +				uaFamily: 'HiddenMarket',
              +				uaName: 'HiddenMarket-1.0-beta',
              +				uaUrl: 'http://www.hiddenmarket.net/crawler.php',
              +				uaCompany: 'HiddenMarket Group, Inc.',
              +				uaCompanyUrl: 'http://www.hiddenmarket.net/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=HiddenMarket'
              +			}
              +		},
              +		'624': {
              +			userAgent: 'Mozdex/0.7.1 (Mozdex; http://www.mozdex.com/bot.html; spider@mozdex.com)',
              +			metadata: {
              +				uaFamily: 'mozDex',
              +				uaName: 'Mozdex/0.7.1',
              +				uaUrl: 'http://www.mozdex.com/bot.html',
              +				uaCompany: 'Mozdex.com',
              +				uaCompanyUrl: 'http://www.mozdex.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=mozDex'
              +			}
              +		},
              +		'626': {
              +			userAgent: 'www.fi crawler, contact crawler@www.fi',
              +			metadata: {
              +				uaFamily: 'www.fi crawler',
              +				uaName: 'www.fi crawler',
              +				uaUrl: '',
              +				uaCompany: 'Fonecta',
              +				uaCompanyUrl: 'http://www.fonecta.fi/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=www.fi crawler'
              +			}
              +		},
              +		'629': {
              +			userAgent: 'Visbot/1.1 (Visvo.com - The Category Search Engine!; http://www.visvo.com/bot.html; bot@visvo.com)',
              +			metadata: {
              +				uaFamily: 'Visbot',
              +				uaName: 'Visbot/1.1',
              +				uaUrl: 'http://www.visvo.com/webmasters.html',
              +				uaCompany: 'Visvo Inc.',
              +				uaCompanyUrl: 'http://www.visvo.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Visbot'
              +			}
              +		},
              +		'630': {
              +			userAgent: 'Mozilla/4.0 (compatible; MSIE is not me; DAUMOA/1.0.0; DAUM Web Robot; Daum Communications Corp., Korea)',
              +			metadata: {
              +				uaFamily: 'Daumoa',
              +				uaName: 'DAUMOA/1.0.0',
              +				uaUrl: 'http://tab.search.daum.net/aboutWebSearch_en.html',
              +				uaCompany: 'Daum Communications Corp.',
              +				uaCompanyUrl: 'http://info.daum.net/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Daumoa'
              +			}
              +		},
              +		'631': {
              +			userAgent: 'LapozzBot/1.4 (+http://robot.lapozz.hu)',
              +			metadata: {
              +				uaFamily: 'LapozzBot',
              +				uaName: 'LapozzBot/1.4 hu',
              +				uaUrl: 'http://robot.lapozz.hu/',
              +				uaCompany: 'lapozz.hu',
              +				uaCompanyUrl: 'http://www.lapozz.hu/',
              +				uaIcon: 'bot_lapozzbot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=LapozzBot'
              +			}
              +		},
              +		'632': {
              +			userAgent: 'LapozzBot/1.4 (+http://robot.lapozz.com)',
              +			metadata: {
              +				uaFamily: 'LapozzBot',
              +				uaName: 'LapozzBot/1.4 com',
              +				uaUrl: 'http://robot.lapozz.com/',
              +				uaCompany: 'lapozz.hu',
              +				uaCompanyUrl: 'http://www.lapozz.hu/',
              +				uaIcon: 'bot_lapozzbot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=LapozzBot'
              +			}
              +		},
              +		'633': {
              +			userAgent: 'Krugle/Krugle,Nutch/0.8+ (Krugle web crawler; http://corp.krugle.com/crawler/info.html; webcrawler@krugle.com)',
              +			metadata: {
              +				uaFamily: 'Krugle',
              +				uaName: 'Krugle (Nutch/0.8+) b',
              +				uaUrl: 'http://corp.krugle.com/crawler/info.html',
              +				uaCompany: 'Steve Larsen',
              +				uaCompanyUrl: 'http://blog.krugle.com/?page_id=5',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Krugle'
              +			}
              +		},
              +		'645': {
              +			userAgent: 'textractor.harvester/h2/1.0 (+http://ufal.mff.cuni.cz/project/textractor/, textractor@ufal.mff.cuni.cz)',
              +			metadata: {
              +				uaFamily: 'textractor',
              +				uaName: 'textractor.harvester/h2/1.0',
              +				uaUrl: 'http://ufal.mff.cuni.cz/project/textractor/',
              +				uaCompany: 'Institute of Formal and Applied Linguistics (\xdaFAL)',
              +				uaCompanyUrl: 'http://ufal.mff.cuni.cz/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=textractor'
              +			}
              +		},
              +		'646': {
              +			userAgent: 'textractor.harvester/h27/1.0 (+http://ufal.mff.cuni.cz/project/textractor/, textractor@ufal.mff.cuni.cz)',
              +			metadata: {
              +				uaFamily: 'textractor',
              +				uaName: 'textractor.harvester/h27/1.0',
              +				uaUrl: 'http://ufal.mff.cuni.cz/project/textractor/',
              +				uaCompany: 'Institute of Formal and Applied Linguistics (\xdaFAL)',
              +				uaCompanyUrl: 'http://ufal.mff.cuni.cz/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=textractor'
              +			}
              +		},
              +		'648': {
              +			userAgent: 'textractor.harvester/h24/1.0 (+http://ufal.mff.cuni.cz/project/textractor/, textractor@ufal.mff.cuni.cz)',
              +			metadata: {
              +				uaFamily: 'textractor',
              +				uaName: 'textractor.harvester/h24/1.0',
              +				uaUrl: 'http://ufal.mff.cuni.cz/project/textractor/',
              +				uaCompany: 'Institute of Formal and Applied Linguistics (\xdaFAL)',
              +				uaCompanyUrl: 'http://ufal.mff.cuni.cz/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=textractor'
              +			}
              +		},
              +		'652': {
              +			userAgent: 'Mozilla/4.0 (compatible; DepSpid/5.07; +http://about.depspid.net)',
              +			metadata: {
              +				uaFamily: 'DepSpid',
              +				uaName: 'DepSpid/5.07',
              +				uaUrl: 'http://about.depspid.net/',
              +				uaCompany: 'Bjoern Henke',
              +				uaCompanyUrl: 'http://www.bjoernhenke.de/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=DepSpid'
              +			}
              +		},
              +		'653': {
              +			userAgent: 'YodaoBot/1.0 (http://www.yodao.com/help/webmaster/spider/; )',
              +			metadata: {
              +				uaFamily: 'YodaoBot',
              +				uaName: 'YodaoBot/1.0',
              +				uaUrl: 'http://www.yodao.com/help/webmaster/spider/',
              +				uaCompany: 'Yodao',
              +				uaCompanyUrl: 'http://www.yodao.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=YodaoBot'
              +			}
              +		},
              +		'656': {
              +			userAgent: 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 4.0; Girafabot; girafabot at girafa dot com; http://www.girafa.com)',
              +			metadata: {
              +				uaFamily: 'Girafabot',
              +				uaName: 'Girafabot b',
              +				uaUrl: '',
              +				uaCompany: 'Girafa Inc.',
              +				uaCompanyUrl: 'http://www.girafa.com/',
              +				uaIcon: 'bot_girafabot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Girafabot'
              +			}
              +		},
              +		'657': {
              +			userAgent: 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; Girafabot [girafa.com])',
              +			metadata: {
              +				uaFamily: 'Girafabot',
              +				uaName: 'Girafabot c',
              +				uaUrl: '',
              +				uaCompany: 'Girafa Inc.',
              +				uaCompanyUrl: 'http://www.girafa.com/',
              +				uaIcon: 'bot_girafabot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Girafabot'
              +			}
              +		},
              +		'658': {
              +			userAgent: 'VERASYS 2k Mozilla/4.0 (compatible; en) (compatible; MSIE 6.0; Windows NT 5.2; (+ http://web.verasys.ro); SV1; Unix; .NET CLR 1.1.4322)',
              +			metadata: {
              +				uaFamily: 'VERASYS 2k',
              +				uaName: 'VERASYS 2k',
              +				uaUrl: 'http://www.ghita.ro/article/1/verasys_2k.html',
              +				uaCompany: 'Serban Ghita',
              +				uaCompanyUrl: 'http://www.ghita.ro/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=VERASYS 2k'
              +			}
              +		},
              +		'665': {
              +			userAgent: 'Blaiz-Bee/2.00.6082 (+http://www.blaiz.net)',
              +			metadata: {
              +				uaFamily: 'Blaiz-Bee',
              +				uaName: 'Blaiz-Bee/2.00.6082',
              +				uaUrl: 'http://www.rawgrunt.com/index.html',
              +				uaCompany: 'Blaiz Enterprises',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Blaiz-Bee'
              +			}
              +		},
              +		'669': {
              +			userAgent: 'holmes/3.10.1 (OnetSzukaj/5.0; +http://szukaj.onet.pl)',
              +			metadata: {
              +				uaFamily: 'Holmes',
              +				uaName: 'holmes/3.10.1 - onet.pl',
              +				uaUrl: 'http://www.ucw.cz/holmes/',
              +				uaCompany: 'Martin Mare\u0161 and Robert \u0160palek',
              +				uaCompanyUrl: 'http://www.ucw.cz/holmes/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Holmes'
              +			}
              +		},
              +		'671': {
              +			userAgent: 'http://www.almaden.ibm.com/cs/crawler',
              +			metadata: {
              +				uaFamily: 'Almaden',
              +				uaName: 'Almaden',
              +				uaUrl: 'http://www.almaden.ibm.com/cs/crawler/',
              +				uaCompany: 'IBM Almaden Research Center',
              +				uaCompanyUrl: 'http://www.almaden.ibm.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Almaden'
              +			}
              +		},
              +		'676': {
              +			userAgent: 'AdsBot-Google (+http://www.google.com/adsbot.html)',
              +			metadata: {
              +				uaFamily: 'AdsBot-Google',
              +				uaName: 'AdsBot-Google',
              +				uaUrl: 'http://www.google.com/adsbot.html',
              +				uaCompany: 'Google Inc.',
              +				uaCompanyUrl: 'http://www.google.com/',
              +				uaIcon: 'bot_googlebot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=AdsBot-Google'
              +			}
              +		},
              +		'678': {
              +			userAgent: 'LinkWalker/2.0',
              +			metadata: {
              +				uaFamily: 'LinkWalker',
              +				uaName: 'LinkWalker/2.0',
              +				uaUrl: '',
              +				uaCompany: 'SEVENtwentyfour Inc.',
              +				uaCompanyUrl: 'http://www.seventwentyfour.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=LinkWalker'
              +			}
              +		},
              +		'679': {
              +			userAgent: 'Mozilla/5.0 (compatible; Exabot/3.0; +http://www.exabot.com/go/robot)',
              +			metadata: {
              +				uaFamily: 'Exabot',
              +				uaName: 'Exabot/3.0',
              +				uaUrl: 'http://www.exabot.com/go/robot',
              +				uaCompany: 'Exalead S.A.',
              +				uaCompanyUrl: 'http://www.exalead.com/',
              +				uaIcon: 'bot_Exabot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Exabot'
              +			}
              +		},
              +		'688': {
              +			userAgent: 'ConveraCrawler/0.9e (+http://www.authoritativeweb.com/crawl)',
              +			metadata: {
              +				uaFamily: 'ConveraCrawler',
              +				uaName: 'ConveraCrawler 0.9e',
              +				uaUrl: 'http://www.authoritativeweb.com/crawl',
              +				uaCompany: 'Convera Corporation',
              +				uaCompanyUrl: 'http://www.authoritativeweb.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ConveraCrawler'
              +			}
              +		},
              +		'689': {
              +			userAgent: 'miniRank/3.1 (miniRank; www.minirank.com; website ranking engine)',
              +			metadata: {
              +				uaFamily: 'miniRank',
              +				uaName: 'miniRank/3.1',
              +				uaUrl: 'http://www.minirank.com/',
              +				uaCompany: 'TitaniumLine.com',
              +				uaCompanyUrl: 'http://titaniumline.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=miniRank'
              +			}
              +		},
              +		'690': {
              +			userAgent: 'Pingdom GIGRIB (http://www.pingdom.com)',
              +			metadata: {
              +				uaFamily: 'pingdom.com_bot',
              +				uaName: 'Pingdom GIGRIB',
              +				uaUrl: 'http://uptime.pingdom.com/general/what_is',
              +				uaCompany: 'Pingdom',
              +				uaCompanyUrl: 'http://www.pingdom.com/',
              +				uaIcon: 'bot_pingdomcom_bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=pingdom.com_bot'
              +			}
              +		},
              +		'694': {
              +			userAgent: 'Mozilla/5.0 (compatible; Ask Jeeves/Teoma; +http://about.ask.com/en/docs/about/webmasters.shtml)',
              +			metadata: {
              +				uaFamily: 'Ask Jeeves/Teoma',
              +				uaName: 'Ask Jeeves/Teoma',
              +				uaUrl: 'http://about.ask.com/en/docs/about/webmasters.shtml',
              +				uaCompany: 'Ask Jeeves Inc.',
              +				uaCompanyUrl: 'http://about.ask.com/en/docs/about/index.shtml',
              +				uaIcon: 'bot_AskJeeves.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Ask Jeeves/Teoma'
              +			}
              +		},
              +		'698': {
              +			userAgent: 'VMBot/0.9 (VMBot; http://www.verticalmatch.com; vmbot@tradedot.com)',
              +			metadata: {
              +				uaFamily: 'VMBot',
              +				uaName: 'VMBot/0.9',
              +				uaUrl: '',
              +				uaCompany: 'Vertical Search Engine (China)',
              +				uaCompanyUrl: 'http://www.verticalmatch.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=VMBot'
              +			}
              +		},
              +		'703': {
              +			userAgent: 'TurnitinBot/2.1 (http://www.turnitin.com/robot/crawlerinfo.html)',
              +			metadata: {
              +				uaFamily: 'TurnitinBot',
              +				uaName: 'TurnitinBot/2.1',
              +				uaUrl: 'http://www.turnitin.com/robot/crawlerinfo.html',
              +				uaCompany: 'iParadigms, LLC.',
              +				uaCompanyUrl: 'http://www.iparadigms.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=TurnitinBot'
              +			}
              +		},
              +		'710': {
              +			userAgent: 'heeii/Nutch-0.9-dev (heeii.com; www.heeii.com; nutch at heeii.com)',
              +			metadata: {
              +				uaFamily: 'Nutch',
              +				uaName: 'heeii/Nutch-0.9-dev at heeii.com',
              +				uaUrl: 'http://www.nutch.org/docs/en/bot.html',
              +				uaCompany: 'lucene',
              +				uaCompanyUrl: 'http://lucene.apache.org/',
              +				uaIcon: 'bot_Nutch.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Nutch'
              +			}
              +		},
              +		'712': {
              +			userAgent: 'Mozilla/5.0 (compatible; BecomeJPBot/2.3; MSIE 6.0 compatible; +http://www.become.co.jp/site_owners.html)',
              +			metadata: {
              +				uaFamily: 'BecomeBot',
              +				uaName: 'BecomeBot/2.3 b',
              +				uaUrl: 'http://www.become.com/site_owners.html',
              +				uaCompany: 'Become, Inc.',
              +				uaCompanyUrl: 'http://www.become.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=BecomeBot'
              +			}
              +		},
              +		'715': {
              +			userAgent: 'AdsBot-Google',
              +			metadata: {
              +				uaFamily: 'AdsBot-Google',
              +				uaName: 'AdsBot-Google b',
              +				uaUrl: 'http://www.google.com/adsbot.html',
              +				uaCompany: 'Google Inc.',
              +				uaCompanyUrl: 'http://www.google.com/',
              +				uaIcon: 'bot_googlebot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=AdsBot-Google'
              +			}
              +		},
              +		'716': {
              +			userAgent: "HouxouCrawler/Nutch-0.8.2-dev (houxou.com's nutch-based crawler which serves special interest on-line communities; http://www.houxou.com/crawler; crawler at houxou dot com)",
              +			metadata: {
              +				uaFamily: 'Nutch',
              +				uaName: 'Nutch/0.8.2-dev at houxou.com',
              +				uaUrl: 'http://www.nutch.org/docs/en/bot.html',
              +				uaCompany: 'lucene',
              +				uaCompanyUrl: 'http://lucene.apache.org/',
              +				uaIcon: 'bot_Nutch.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Nutch'
              +			}
              +		},
              +		'725': {
              +			userAgent: 'DataFountains/Dmoz Downloader (http://ivia.ucr.edu/useragents.shtml)',
              +			metadata: {
              +				uaFamily: 'DataFountains',
              +				uaName: 'DataFountains at Dmoz',
              +				uaUrl: 'http://ivia.ucr.edu/useragents.shtml',
              +				uaCompany: 'University of California',
              +				uaCompanyUrl: 'http://www.universityofcalifornia.edu/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=DataFountains'
              +			}
              +		},
              +		'728': {
              +			userAgent: 'Mozilla/5.0 (compatible; YodaoBot/1.0; http://www.yodao.com/help/webmaster/spider/; )',
              +			metadata: {
              +				uaFamily: 'YodaoBot',
              +				uaName: 'YodaoBot/1.0',
              +				uaUrl: 'http://www.yodao.com/help/webmaster/spider/',
              +				uaCompany: 'yodao.com',
              +				uaCompanyUrl: 'http://www.yodao.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=YodaoBot'
              +			}
              +		},
              +		'729': {
              +			userAgent: 'IRLbot/3.0 (compatible; MSIE 6.0; http://irl.cs.tamu.edu/crawler)',
              +			metadata: {
              +				uaFamily: 'IRLbot',
              +				uaName: 'IRLbot/3.0',
              +				uaUrl: 'http://irl.cs.tamu.edu/crawler/',
              +				uaCompany: 'Texas A&M University',
              +				uaCompanyUrl: 'http://www.tamu.edu/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=IRLbot'
              +			}
              +		},
              +		'731': {
              +			userAgent: 'Mozilla/5.0 (compatible; del.icio.us-thumbnails/1.0; FreeBSD) KHTML/4.3.2 (like Gecko)',
              +			metadata: {
              +				uaFamily: 'del.icio.us-thumbnails',
              +				uaName: 'del.icio.us-thumbnails/1.0',
              +				uaUrl: '',
              +				uaCompany: 'Yahoo! Inc',
              +				uaCompanyUrl: 'http://www.yahoo.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=del.icio.us-thumbnails'
              +			}
              +		},
              +		'741': {
              +			userAgent: 'Gallent Search Spider v1.4 Robot 3 (http://www.GallentSearch.com/robot)',
              +			metadata: {
              +				uaFamily: 'Gallent Search Spider',
              +				uaName: 'Gallent Search Spider v1.4 Robot 3',
              +				uaUrl: '',
              +				uaCompany: 'Gallent Limited',
              +				uaCompanyUrl: 'http://www.gallentsearch.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Gallent Search Spider'
              +			}
              +		},
              +		'742': {
              +			userAgent: 'CazoodleBot/0.1 (CazoodleBot Crawler; http://www.cazoodle.com; mqbot@cazoodle.com)',
              +			metadata: {
              +				uaFamily: 'CazoodleBot',
              +				uaName: 'CazoodleBot b',
              +				uaUrl: 'http://www.cazoodle.com/cazoodlebot.php',
              +				uaCompany: 'Cazoodle Inc.',
              +				uaCompanyUrl: 'http://www.cazoodle.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=CazoodleBot'
              +			}
              +		},
              +		'747': {
              +			userAgent: 'ShopWiki/1.0 ( +http://www.shopwiki.com/wiki/Help:Bot)',
              +			metadata: {
              +				uaFamily: 'ShopWiki',
              +				uaName: 'ShopWiki/1.0',
              +				uaUrl: 'http://www.shopwiki.com/wiki/Help:Bot',
              +				uaCompany: 'ShopWiki Corp',
              +				uaCompanyUrl: 'http://www.shopwiki.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ShopWiki'
              +			}
              +		},
              +		'749': {
              +			userAgent: 'Blaiz-Bee/2.00.8315 (BE Internet Search Engine http://www.rawgrunt.com)',
              +			metadata: {
              +				uaFamily: 'Blaiz-Bee',
              +				uaName: 'Blaiz-Bee/2.00.8315',
              +				uaUrl: 'http://www.rawgrunt.com/index.html',
              +				uaCompany: 'Blaiz Enterprises',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Blaiz-Bee'
              +			}
              +		},
              +		'752': {
              +			userAgent: 'del.icio.us-thumbnails/1.0 Mozilla/5.0 (compatible; Konqueror/3.4; FreeBSD) KHTML/3.4.2 (like Gecko)',
              +			metadata: {
              +				uaFamily: 'del.icio.us-thumbnails',
              +				uaName: 'del.icio.us-thumbnails/1.0',
              +				uaUrl: '',
              +				uaCompany: 'Yahoo!',
              +				uaCompanyUrl: 'http://www.yahoo.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=del.icio.us-thumbnails'
              +			}
              +		},
              +		'753': {
              +			userAgent: 'Mozilla/5.0 (compatible; Exabot-Images/3.0; +http://www.exabot.com/go/robot)',
              +			metadata: {
              +				uaFamily: 'Exabot',
              +				uaName: 'Exabot-Images/3.0',
              +				uaUrl: 'http://www.exabot.com/go/robot',
              +				uaCompany: 'Exalead S.A.',
              +				uaCompanyUrl: 'http://www.exalead.com/',
              +				uaIcon: 'bot_Exabot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Exabot'
              +			}
              +		},
              +		'754': {
              +			userAgent: 'Snapbot/1.0 (+http://www.snap.com)',
              +			metadata: {
              +				uaFamily: 'Snapbot',
              +				uaName: 'Snapbot/1.0 b',
              +				uaUrl: '',
              +				uaCompany: 'Snap',
              +				uaCompanyUrl: 'http://www.snap.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Snapbot'
              +			}
              +		},
              +		'755': {
              +			userAgent: 'DataFountains/DMOZ Feature Vector Corpus Creator (http://ivia.ucr.edu/useragents.shtml)',
              +			metadata: {
              +				uaFamily: 'DataFountains',
              +				uaName: 'DataFountains at Dmoz b',
              +				uaUrl: 'http://ivia.ucr.edu/useragents.shtml',
              +				uaCompany: 'University of California',
              +				uaCompanyUrl: 'http://www.universityofcalifornia.edu/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=DataFountains'
              +			}
              +		},
              +		'756': {
              +			userAgent: 'HatenaScreenshot/1.0 (checker)',
              +			metadata: {
              +				uaFamily: 'HatenaScreenshot',
              +				uaName: 'HatenaScreenshot/1.0 (checker)',
              +				uaUrl: 'http://screenshot.hatena.ne.jp/help',
              +				uaCompany: 'hatena',
              +				uaCompanyUrl: 'http://www.hatena.ne.jp/company/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=HatenaScreenshot'
              +			}
              +		},
              +		'758': {
              +			userAgent: 'Webscope/Nutch-0.9-dev (http://www.cs.washington.edu/homes/mjc/agent.html)',
              +			metadata: {
              +				uaFamily: 'Webscope Crawler',
              +				uaName: 'Webscope Crawler',
              +				uaUrl: 'http://www.cs.washington.edu/homes/mjc/agent.html',
              +				uaCompany: 'University of Washington Computer Science & Engineering',
              +				uaCompanyUrl: 'http://www.cs.washington.edu/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Webscope Crawler'
              +			}
              +		},
              +		'760': {
              +			userAgent: 'posterus (seek.se) +http://www.seek.se/studio/index.php?id=47&t=details',
              +			metadata: {
              +				uaFamily: 'posterus',
              +				uaName: 'posterus',
              +				uaUrl: 'http://www.seek.se/studio/index.php?id=47&t=details',
              +				uaCompany: 'Seek.se',
              +				uaCompanyUrl: 'http://www.seek.se/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=posterus'
              +			}
              +		},
              +		'761': {
              +			userAgent: 'iaskspider/2.0(+http://iask.com/help/help_index.html)',
              +			metadata: {
              +				uaFamily: 'iaskspider',
              +				uaName: 'iaskspider/2.0',
              +				uaUrl: 'http://iask.com/help/help_index.html',
              +				uaCompany: 'SINA Corporation',
              +				uaCompanyUrl: 'http://corp.sina.com.cn/eng/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=iaskspider'
              +			}
              +		},
              +		'764': {
              +			userAgent: 'IlseBot/1.1',
              +			metadata: {
              +				uaFamily: 'IlseBot',
              +				uaName: 'IlseBot/1.1',
              +				uaUrl: '',
              +				uaCompany: 'ilse.nl',
              +				uaCompanyUrl: 'http://ilse.nl/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=IlseBot'
              +			}
              +		},
              +		'765': {
              +			userAgent: 'WebarooBot (Webaroo Bot; http://64.124.122.252/feedback.html)',
              +			metadata: {
              +				uaFamily: 'WebarooBot',
              +				uaName: 'WebarooBot (Webaroo Bot)',
              +				uaUrl: 'http://www.webaroo.com/company/site-owners',
              +				uaCompany: 'Webaroo Inc.',
              +				uaCompanyUrl: 'http://www.webaroo.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=WebarooBot'
              +			}
              +		},
              +		'768': {
              +			userAgent: 'sogou web spider http://www.sogou.com/docs/help/webmasters.htm#07',
              +			metadata: {
              +				uaFamily: 'sogou spider',
              +				uaName: 'sogou spider',
              +				uaUrl: 'http://www.sogou.com/docs/help/webmasters.htm#07',
              +				uaCompany: 'SOGOU.COM',
              +				uaCompanyUrl: 'http://www.sogou.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=sogou spider'
              +			}
              +		},
              +		'770': {
              +			userAgent: 'sogou web spider(+http://www.sogou.com/docs/help/webmasters.htm#07)',
              +			metadata: {
              +				uaFamily: 'sogou spider',
              +				uaName: 'sogou spider',
              +				uaUrl: 'http://www.sogou.com/docs/help/webmasters.htm#07',
              +				uaCompany: 'SOGOU.COM',
              +				uaCompanyUrl: 'http://www.sogou.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=sogou spider'
              +			}
              +		},
              +		'771': {
              +			userAgent: 'NextGenSearchBot 1 (for information visit http://about.zoominfo.com/About/NextGenSearchBot.aspx)',
              +			metadata: {
              +				uaFamily: 'NextGenSearchBot',
              +				uaName: 'NextGenSearchBot 1',
              +				uaUrl: 'http://www.zoominfo.com/About/misc/NextGenSearchBot.aspx',
              +				uaCompany: 'Zoom Information Inc.',
              +				uaCompanyUrl: 'http://www.zoominfo.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=NextGenSearchBot'
              +			}
              +		},
              +		'773': {
              +			userAgent: 'Sogou web spider/3.0(+http://www.sogou.com/docs/help/webmasters.htm#07)',
              +			metadata: {
              +				uaFamily: 'sogou spider',
              +				uaName: 'Sogou web spider/3.0',
              +				uaUrl: 'http://www.sogou.com/docs/help/webmasters.htm#07',
              +				uaCompany: 'SOGOU.COM',
              +				uaCompanyUrl: 'http://www.sogou.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=sogou spider'
              +			}
              +		},
              +		'774': {
              +			userAgent: 'Mozilla/5.0 (compatible; LinksManager.com_bot +http://linksmanager.com/linkchecker.html)',
              +			metadata: {
              +				uaFamily: 'linksmanager_bot',
              +				uaName: 'linksmanager_bot',
              +				uaUrl: 'http://linksmanager.com/linkchecker.html',
              +				uaCompany: 'CreativeNetVentures, Inc.',
              +				uaCompanyUrl: 'http://cnvi.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=linksmanager_bot'
              +			}
              +		},
              +		'778': {
              +			userAgent: 'LarbinWebCrawler (spider@download11.com)',
              +			metadata: {
              +				uaFamily: 'LemurWebCrawler',
              +				uaName: 'LabrinWebCrawler',
              +				uaUrl: 'http://boston.lti.cs.cmu.edu/crawler_12/',
              +				uaCompany: 'Language Technologies Institute',
              +				uaCompanyUrl: 'http://www.lti.cs.cmu.edu/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=LemurWebCrawler'
              +			}
              +		},
              +		'786': {
              +			userAgent: 'wectar/Nutch-0.9 (wectar - wectar extracted from the glorious web; http://goosebumps4all.net/wectar)',
              +			metadata: {
              +				uaFamily: 'wectar',
              +				uaName: 'wectar/Nutch-0.9',
              +				uaUrl: 'http://wectar.com/',
              +				uaCompany: 'Martin Dudek',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=wectar'
              +			}
              +		},
              +		'788': {
              +			userAgent: 'WebarooBot (Webaroo Bot; http://www.webaroo.com/rooSiteOwners.html)',
              +			metadata: {
              +				uaFamily: 'WebarooBot',
              +				uaName: 'WebarooBot (Webaroo Bot) b',
              +				uaUrl: 'http://www.webaroo.com/company/site-owners',
              +				uaCompany: 'Webaroo Inc.',
              +				uaCompanyUrl: 'http://www.webaroo.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=WebarooBot'
              +			}
              +		},
              +		'789': {
              +			userAgent: 'Bigsearch.ca/Nutch-1.0-dev (Bigsearch.ca Internet Spider; http://www.bigsearch.ca/; info@enhancededge.com)',
              +			metadata: {
              +				uaFamily: 'Bigsearch.ca',
              +				uaName: 'Bigsearch.ca/Nutch-1.0-dev',
              +				uaUrl: '',
              +				uaCompany: 'bigsearch.ca',
              +				uaCompanyUrl: 'http://www.bigsearch.ca/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Bigsearch.ca'
              +			}
              +		},
              +		'791': {
              +			userAgent: 'MSRBOT (http://research.microsoft.com/research/sv/msrbot)',
              +			metadata: {
              +				uaFamily: 'MSRBOT',
              +				uaName: 'MSRBOT c',
              +				uaUrl: 'http://research.microsoft.com/research/sv/msrbot/',
              +				uaCompany: 'Microsoft Corporation',
              +				uaCompanyUrl: 'http://www.microsoft.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MSRBOT'
              +			}
              +		},
              +		'797': {
              +			userAgent: 'Jambot/0.1.1 (Jambot; http://www.jambot.com/blog; crawler@jambot.com)',
              +			metadata: {
              +				uaFamily: 'Jambot',
              +				uaName: 'Jambot/0.1.1',
              +				uaUrl: 'http://www.jambot.com/blog/static.php?page=webmaster-robot',
              +				uaCompany: '',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Jambot'
              +			}
              +		},
              +		'798': {
              +			userAgent: 'VisBot/2.0 (Visvo.com Crawler; http://www.visvo.com/bot.html; bot@visvo.com)',
              +			metadata: {
              +				uaFamily: 'Visbot',
              +				uaName: 'Visbot/2.0',
              +				uaUrl: 'http://www.visvo.com/webmasters.html',
              +				uaCompany: 'Visvo Inc.',
              +				uaCompanyUrl: 'http://www.visvo.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Visbot'
              +			}
              +		},
              +		'804': {
              +			userAgent: 'Francis/2.0 (francis@neomo.de http://www.neomo.de/pages/crawler.php)',
              +			metadata: {
              +				uaFamily: 'Francis',
              +				uaName: 'Francis/2.0',
              +				uaUrl: 'http://www.neomo.de/pages/crawler.php',
              +				uaCompany: 'Neomo GmbH & Co. KG.',
              +				uaCompanyUrl: 'http://www.neomo.de/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Francis'
              +			}
              +		},
              +		'805': {
              +			userAgent: 'cinetic_htdig',
              +			metadata: {
              +				uaFamily: 'ht://Dig',
              +				uaName: 'ht://Dig',
              +				uaUrl: '',
              +				uaCompany: 'The ht://Dig Group',
              +				uaCompanyUrl: 'http://htdig.sourceforge.net/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ht://Dig'
              +			}
              +		},
              +		'807': {
              +			userAgent: 'Mozilla/4.0 (compatible; MSIE is not me; DAUMOA/1.0.1; DAUM Web Robot; Daum Communications Corp., Korea)',
              +			metadata: {
              +				uaFamily: 'Daumoa',
              +				uaName: 'DAUMOA/1.0.1',
              +				uaUrl: 'http://tab.search.daum.net/aboutWebSearch_en.html',
              +				uaCompany: 'Daum Communications Corp.',
              +				uaCompanyUrl: 'http://info.daum.net/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Daumoa'
              +			}
              +		},
              +		'808': {
              +			userAgent: 'favorstarbot/1.0 (+http://favorstar.com/bot.html)',
              +			metadata: {
              +				uaFamily: 'favorstarbot',
              +				uaName: 'favorstarbot/1.0',
              +				uaUrl: 'http://favorstar.com/bot.html',
              +				uaCompany: 'favorstar.com',
              +				uaCompanyUrl: 'http://favorstar.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=favorstarbot'
              +			}
              +		},
              +		'809': {
              +			userAgent: 'FAST Enterprise Crawler 6 used by FAST (jim.mosher@fastsearch.com)',
              +			metadata: {
              +				uaFamily: 'FAST Enterprise Crawler',
              +				uaName: 'FAST Enterprise Crawler/6',
              +				uaUrl: 'http://www.fast.no/glossary.aspx?m=48&amid=415',
              +				uaCompany: 'Fast Search & Transfer',
              +				uaCompanyUrl: 'http://www.fastsearch.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=FAST Enterprise Crawler'
              +			}
              +		},
              +		'811': {
              +			userAgent: 'depspid - the dependency spider',
              +			metadata: {
              +				uaFamily: 'DepSpid',
              +				uaName: 'DepSpid',
              +				uaUrl: 'http://about.depspid.net/',
              +				uaCompany: 'Bjoern Henke',
              +				uaCompanyUrl: 'http://www.bjoernhenke.de/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=DepSpid'
              +			}
              +		},
              +		'812': {
              +			userAgent: 'mozilla/4.0 (compatible; changedetection/1.0 (admin@changedetection.com))',
              +			metadata: {
              +				uaFamily: 'ChangeDetection',
              +				uaName: 'changedetection/1.0',
              +				uaUrl: '',
              +				uaCompany: 'FreeFind.com',
              +				uaCompanyUrl: 'http://www.freefind.com/',
              +				uaIcon: 'bot_ChangeDetection.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ChangeDetection'
              +			}
              +		},
              +		'813': {
              +			userAgent: 'mozilla/4.0 (compatible; myfamilybot/1.0; http://www.ancestry.com/learn/bot.aspx)',
              +			metadata: {
              +				uaFamily: 'MyFamilyBot',
              +				uaName: 'MyFamilyBot/1.0',
              +				uaUrl: 'http://www.ancestry.com/learn/bot.aspx',
              +				uaCompany: 'The Generations Network, Inc.',
              +				uaCompanyUrl: 'http://www.myfamilyinc.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MyFamilyBot'
              +			}
              +		},
              +		'814': {
              +			userAgent: 'navissobot/1.7  (+http://navisso.com/)',
              +			metadata: {
              +				uaFamily: 'navissobot',
              +				uaName: 'navissobot/1.7',
              +				uaUrl: 'http://navisso.com/topics?c=navissobot',
              +				uaCompany: 'Navisso Search',
              +				uaCompanyUrl: 'http://navisso.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=navissobot'
              +			}
              +		},
              +		'815': {
              +			userAgent: 'Mozilla/5.0 (compatible; SnapPreviewBot; en-US; rv:1.8.0.9) Gecko/20061206 Firefox/1.5.0.9',
              +			metadata: {
              +				uaFamily: 'SnapBot',
              +				uaName: 'SnapPreviewBot',
              +				uaUrl: '',
              +				uaCompany: 'Snap',
              +				uaCompanyUrl: 'http://www.snap.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SnapBot'
              +			}
              +		},
              +		'817': {
              +			userAgent: 'Mozilla/5.0 (compatible; BuzzRankingBot/1.0; +http://www.buzzrankingbot.com/)',
              +			metadata: {
              +				uaFamily: 'BuzzRankingBot',
              +				uaName: 'BuzzRankingBot/1.0',
              +				uaUrl: 'http://www.buzzrankingbot.com/',
              +				uaCompany: 'Matthieu Aubry',
              +				uaCompanyUrl: 'http://giik.net/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=BuzzRankingBot'
              +			}
              +		},
              +		'820': {
              +			userAgent: 'lmspider/Nutch-0.9-dev (For research purposes.; www.nuance.com)',
              +			metadata: {
              +				uaFamily: 'lmspider',
              +				uaName: 'lmspider b',
              +				uaUrl: 'http://www.nuance.com/',
              +				uaCompany: 'Nuance Communications, Inc.',
              +				uaCompanyUrl: 'http://www.nuance.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=lmspider'
              +			}
              +		},
              +		'824': {
              +			userAgent: 'ccubee/3.5',
              +			metadata: {
              +				uaFamily: 'ccubee',
              +				uaName: 'ccubee/3.5',
              +				uaUrl: 'http://empyreum.com/technologies/platforms/ccubee/',
              +				uaCompany: 'EMPYREUM k. s.',
              +				uaCompanyUrl: 'http://empyreum.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ccubee'
              +			}
              +		},
              +		'825': {
              +			userAgent: 'Snapbot/1.0 (Snap Shots, +http://www.snap.com)',
              +			metadata: {
              +				uaFamily: 'Snapbot',
              +				uaName: 'Snapbot/1.0 c',
              +				uaUrl: '',
              +				uaCompany: 'Snap',
              +				uaCompanyUrl: 'http://www.snap.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Snapbot'
              +			}
              +		},
              +		'829': {
              +			userAgent: 'Acorn/Nutch-0.9 (Non-Profit Search Engine; acorn.isara.org; acorn at isara dot org)',
              +			metadata: {
              +				uaFamily: 'Acorn',
              +				uaName: 'Acorn/Nutch-0.9',
              +				uaUrl: 'http://acorn.isara.org/',
              +				uaCompany: 'Isara',
              +				uaCompanyUrl: 'http://www.isara.org/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Acorn'
              +			}
              +		},
              +		'832': {
              +			userAgent: 'nestReader/0.2 (discovery; http://echonest.com/reader.shtml; reader at echonest.com)',
              +			metadata: {
              +				uaFamily: 'nestReader',
              +				uaName: 'nestReader/0.2',
              +				uaUrl: 'http://echonest.com/reader.shtml',
              +				uaCompany: 'The Echo Nest Corporation',
              +				uaCompanyUrl: 'http://echonest.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=nestReader'
              +			}
              +		},
              +		'833': {
              +			userAgent: 'boitho.com-dc/0.86 ( http://www.boitho.com/dcbot.html )',
              +			metadata: {
              +				uaFamily: 'boitho.com-dc',
              +				uaName: 'boitho.com-dc/0.86',
              +				uaUrl: 'http://www.boitho.com/dcbot.html',
              +				uaCompany: 'Boitho',
              +				uaCompanyUrl: 'http://www.boitho.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=boitho.com-dc'
              +			}
              +		},
              +		'835': {
              +			userAgent: 'Snappy/1.1 ( http://www.urltrends.com/ )',
              +			metadata: {
              +				uaFamily: 'Snappy',
              +				uaName: 'Snappy/1.1',
              +				uaUrl: 'http://www.urltrends.com/',
              +				uaCompany: 'Xerocity Design Group, LLC.',
              +				uaCompanyUrl: 'http://www.xerocity.com/',
              +				uaIcon: 'bot_snappy.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Snappy'
              +			}
              +		},
              +		'844': {
              +			userAgent: 'great-plains-web-spider/gpws (Flatland Industries Web Spider; http://www.flatlandindustries.com/flatlandbot.php; jason@flatlandindustries.com)',
              +			metadata: {
              +				uaFamily: 'flatlandbot',
              +				uaName: 'flatlandbot c',
              +				uaUrl: 'http://www.flatlandindustries.com/flatlandbot.php',
              +				uaCompany: 'Flatland Industries, Inc.',
              +				uaCompanyUrl: 'http://www.flatlandindustries.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=flatlandbot'
              +			}
              +		},
              +		'851': {
              +			userAgent: 'Mozilla/5.0 (compatible; FunnelBack; http://cyan.funnelback.com/robot.html)',
              +			metadata: {
              +				uaFamily: 'FunnelBack',
              +				uaName: 'FunnelBack',
              +				uaUrl: 'http://cyan.funnelback.com/robot.html',
              +				uaCompany: 'Funnelback Pty Ltd',
              +				uaCompanyUrl: 'http://www.funnelback.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=FunnelBack'
              +			}
              +		},
              +		'856': {
              +			userAgent: 'RedBot/redbot-1.0 (Rediff.com Crawler; redbot at rediff dot com)',
              +			metadata: {
              +				uaFamily: 'RedBot',
              +				uaName: 'RedBot1.0',
              +				uaUrl: '',
              +				uaCompany: 'Rediff.com India Limited.',
              +				uaCompanyUrl: 'http://www.rediff.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=RedBot'
              +			}
              +		},
              +		'859': {
              +			userAgent: 'Mozilla/5.0 (compatible; heritrix/1.12.0 +http://www.accelobot.com)',
              +			metadata: {
              +				uaFamily: 'Accelobot',
              +				uaName: 'Accelobot',
              +				uaUrl: 'http://www.accelobot.com/',
              +				uaCompany: 'NetBase Solutions, Inc.',
              +				uaCompanyUrl: 'http://www.netbase.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Accelobot'
              +			}
              +		},
              +		'861': {
              +			userAgent: 'wectar/Nutch-0.9 (nectar extracted form the glorious web; http://goosebumps4all.net/wectar; see website)',
              +			metadata: {
              +				uaFamily: 'wectar',
              +				uaName: 'wectar/Nutch-0.9 b',
              +				uaUrl: 'http://wectar.com/',
              +				uaCompany: 'Martin Dudek',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=wectar'
              +			}
              +		},
              +		'865': {
              +			userAgent: 'MQBOT/Nutch-0.9-dev (MQBOT Nutch Crawler; http://vwbot.cs.uiuc.edu; mqbot@cs.uiuc.edu)',
              +			metadata: {
              +				uaFamily: 'MQbot',
              +				uaName: 'MQBOT/Nutch-0.9-dev c',
              +				uaUrl: 'http://metaquerier.cs.uiuc.edu/crawler/',
              +				uaCompany: 'University of Illinois at Urbana-Champaign',
              +				uaCompanyUrl: 'http://www.uiuc.edu/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MQbot'
              +			}
              +		},
              +		'872': {
              +			userAgent: 'Willow Internet Crawler by Twotrees V2.1',
              +			metadata: {
              +				uaFamily: 'Willow Internet Crawler',
              +				uaName: 'Willow Internet Crawler 2.1',
              +				uaUrl: '',
              +				uaCompany: 'Twotrees Technologies, LLC.',
              +				uaCompanyUrl: 'http://www.twotrees.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Willow Internet Crawler'
              +			}
              +		},
              +		'873': {
              +			userAgent: 'Netintelligence LiveAssessment - www.netintelligence.com',
              +			metadata: {
              +				uaFamily: 'Netintelligence LiveAssessment',
              +				uaName: 'Netintelligence LiveAssessment',
              +				uaUrl: '',
              +				uaCompany: 'Netintelligence Limited',
              +				uaCompanyUrl: 'http://www.netintelligence.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Netintelligence LiveAssessment'
              +			}
              +		},
              +		'874': {
              +			userAgent: 'Mozilla/5.0 (compatible; SkreemRBot +http://skreemr.com)',
              +			metadata: {
              +				uaFamily: 'SkreemRBot',
              +				uaName: 'SkreemRBot',
              +				uaUrl: '',
              +				uaCompany: 'SkreemR',
              +				uaCompanyUrl: 'http://skreemr.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SkreemRBot'
              +			}
              +		},
              +		'876': {
              +			userAgent: 'great-plains-web-spider/flatlandbot (Flatland Industries Web Robot; http://www.flatlandindustries.com/flatlandbot.php; jason@flatlandindustries.com)',
              +			metadata: {
              +				uaFamily: 'flatlandbot',
              +				uaName: 'flatlandbot b',
              +				uaUrl: 'http://www.flatlandindustries.com/flatlandbot.php',
              +				uaCompany: 'Flatland Industries, Inc.',
              +				uaCompanyUrl: 'http://www.flatlandindustries.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=flatlandbot'
              +			}
              +		},
              +		'877': {
              +			userAgent: 'flatlandbot/flatlandbot (Flatland Industries Web Spider; http://www.flatlandindustries.com/flatlandbot.php; jason@flatlandindustries.com)',
              +			metadata: {
              +				uaFamily: 'flatlandbot',
              +				uaName: 'flatlandbot',
              +				uaUrl: 'http://www.flatlandindustries.com/flatlandbot.php',
              +				uaCompany: 'Flatland Industries, Inc.',
              +				uaCompanyUrl: 'http://www.flatlandindustries.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=flatlandbot'
              +			}
              +		},
              +		'881': {
              +			userAgent: 'Larbin (larbin2.6.3@unspecified.mail)',
              +			metadata: {
              +				uaFamily: 'Larbin',
              +				uaName: 'Larbin/2.6.3',
              +				uaUrl: '',
              +				uaCompany: 'Sebastien Ailleret',
              +				uaCompanyUrl: 'http://larbin.sourceforge.net/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Larbin'
              +			}
              +		},
              +		'882': {
              +			userAgent: 'InternetSeer.com',
              +			metadata: {
              +				uaFamily: 'InternetSeer',
              +				uaName: 'InternetSeer (Web Monitor)',
              +				uaUrl: '',
              +				uaCompany: 'InternetSeer',
              +				uaCompanyUrl: 'http://internetseer.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=InternetSeer'
              +			}
              +		},
              +		'886': {
              +			userAgent: 'panscient.com',
              +			metadata: {
              +				uaFamily: 'Panscient web crawler',
              +				uaName: 'Panscient web crawler',
              +				uaUrl: 'http://panscient.com/faq.html',
              +				uaCompany: 'Panscient, Inc.',
              +				uaCompanyUrl: 'http://panscient.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Panscient web crawler'
              +			}
              +		},
              +		'888': {
              +			userAgent: 'void-bot/0.1 (bot@void.be; http://www.void.be/)',
              +			metadata: {
              +				uaFamily: 'void-bot',
              +				uaName: 'void-bot/0.1',
              +				uaUrl: 'http://www.void.be/void-bot.html',
              +				uaCompany: 'Void Security',
              +				uaCompanyUrl: 'http://www.void.be/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=void-bot'
              +			}
              +		},
              +		'890': {
              +			userAgent: 'Mozilla/2.0 (compatible; Ask Jeeves/Teoma; http://about.ask.com/en/docs/about/webmasters.shtml)',
              +			metadata: {
              +				uaFamily: 'Ask Jeeves/Teoma',
              +				uaName: 'Ask Jeeves/Teoma - d',
              +				uaUrl: 'http://about.ask.com/en/docs/about/webmasters.shtml',
              +				uaCompany: 'Ask Jeeves Inc.',
              +				uaCompanyUrl: 'http://about.ask.com/en/docs/about/index.shtml',
              +				uaIcon: 'bot_AskJeeves.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Ask Jeeves/Teoma'
              +			}
              +		},
              +		'891': {
              +			userAgent: 'Mozilla/5.0 (compatible; Yoono; http://www.yoono.com/)',
              +			metadata: {
              +				uaFamily: 'Yoono Bot',
              +				uaName: 'Yoono Bot',
              +				uaUrl: 'http://blog.yoono.com/blog/?page_id=40',
              +				uaCompany: 'Yoono Team',
              +				uaCompanyUrl: 'http://www.yoono.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Yoono Bot'
              +			}
              +		},
              +		'892': {
              +			userAgent: 'Accelobot',
              +			metadata: {
              +				uaFamily: 'Accelobot',
              +				uaName: 'Accelobot',
              +				uaUrl: 'http://www.accelobot.com/',
              +				uaCompany: 'Accelovation, Inc.',
              +				uaCompanyUrl: 'http://www.accelovation.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Accelobot'
              +			}
              +		},
              +		'902': {
              +			userAgent: 'WebAlta Crawler/1.3.33 (http://www.webalta.net/ru/about_webmaster.html) (Windows; U; Windows NT 5.1; ru-RU)',
              +			metadata: {
              +				uaFamily: 'WebAlta Crawler',
              +				uaName: 'WebAlta Crawler/1.3.33',
              +				uaUrl: 'http://www.webalta.net/ru/about_webmaster.html',
              +				uaCompany: 'Webalta',
              +				uaCompanyUrl: 'http://www.webalta.ru/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=WebAlta Crawler'
              +			}
              +		},
              +		'911': {
              +			userAgent: 'Sirketcebot/v.01 (http://www.sirketce.com/bot.html)',
              +			metadata: {
              +				uaFamily: 'Sirketce/Busiverse',
              +				uaName: 'Sirketcebot/v.01',
              +				uaUrl: 'http://www.sirketce.com/bot.html',
              +				uaCompany: 'BERI.L Teknoloji Ltd.',
              +				uaCompanyUrl: 'http://www.berilteknoloji.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Sirketce/Busiverse'
              +			}
              +		},
              +		'913': {
              +			userAgent: 'ZoomSpider - wrensoft.com [ZSEBOT]',
              +			metadata: {
              +				uaFamily: 'ZoomSpider (ZSEBOT)',
              +				uaName: 'ZoomSpider (ZSEBOT)',
              +				uaUrl: 'http://wrensoft.com/zoom/support/useragent.html',
              +				uaCompany: 'PassMark Software Pty Ltd.',
              +				uaCompanyUrl: 'http://www.passmark.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ZoomSpider (ZSEBOT)'
              +			}
              +		},
              +		'914': {
              +			userAgent: 'Mozilla/5.0 (compatible; Quantcastbot/1.0; www.quantcast.com)',
              +			metadata: {
              +				uaFamily: 'Quantcastbot',
              +				uaName: 'Quantcastbot/1.0',
              +				uaUrl: '',
              +				uaCompany: 'Quantcast Corporation',
              +				uaCompanyUrl: 'http://www.quantcast.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Quantcastbot'
              +			}
              +		},
              +		'917': {
              +			userAgent: 'NutchCVS/Nutch-0.9 (Nutch; http://lucene.apache.org/nutch/bot.html; nutch-agent@lucene.apache.org)',
              +			metadata: {
              +				uaFamily: 'Nutch',
              +				uaName: 'NutchCSV/0.9',
              +				uaUrl: 'http://www.nutch.org/docs/en/bot.html',
              +				uaCompany: 'lucene',
              +				uaCompanyUrl: 'http://lucene.apache.org/',
              +				uaIcon: 'bot_Nutch.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Nutch'
              +			}
              +		},
              +		'920': {
              +			userAgent: 'Gigabot/3.0 (http://www.gigablast.com/spider.html)',
              +			metadata: {
              +				uaFamily: 'Gigabot',
              +				uaName: 'Gigabot/3.0',
              +				uaUrl: 'http://www.gigablast.com/spider.html',
              +				uaCompany: 'Gigablast Inc',
              +				uaCompanyUrl: 'http://www.gigablast.com/',
              +				uaIcon: 'bot_gigabot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Gigabot'
              +			}
              +		},
              +		'921': {
              +			userAgent: 'Snapbot/1.0 (Site Search Crawler, +http://www.snap.com)',
              +			metadata: {
              +				uaFamily: 'Snapbot',
              +				uaName: 'Snapbot/1.0 d',
              +				uaUrl: '',
              +				uaCompany: 'Snap',
              +				uaCompanyUrl: 'http://www.snap.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Snapbot'
              +			}
              +		},
              +		'922': {
              +			userAgent: 'WebAlta Crawler/1.3.34 (http://www.webalta.net/ru/about_webmaster.html) (Windows; U; Windows NT 5.1; ru-RU)',
              +			metadata: {
              +				uaFamily: 'WebAlta Crawler',
              +				uaName: 'WebAlta Crawler/1.3.34',
              +				uaUrl: 'http://www.webalta.net/ru/about_webmaster.html',
              +				uaCompany: 'Webalta',
              +				uaCompanyUrl: 'http://www.webalta.ru/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=WebAlta Crawler'
              +			}
              +		},
              +		'925': {
              +			userAgent: 'great-plains-web-spider/flatlandbot (Flatland Industries Web Spider; http://www.flatlandindustries.com/flatlandbot.php; jason@flatlandindustries.com)',
              +			metadata: {
              +				uaFamily: 'flatlandbot',
              +				uaName: 'flatlandbot d',
              +				uaUrl: 'http://www.flatlandindustries.com/flatlandbot.php',
              +				uaCompany: 'Flatland Industries, Inc.',
              +				uaCompanyUrl: 'http://www.flatlandindustries.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=flatlandbot'
              +			}
              +		},
              +		'927': {
              +			userAgent: 'holmes/3.11 (OnetSzukaj/5.0; +http://szukaj.onet.pl)',
              +			metadata: {
              +				uaFamily: 'Holmes',
              +				uaName: 'holmes/3.11 - onet.pl',
              +				uaUrl: 'http://www.ucw.cz/holmes/',
              +				uaCompany: 'Martin Mare\u0161 and Robert \u0160palek',
              +				uaCompanyUrl: 'http://www.ucw.cz/holmes/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Holmes'
              +			}
              +		},
              +		'928': {
              +			userAgent: 'CazoodleBot/Nutch-0.9-dev (CazoodleBot Crawler; http://www.cazoodle.com/cazoodlebot; cazoodlebot@cazoodle.com)',
              +			metadata: {
              +				uaFamily: 'CazoodleBot',
              +				uaName: 'CazoodleBot c',
              +				uaUrl: 'http://www.cazoodle.com/cazoodlebot.php',
              +				uaCompany: 'Cazoodle Inc.',
              +				uaCompanyUrl: 'http://www.cazoodle.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=CazoodleBot'
              +			}
              +		},
              +		'929': {
              +			userAgent: 'VWBOT/Nutch-0.9-dev (VWBOT Nutch Crawler; http://vwbot.cs.uiuc.edu; vwbot@cs.uiuc.edu)',
              +			metadata: {
              +				uaFamily: 'VWBot',
              +				uaName: 'VWBot/Nutch-0.9-dev',
              +				uaUrl: 'http://vwbot.cs.uiuc.edu/',
              +				uaCompany: 'University of Illinois at Urbana-Champaign',
              +				uaCompanyUrl: 'http://www.cs.uiuc.edu/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=VWBot'
              +			}
              +		},
              +		'934': {
              +			userAgent: 'Spock Crawler (http://www.spock.com/crawler)',
              +			metadata: {
              +				uaFamily: 'Spock Crawler',
              +				uaName: 'Spock Crawler',
              +				uaUrl: 'http://www.spock.com/crawler',
              +				uaCompany: 'spock.com',
              +				uaCompanyUrl: 'http://www.spock.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Spock Crawler'
              +			}
              +		},
              +		'938': {
              +			userAgent: 'Mozilla/4.0 (compatible; DepSpid/5.10; +http://about.depspid.net)',
              +			metadata: {
              +				uaFamily: 'DepSpid',
              +				uaName: 'DepSpid/5.10',
              +				uaUrl: 'http://about.depspid.net/',
              +				uaCompany: 'Bjoern Henke',
              +				uaCompanyUrl: 'http://www.bjoernhenke.de/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=DepSpid'
              +			}
              +		},
              +		'959': {
              +			userAgent: 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1;  http://www.changedetection.com/bot.html )',
              +			metadata: {
              +				uaFamily: 'ChangeDetection',
              +				uaName: 'ChangeDetection',
              +				uaUrl: 'http://www.changedetection.com/bot.html',
              +				uaCompany: 'FreeFind.com',
              +				uaCompanyUrl: 'http://www.freefind.com/',
              +				uaIcon: 'bot_ChangeDetection.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ChangeDetection'
              +			}
              +		},
              +		'961': {
              +			userAgent: 'textractor.harvester/h5/1.0 (+http://ufal.mff.cuni.cz/project/textractor/, textractor@ufal.mff.cuni.cz)',
              +			metadata: {
              +				uaFamily: 'textractor',
              +				uaName: 'textractor.harvester/h5/1.0',
              +				uaUrl: 'http://ufal.mff.cuni.cz/project/textractor/',
              +				uaCompany: 'Institute of Formal and Applied Linguistics (\xdaFAL)',
              +				uaCompanyUrl: 'http://ufal.mff.cuni.cz/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=textractor'
              +			}
              +		},
              +		'962': {
              +			userAgent: 'textractor.harvester/h39/1.0 (+http://ufal.mff.cuni.cz/project/textractor/, textractor@ufal.mff.cuni.cz)',
              +			metadata: {
              +				uaFamily: 'textractor',
              +				uaName: 'textractor.harvester/h39/1.0',
              +				uaUrl: 'http://ufal.mff.cuni.cz/project/textractor/',
              +				uaCompany: 'Institute of Formal and Applied Linguistics (\xdaFAL)',
              +				uaCompanyUrl: 'http://ufal.mff.cuni.cz/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=textractor'
              +			}
              +		},
              +		'963': {
              +			userAgent: 'textractor.harvester/h37/1.0 (+http://ufal.mff.cuni.cz/project/textractor/, textractor@ufal.mff.cuni.cz)',
              +			metadata: {
              +				uaFamily: 'textractor',
              +				uaName: 'textractor.harvester/h37/1.0',
              +				uaUrl: 'http://ufal.mff.cuni.cz/project/textractor/',
              +				uaCompany: 'Institute of Formal and Applied Linguistics (\xdaFAL)',
              +				uaCompanyUrl: 'http://ufal.mff.cuni.cz/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=textractor'
              +			}
              +		},
              +		'964': {
              +			userAgent: 'textractor.harvester/h38/1.0 (+http://ufal.mff.cuni.cz/project/textractor/, textractor@ufal.mff.cuni.cz)',
              +			metadata: {
              +				uaFamily: 'textractor',
              +				uaName: 'textractor.harvester/h38/1.0',
              +				uaUrl: 'http://ufal.mff.cuni.cz/project/textractor/',
              +				uaCompany: 'Institute of Formal and Applied Linguistics (\xdaFAL)',
              +				uaCompanyUrl: 'http://ufal.mff.cuni.cz/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=textractor'
              +			}
              +		},
              +		'965': {
              +			userAgent: 'textractor.harvester/h12/1.0 (+http://ufal.mff.cuni.cz/project/textractor/, textractor@ufal.mff.cuni.cz)',
              +			metadata: {
              +				uaFamily: 'textractor',
              +				uaName: 'textractor.harvester/h12/1.0',
              +				uaUrl: 'http://ufal.mff.cuni.cz/project/textractor/',
              +				uaCompany: 'Institute of Formal and Applied Linguistics (\xdaFAL)',
              +				uaCompanyUrl: 'http://ufal.mff.cuni.cz/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=textractor'
              +			}
              +		},
              +		'966': {
              +			userAgent: 'textractor.harvester/h34/1.0 (+http://ufal.mff.cuni.cz/project/textractor/, textractor@ufal.mff.cuni.cz)',
              +			metadata: {
              +				uaFamily: 'textractor',
              +				uaName: 'textractor.harvester/h34/1.0',
              +				uaUrl: 'http://ufal.mff.cuni.cz/project/textractor/',
              +				uaCompany: 'Institute of Formal and Applied Linguistics (\xdaFAL)',
              +				uaCompanyUrl: 'http://ufal.mff.cuni.cz/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=textractor'
              +			}
              +		},
              +		'967': {
              +			userAgent: 'Mozilla/4.0 (compatible; MSIE enviable; DAUMOA/1.0.1; DAUM Web Robot; Daum Communications Corp., Korea; +http://ws.daum.net/aboutkr.html)',
              +			metadata: {
              +				uaFamily: 'Daumoa',
              +				uaName: 'DAUMOA/1.0.1 b',
              +				uaUrl: 'http://tab.search.daum.net/aboutWebSearch_en.html',
              +				uaCompany: 'Daum Communications Corp.',
              +				uaCompanyUrl: 'http://info.daum.net/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Daumoa'
              +			}
              +		},
              +		'969': {
              +			userAgent: 'CazoodleBot/CazoodleBot-0.1 (CazoodleBot Crawler; http://www.cazoodle.com/cazoodlebot; cazoodlebot@cazoodle.com)',
              +			metadata: {
              +				uaFamily: 'CazoodleBot',
              +				uaName: 'CazoodleBot-0.1',
              +				uaUrl: 'http://www.cazoodle.com/cazoodlebot.php',
              +				uaCompany: 'Cazoodle Inc.',
              +				uaCompanyUrl: 'http://www.cazoodle.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=CazoodleBot'
              +			}
              +		},
              +		'977': {
              +			userAgent: 'multicrawler (+http://sw.deri.org/2006/04/multicrawler/robots.html)',
              +			metadata: {
              +				uaFamily: 'MultiCrawler',
              +				uaName: 'MultiCrawler',
              +				uaUrl: 'http://sw.deri.org/2006/04/multicrawler/robots.html',
              +				uaCompany: 'Semantic Web Search Engine',
              +				uaCompanyUrl: 'http://swse.org/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MultiCrawler'
              +			}
              +		},
              +		'982': {
              +			userAgent: 'Mediapartners-Google',
              +			metadata: {
              +				uaFamily: 'Googlebot',
              +				uaName: 'Mediapartners-Google',
              +				uaUrl: 'http://support.google.com/webmasters/bin/answer.py?hl=en&answer=1061943',
              +				uaCompany: 'Google Inc.',
              +				uaCompanyUrl: 'http://www.google.com/',
              +				uaIcon: 'bot_googlebot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Googlebot'
              +			}
              +		},
              +		'994': {
              +			userAgent: 'MnoGoSearch/3.3.2',
              +			metadata: {
              +				uaFamily: 'MnoGoSearch',
              +				uaName: 'MnoGoSearch/3.3.2',
              +				uaUrl: 'http://www.mnogosearch.org/products.html',
              +				uaCompany: 'Lavtech.Com',
              +				uaCompanyUrl: 'http://www.lavtech.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MnoGoSearch'
              +			}
              +		},
              +		'999': {
              +			userAgent: 'Speedy Spider (http://www.entireweb.com/about/search_tech/speedy_spider/)',
              +			metadata: {
              +				uaFamily: 'Speedy',
              +				uaName: 'Speedy Spider',
              +				uaUrl: '',
              +				uaCompany: 'Entireweb Sweden AB',
              +				uaCompanyUrl: 'http://www.entireweb.com/',
              +				uaIcon: 'bot_Speedy.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Speedy'
              +			}
              +		},
              +		'1005': {
              +			userAgent: 'FAST Enterprise Crawler 6 used by Virk.dk - udvikling (thomas.bentzen@capgemini.com)',
              +			metadata: {
              +				uaFamily: 'FAST Enterprise Crawler',
              +				uaName: 'FAST Enterprise Crawler 6 at virk.dk',
              +				uaUrl: 'http://www.fast.no/glossary.aspx?m=48&amid=415',
              +				uaCompany: 'Fast Search & Transfer',
              +				uaCompanyUrl: 'http://www.fastsearch.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=FAST Enterprise Crawler'
              +			}
              +		},
              +		'1023': {
              +			userAgent: 'ccubee/2008',
              +			metadata: {
              +				uaFamily: 'ccubee',
              +				uaName: 'ccubee/2008',
              +				uaUrl: 'http://empyreum.com/technologies/platforms/ccubee/',
              +				uaCompany: 'EMPYREUM k. s.',
              +				uaCompanyUrl: 'http://empyreum.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ccubee'
              +			}
              +		},
              +		'1024': {
              +			userAgent: 'MSRBOT (http://research.microsoft.com/research/sv/msrbot/',
              +			metadata: {
              +				uaFamily: 'MSRBOT',
              +				uaName: 'MSRBOT d',
              +				uaUrl: 'http://research.microsoft.com/research/sv/msrbot/',
              +				uaCompany: 'Microsoft Corporation',
              +				uaCompanyUrl: 'http://www.microsoft.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MSRBOT'
              +			}
              +		},
              +		'1027': {
              +			userAgent: 'Enterprise_Search/1.00.143;MSSQL (http://www.innerprise.net/es-spider.asp)',
              +			metadata: {
              +				uaFamily: 'Enterprise_Search',
              +				uaName: 'Enterprise_Search/1.00.143',
              +				uaUrl: 'http://www.innerprise.net/hosted-bi.asp',
              +				uaCompany: 'Innerprise',
              +				uaCompanyUrl: 'http://www.innerprise.net/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Enterprise_Search'
              +			}
              +		},
              +		'1035': {
              +			userAgent: 'FyberSpider/1.2 (http://www.fybersearch.com/fyberspider.php)',
              +			metadata: {
              +				uaFamily: 'FyberSpider',
              +				uaName: 'FyberSpider/1.2',
              +				uaUrl: 'http://www.fybersearch.com/fyberspider.php',
              +				uaCompany: 'FyberSearch',
              +				uaCompanyUrl: 'http://www.fybersearch.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=FyberSpider'
              +			}
              +		},
              +		'1037': {
              +			userAgent: 'owsBot/0.1 (Nutch; www.oneworldstreet.com; nutch-agent@lucene.apache.org)',
              +			metadata: {
              +				uaFamily: 'owsBot',
              +				uaName: 'owsBot/0.1',
              +				uaUrl: '',
              +				uaCompany: 'OneWorldStreet.com',
              +				uaCompanyUrl: 'http://www.oneworldstreet.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=owsBot'
              +			}
              +		},
              +		'1040': {
              +			userAgent: 'owsBot/0.2 (owsBot; www.oneworldstreet.com; owsBot)',
              +			metadata: {
              +				uaFamily: 'owsBot',
              +				uaName: 'owsBot/0.2',
              +				uaUrl: '',
              +				uaCompany: 'OneWorldStreet.com',
              +				uaCompanyUrl: 'http://www.oneworldstreet.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=owsBot'
              +			}
              +		},
              +		'1042': {
              +			userAgent: 'ASAHA Search Engine Turkey V.001 (http://www.asaha.com/)',
              +			metadata: {
              +				uaFamily: 'ASAHA Search Engine Turkey',
              +				uaName: 'ASAHA Search Engine Turkey V.001',
              +				uaUrl: 'http://www.asaha.com/beta/',
              +				uaCompany: 'asaha.com',
              +				uaCompanyUrl: 'http://www.asaha.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ASAHA Search Engine Turkey'
              +			}
              +		},
              +		'1044': {
              +			userAgent: 'ICF_Site_Crawler+(see+http://www.infocenter.fi/spiderinfo.html)',
              +			metadata: {
              +				uaFamily: 'ICF_Site_Crawler',
              +				uaName: 'ICF_Site_Crawler',
              +				uaUrl: 'http://www.infocenter.fi/spiderinfo.html',
              +				uaCompany: 'Info Center Finland Ltd.',
              +				uaCompanyUrl: 'http://www.infocenter.fi/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ICF_Site_Crawler'
              +			}
              +		},
              +		'1052': {
              +			userAgent: 'Giant/1.0 (Openmaru bot; robot@openmaru.com)',
              +			metadata: {
              +				uaFamily: 'Giant/1.0',
              +				uaName: 'Giant/1.0',
              +				uaUrl: '',
              +				uaCompany: 'openmaru studio',
              +				uaCompanyUrl: 'http://www.openmaru.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Giant/1.0'
              +			}
              +		},
              +		'1061': {
              +			userAgent: 'Factbot 1.09',
              +			metadata: {
              +				uaFamily: 'factbot',
              +				uaName: 'Factbot 1.09',
              +				uaUrl: 'http://www.factbites.com/webmasters.php',
              +				uaCompany: 'Rapid Intelligence Pty Ltd',
              +				uaCompanyUrl: 'http://www.rapint.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=factbot'
              +			}
              +		},
              +		'1072': {
              +			userAgent: 'Mozilla/5.0 (Windows;) NimbleCrawler 2.0.2 obeys UserAgent NimbleCrawler For problems contact: crawler@healthline.com',
              +			metadata: {
              +				uaFamily: 'NimbleCrawler',
              +				uaName: 'NimbleCrawler/2.0.2',
              +				uaUrl: '',
              +				uaCompany: 'Healthline Networks, Inc.',
              +				uaCompanyUrl: 'http://www.healthline.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=NimbleCrawler'
              +			}
              +		},
              +		'1078': {
              +			userAgent: 'SygolBot http://www.sygol.com',
              +			metadata: {
              +				uaFamily: 'SygolBot',
              +				uaName: 'SygolBot',
              +				uaUrl: 'http://www.sygol.com/SygolBot.asp',
              +				uaCompany: 'Giorgio Galeotti',
              +				uaCompanyUrl: 'http://www.sygol.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SygolBot'
              +			}
              +		},
              +		'1089': {
              +			userAgent: "HouxouCrawler/Nutch-0.9 (houxou.com's nutch-based crawler which serves special interest on-line communities; http://www.houxou.com/crawler; crawler at houxou dot com)",
              +			metadata: {
              +				uaFamily: 'Nutch',
              +				uaName: 'Nutch/0.9 at houxou.com',
              +				uaUrl: 'http://www.nutch.org/docs/en/bot.html',
              +				uaCompany: 'lucene',
              +				uaCompanyUrl: 'http://lucene.apache.org/',
              +				uaIcon: 'bot_Nutch.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Nutch'
              +			}
              +		},
              +		'1092': {
              +			userAgent: 'Steeler/3.3 (http://www.tkl.iis.u-tokyo.ac.jp/~crawler/)',
              +			metadata: {
              +				uaFamily: 'Steeler',
              +				uaName: 'Steeler/3.3',
              +				uaUrl: 'http://www.tkl.iis.u-tokyo.ac.jp/~crawler/',
              +				uaCompany: 'Kitsuregawa Laboratory, The University of Tokyo',
              +				uaCompanyUrl: 'http://www.tkl.iis.u-tokyo.ac.jp/',
              +				uaIcon: 'bot_Steeler.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Steeler'
              +			}
              +		},
              +		'1095': {
              +			userAgent: 'nrsbot/5.0(loopip.com/robot.html)',
              +			metadata: {
              +				uaFamily: 'NetResearchServer',
              +				uaName: 'nrsbot/5.0',
              +				uaUrl: 'http://loopip.com/robot.html',
              +				uaCompany: 'LoopIP LLC',
              +				uaCompanyUrl: 'http://loopip.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=NetResearchServer'
              +			}
              +		},
              +		'1102': {
              +			userAgent: 'NextGenSearchBot 1 (for information visit http://www.zoominfo.com/About/misc/NextGenSearchBot.aspx)',
              +			metadata: {
              +				uaFamily: 'NextGenSearchBot',
              +				uaName: 'NextGenSearchBot 1 b',
              +				uaUrl: 'http://www.zoominfo.com/About/misc/NextGenSearchBot.aspx',
              +				uaCompany: 'Zoom Information Inc.',
              +				uaCompanyUrl: 'http://www.zoominfo.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=NextGenSearchBot'
              +			}
              +		},
              +		'1115': {
              +			userAgent: 'Mozilla/5.0 (compatible; egothor/11.0d; +http://ego.ms.mff.cuni.cz/)',
              +			metadata: {
              +				uaFamily: 'egothor',
              +				uaName: 'egothor/11.0d',
              +				uaUrl: 'http://ego.ms.mff.cuni.cz/',
              +				uaCompany: 'Katedra softwarov\xe9ho in\u017een\xfdrstv\xed Univerzity Karlovi',
              +				uaCompanyUrl: 'http://kocour.ms.mff.cuni.cz/cs/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=egothor'
              +			}
              +		},
              +		'1133': {
              +			userAgent: 'GeonaBot/1.2; http://www.geona.com/',
              +			metadata: {
              +				uaFamily: 'GeonaBot',
              +				uaName: 'GeonaBot/1.2',
              +				uaUrl: 'http://www.geona.net/about.htm',
              +				uaCompany: 'Gold Vision Communications',
              +				uaCompanyUrl: 'http://www.goldvision.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=GeonaBot'
              +			}
              +		},
              +		'1137': {
              +			userAgent: 'Mozilla/4.0 (compatible; DepSpid/5.24; +http://about.depspid.net)',
              +			metadata: {
              +				uaFamily: 'DepSpid',
              +				uaName: 'DepSpid/5.24',
              +				uaUrl: 'http://about.depspid.net/',
              +				uaCompany: 'Bjoern Henke',
              +				uaCompanyUrl: 'http://www.bjoernhenke.de/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=DepSpid'
              +			}
              +		},
              +		'1150': {
              +			userAgent: 'Mozilla/4.0 (compatible; MSIE enviable; DAUMOA 2.0; DAUM Web Robot; Daum Communications Corp., Korea; +http://ws.daum.net/aboutkr.html)',
              +			metadata: {
              +				uaFamily: 'Daumoa',
              +				uaName: 'Daumoa/2.0',
              +				uaUrl: 'http://tab.search.daum.net/aboutWebSearch_en.html',
              +				uaCompany: 'Daum Communications Corp.',
              +				uaCompanyUrl: 'http://info.daum.net/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Daumoa'
              +			}
              +		},
              +		'1164': {
              +			userAgent: 'Mozilla/4.0 (compatible; DepSpid/5.25; +http://about.depspid.net)',
              +			metadata: {
              +				uaFamily: 'DepSpid',
              +				uaName: 'DepSpid/5.25',
              +				uaUrl: 'http://about.depspid.net/',
              +				uaCompany: 'Bjoern Henke',
              +				uaCompanyUrl: 'http://www.bjoernhenke.de/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=DepSpid'
              +			}
              +		},
              +		'1169': {
              +			userAgent: 'Mozilla/5.0 (compatible; egothor/11.0d; +https://kocour.ms.mff.cuni.cz/ego/)',
              +			metadata: {
              +				uaFamily: 'egothor',
              +				uaName: 'egothor/11.0d b',
              +				uaUrl: 'http://ego.ms.mff.cuni.cz/',
              +				uaCompany: 'Katedra softwarov\xe9ho in\u017een\xfdrstv\xed Univerzity Karlovi',
              +				uaCompanyUrl: 'http://kocour.ms.mff.cuni.cz/cs/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=egothor'
              +			}
              +		},
              +		'1180': {
              +			userAgent: 'msnbot/1.1 (+http://search.msn.com/msnbot.htm)',
              +			metadata: {
              +				uaFamily: 'MSNBot',
              +				uaName: 'MSNBot/1.1',
              +				uaUrl: 'http://search.msn.com/msnbot.htm',
              +				uaCompany: 'Microsoft Corporation',
              +				uaCompanyUrl: 'http://www.microsoft.com/',
              +				uaIcon: 'bot_msnbot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MSNBot'
              +			}
              +		},
              +		'1197': {
              +			userAgent: 'ichiro/3.0 (http://help.goo.ne.jp/door/crawler.html)',
              +			metadata: {
              +				uaFamily: 'ichiro',
              +				uaName: 'ichiro/3.0',
              +				uaUrl: 'http://search.goo.ne.jp/option/use/sub4/sub4-1/',
              +				uaCompany: 'NTT-Resonant Inc.',
              +				uaCompanyUrl: 'http://www.nttr.co.jp/',
              +				uaIcon: 'bot_ichiro.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ichiro'
              +			}
              +		},
              +		'1198': {
              +			userAgent: 'EnaBot/1.1 (http://www.enaball.com/crawler.html)',
              +			metadata: {
              +				uaFamily: 'EnaBot',
              +				uaName: 'EnaBot/1.1',
              +				uaUrl: 'http://www.enaball.com/crawler.html',
              +				uaCompany: 'Enaball Inc.',
              +				uaCompanyUrl: 'http://www.enaball.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=EnaBot'
              +			}
              +		},
              +		'1205': {
              +			userAgent: 'EnaBot/1.2 (http://www.enaball.com/crawler.html)',
              +			metadata: {
              +				uaFamily: 'EnaBot',
              +				uaName: 'EnaBot/1.2',
              +				uaUrl: 'http://www.enaball.com/crawler.html',
              +				uaCompany: 'Enaball Inc.',
              +				uaCompanyUrl: 'http://www.enaball.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=EnaBot'
              +			}
              +		},
              +		'1210': {
              +			userAgent: 'Mahiti.Com/Mahiti Crawler-1.0 (Mahiti.Com; http://mahiti.com ; mahiti.com)',
              +			metadata: {
              +				uaFamily: 'Mahiti Crawler',
              +				uaName: 'Mahiti Crawler-1.0',
              +				uaUrl: '',
              +				uaCompany: 'Mahiti.Com',
              +				uaCompanyUrl: 'http://mahiti.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Mahiti Crawler'
              +			}
              +		},
              +		'1213': {
              +			userAgent: 'MLBot (www.metadatalabs.com)',
              +			metadata: {
              +				uaFamily: 'MLBot',
              +				uaName: 'MLBot',
              +				uaUrl: 'http://www.metadatalabs.com/mlbot/',
              +				uaCompany: 'metadata labs',
              +				uaCompanyUrl: 'http://www.metadatalabs.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MLBot'
              +			}
              +		},
              +		'1214': {
              +			userAgent: 'Mozilla/4.0 (compatible; DepSpid/5.26; +http://about.depspid.net)',
              +			metadata: {
              +				uaFamily: 'DepSpid',
              +				uaName: 'DepSpid/5.26',
              +				uaUrl: 'http://about.depspid.net/',
              +				uaCompany: 'Bjoern Henke',
              +				uaCompanyUrl: 'http://www.bjoernhenke.de/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=DepSpid'
              +			}
              +		},
              +		'1220': {
              +			userAgent: 'IRLbot/3.0 (compatible; MSIE 6.0; http://irl.cs.tamu.edu/crawler/)',
              +			metadata: {
              +				uaFamily: 'IRLbot',
              +				uaName: 'IRLbot/3.0 b',
              +				uaUrl: 'http://irl.cs.tamu.edu/crawler/',
              +				uaCompany: 'Texas A&M University',
              +				uaCompanyUrl: 'http://www.tamu.edu/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=IRLbot'
              +			}
              +		},
              +		'1225': {
              +			userAgent: 'DuckDuckBot/1.0; (+http://duckduckgo.com/duckduckbot.html)',
              +			metadata: {
              +				uaFamily: 'DuckDuckBot',
              +				uaName: 'DuckDuckBot/1.0',
              +				uaUrl: 'http://duckduckgo.com/duckduckbot.html',
              +				uaCompany: 'Duck Duck Go, Inc.',
              +				uaCompanyUrl: 'http://duckduckgo.com/blog/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=DuckDuckBot'
              +			}
              +		},
              +		'1238': {
              +			userAgent: 'CCBot/1.0 (+http://www.commoncrawl.org/bot.html)',
              +			metadata: {
              +				uaFamily: 'CCBot',
              +				uaName: 'CCBot/1.0',
              +				uaUrl: 'http://commoncrawl.org/research/',
              +				uaCompany: 'CommonCrawl Foundation',
              +				uaCompanyUrl: 'http://www.commoncrawl.org/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=CCBot'
              +			}
              +		},
              +		'1247': {
              +			userAgent: 'MnoGoSearch/3.3.6',
              +			metadata: {
              +				uaFamily: 'MnoGoSearch',
              +				uaName: 'MnoGoSearch/3.3.6',
              +				uaUrl: 'http://www.mnogosearch.org/products.html',
              +				uaCompany: 'Lavtech.Com',
              +				uaCompanyUrl: 'http://www.lavtech.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MnoGoSearch'
              +			}
              +		},
              +		'1270': {
              +			userAgent: 'Mozilla/5.0 (compatible; Charlotte/1.1; http://www.searchme.com/support/)',
              +			metadata: {
              +				uaFamily: 'Charlotte',
              +				uaName: 'Charlotte/1.1',
              +				uaUrl: 'http://www.searchme.com/support/)',
              +				uaCompany: 'Searchme, Inc.',
              +				uaCompanyUrl: 'http://www.searchme.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Charlotte'
              +			}
              +		},
              +		'1273': {
              +			userAgent: 'Acoon-Robot 4.0.0RC2 (http://www.acoon.de)',
              +			metadata: {
              +				uaFamily: 'AcoonBot',
              +				uaName: 'Acoon-Robot 4.0.0RC2',
              +				uaUrl: 'http://www.acoon.de/robot.asp',
              +				uaCompany: 'Acoon GmbH',
              +				uaCompanyUrl: 'http://www.acoon.de/',
              +				uaIcon: 'bot_Acoon.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=AcoonBot'
              +			}
              +		},
              +		'1282': {
              +			userAgent: 'Acoon-Robot 4.0.1 (http://www.acoon.de)',
              +			metadata: {
              +				uaFamily: 'AcoonBot',
              +				uaName: 'Acoon-Robot 4.0.1',
              +				uaUrl: 'http://www.acoon.de/robot.asp',
              +				uaCompany: 'Acoon GmbH',
              +				uaCompanyUrl: 'http://www.acoon.de/',
              +				uaIcon: 'bot_Acoon.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=AcoonBot'
              +			}
              +		},
              +		'1283': {
              +			userAgent: 'MLBot (www.metadatalabs.com/mlbot)',
              +			metadata: {
              +				uaFamily: 'MLBot',
              +				uaName: 'MLBot b',
              +				uaUrl: 'http://www.metadatalabs.com/mlbot/',
              +				uaCompany: 'metadata labs',
              +				uaCompanyUrl: 'http://www.metadatalabs.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MLBot'
              +			}
              +		},
              +		'1287': {
              +			userAgent: 'Acoon-Robot 4.0.2 (http://www.acoon.de)',
              +			metadata: {
              +				uaFamily: 'AcoonBot',
              +				uaName: 'Acoon-Robot 4.0.2',
              +				uaUrl: 'http://www.acoon.de/robot.asp',
              +				uaCompany: 'Acoon GmbH',
              +				uaCompanyUrl: 'http://www.acoon.de/',
              +				uaIcon: 'bot_Acoon.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=AcoonBot'
              +			}
              +		},
              +		'1293': {
              +			userAgent: 'Touche (+http://www.touche.com.ve)',
              +			metadata: {
              +				uaFamily: 'Touche',
              +				uaName: 'Touche',
              +				uaUrl: 'http://www.touche.com.ve/Acerca.jsp',
              +				uaCompany: 'Touch\xe9',
              +				uaCompanyUrl: 'http://www.touche.com.ve/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Touche'
              +			}
              +		},
              +		'1297': {
              +			userAgent: 'Acoon-Robot 4.0.2.17 (http://www.acoon.de)',
              +			metadata: {
              +				uaFamily: 'AcoonBot',
              +				uaName: 'Acoon-Robot 4.0.2.17',
              +				uaUrl: 'http://www.acoon.de/robot.asp',
              +				uaCompany: 'Acoon GmbH',
              +				uaCompanyUrl: 'http://www.acoon.de/',
              +				uaIcon: 'bot_Acoon.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=AcoonBot'
              +			}
              +		},
              +		'1323': {
              +			userAgent: 'Mozilla/5.0 (compatible; egothor/12.0rc-2; +http://ego.ms.mff.cuni.cz/)',
              +			metadata: {
              +				uaFamily: 'egothor',
              +				uaName: 'egothor/12.0rc-2',
              +				uaUrl: 'http://ego.ms.mff.cuni.cz/',
              +				uaCompany: 'Katedra softwarov\xe9ho in\u017een\xfdrstv\xed Univerzity Karlovi',
              +				uaCompanyUrl: 'http://kocour.ms.mff.cuni.cz/cs/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=egothor'
              +			}
              +		},
              +		'1458': {
              +			userAgent: 'Yandex/1.01.001 (compatible; Win16; P)',
              +			metadata: {
              +				uaFamily: 'YandexBot',
              +				uaName: 'Yandex/1.01.001',
              +				uaUrl: 'http://yandex.com/bots',
              +				uaCompany: 'Yandex LLC',
              +				uaCompanyUrl: 'http://company.yandex.com/',
              +				uaIcon: 'bot_Yandex.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=YandexBot'
              +			}
              +		},
              +		'1459': {
              +			userAgent: 'Mozilla/5.0 (compatible; DotBot/1.1; http://www.dotnetdotcom.org/, crawler@dotnetdotcom.org)',
              +			metadata: {
              +				uaFamily: 'DotBot',
              +				uaName: 'DotBot/1.1',
              +				uaUrl: 'http://www.dotnetdotcom.org/',
              +				uaCompany: 'dotnetdotcom.org',
              +				uaCompanyUrl: 'http://www.dotnetdotcom.org/#cont',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=DotBot'
              +			}
              +		},
              +		'1461': {
              +			userAgent: 'ia_archiver (+http://www.alexa.com/site/help/webmasters; crawler@alexa.com)',
              +			metadata: {
              +				uaFamily: 'ia_archiver',
              +				uaName: 'ia_archiver alexa',
              +				uaUrl: 'http://www.alexa.com/site/help/webmasters',
              +				uaCompany: 'Alexa Internet, Inc.',
              +				uaCompanyUrl: 'http://www.alexa.com/',
              +				uaIcon: 'bot_ia_archiver.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ia_archiver'
              +			}
              +		},
              +		'1462': {
              +			userAgent: 'Mozilla/5.0 (Twiceler-0.9 http://www.cuil.com/twiceler/robot.html)',
              +			metadata: {
              +				uaFamily: 'Twiceler',
              +				uaName: 'Twiceler-0.9',
              +				uaUrl: 'http://www.cuil.com/twiceler/robot.html',
              +				uaCompany: 'Cuil, Inc. ',
              +				uaCompanyUrl: 'http://www.cuil.com/',
              +				uaIcon: 'bot_Twiceler.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Twiceler'
              +			}
              +		},
              +		'1463': {
              +			userAgent: 'Mozilla/5.0 (compatible; Seznam screenshot-generator 2.0; +http://fulltext.sblog.cz/screenshot/)',
              +			metadata: {
              +				uaFamily: 'SeznamBot',
              +				uaName: 'Seznam screenshot-generator 2.0',
              +				uaUrl: 'http://napoveda.seznam.cz/en/indexing-the-web.html',
              +				uaCompany: 'Seznam.cz, a.s.',
              +				uaCompanyUrl: 'http://www.seznam.cz/',
              +				uaIcon: 'seznam.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SeznamBot'
              +			}
              +		},
              +		'1464': {
              +			userAgent: 'SeznamBot/2.0 (+http://fulltext.sblog.cz/robot/)',
              +			metadata: {
              +				uaFamily: 'SeznamBot',
              +				uaName: 'SeznamBot/2.0',
              +				uaUrl: 'http://napoveda.seznam.cz/en/indexing-the-web.html',
              +				uaCompany: 'Seznam.cz, a.s.',
              +				uaCompanyUrl: 'http://www.seznam.cz/',
              +				uaIcon: 'seznam.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SeznamBot'
              +			}
              +		},
              +		'1466': {
              +			userAgent: 'Mozilla/5.0 (compatible; MSIE or Firefox mutant; not on Windows server; +http://ws.daum.net/aboutWebSearch.html) Daumoa/2.0',
              +			metadata: {
              +				uaFamily: 'Daumoa',
              +				uaName: 'Daumoa/2.0 b',
              +				uaUrl: 'http://tab.search.daum.net/aboutWebSearch_en.html',
              +				uaCompany: 'Daum Communications Corp.',
              +				uaCompanyUrl: 'http://info.daum.net/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Daumoa'
              +			}
              +		},
              +		'1468': {
              +			userAgent: 'msnbot-media/1.1 (+http://search.msn.com/msnbot.htm)',
              +			metadata: {
              +				uaFamily: 'MSNBot',
              +				uaName: 'msnbot-media/1.1',
              +				uaUrl: 'http://search.msn.com/msnbot.htm',
              +				uaCompany: 'Microsoft Corporation',
              +				uaCompanyUrl: 'http://www.microsoft.com/',
              +				uaIcon: 'bot_msnbot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MSNBot'
              +			}
              +		},
              +		'1469': {
              +			userAgent: 'OOZBOT/0.20 ( -- ; http://www.setooz.com/oozbot.html ; agentname at setooz dot_com )',
              +			metadata: {
              +				uaFamily: 'Setoozbot',
              +				uaName: 'OOZBOT/0.20',
              +				uaUrl: 'http://www.setooz.com/oozbot.html',
              +				uaCompany: 'SETU Software Systems (P) Ltd.',
              +				uaCompanyUrl: 'http://www.setusoftware.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Setoozbot'
              +			}
              +		},
              +		'1470': {
              +			userAgent: 'Sogou develop spider/4.0(+http://www.sogou.com/docs/help/webmasters.htm#07)',
              +			metadata: {
              +				uaFamily: 'sogou spider',
              +				uaName: 'Sogou develop spider/4.0',
              +				uaUrl: 'http://www.sogou.com/docs/help/webmasters.htm#07',
              +				uaCompany: 'SOGOU.COM',
              +				uaCompanyUrl: 'http://www.sogou.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=sogou spider'
              +			}
              +		},
              +		'1471': {
              +			userAgent: 'Sogou web spider/4.0(+http://www.sogou.com/docs/help/webmasters.htm#07)',
              +			metadata: {
              +				uaFamily: 'sogou spider',
              +				uaName: 'Sogou web spider/4.0',
              +				uaUrl: 'http://www.sogou.com/docs/help/webmasters.htm#07',
              +				uaCompany: 'SOGOU.COM',
              +				uaCompanyUrl: 'http://www.sogou.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=sogou spider'
              +			}
              +		},
              +		'1472': {
              +			userAgent: 'SpokeSpider/1.0 (http://support.spoke.com/webspider/) Mozilla/5.0 (not really)',
              +			metadata: {
              +				uaFamily: 'SpokeSpider',
              +				uaName: 'SpokeSpider/1.0',
              +				uaUrl: 'http://support.spoke.com/webspider/',
              +				uaCompany: 'Spoke Software ',
              +				uaCompanyUrl: 'http://www.spoke.com/company/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SpokeSpider'
              +			}
              +		},
              +		'1474': {
              +			userAgent: 'Baiduspider+(+http://www.baidu.jp/spider/)',
              +			metadata: {
              +				uaFamily: 'Baiduspider',
              +				uaName: 'Baiduspider japan',
              +				uaUrl: 'http://www.baidu.com/search/spider.htm',
              +				uaCompany: 'Baidu',
              +				uaCompanyUrl: 'http://www.baidu.com/',
              +				uaIcon: 'bot_baiduspider.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Baiduspider'
              +			}
              +		},
              +		'1475': {
              +			userAgent: 'linkdexbot/Nutch-1.0-dev (http://www.linkdex.com/; crawl at linkdex dot com)',
              +			metadata: {
              +				uaFamily: 'linkdexbot',
              +				uaName: 'linkdexbot',
              +				uaUrl: 'http://www.linkdex.com/about/bots/',
              +				uaCompany: 'Linkdex Limited.',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=linkdexbot'
              +			}
              +		},
              +		'1476': {
              +			userAgent: 'Yeti/1.0 (NHN Corp.; http://help.naver.com/robots/)',
              +			metadata: {
              +				uaFamily: 'NaverBot',
              +				uaName: 'Yeti/1.0',
              +				uaUrl: 'http://help.naver.com/robots/',
              +				uaCompany: 'NHN Corporation',
              +				uaCompanyUrl: 'http://www.nhncorp.com/',
              +				uaIcon: 'bot_NaverBot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=NaverBot'
              +			}
              +		},
              +		'1478': {
              +			userAgent: 'mozilla/5.0 (compatible; webmastercoffee/0.7; +http://webmastercoffee.com/about)',
              +			metadata: {
              +				uaFamily: 'webmastercoffee',
              +				uaName: 'webmastercoffee/0.7',
              +				uaUrl: 'http://webmastercoffee.com/about',
              +				uaCompany: 'Martin Schwartz',
              +				uaCompanyUrl: 'http://webmastercoffee.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=webmastercoffee'
              +			}
              +		},
              +		'1479': {
              +			userAgent: 'boitho.com-dc/0.82 ( http://www.boitho.com/dcbot.html )',
              +			metadata: {
              +				uaFamily: 'boitho.com-dc',
              +				uaName: 'boitho.com-dc/0.82',
              +				uaUrl: 'http://www.boitho.com/dcbot.html',
              +				uaCompany: 'Boitho',
              +				uaCompanyUrl: 'http://www.boitho.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=boitho.com-dc'
              +			}
              +		},
              +		'1480': {
              +			userAgent: 'Busiversebot/v1.0 (http://www.busiverse.com/bot.php)',
              +			metadata: {
              +				uaFamily: 'Sirketce/Busiverse',
              +				uaName: 'Busiversebot/v1.0',
              +				uaUrl: 'http://www.busiverse.com/bot.php',
              +				uaCompany: 'BerilTech',
              +				uaCompanyUrl: 'http://www.sirketce.com.tr/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Sirketce/Busiverse'
              +			}
              +		},
              +		'1481': {
              +			userAgent: 'CatchBot/1.0; +http://www.catchbot.com',
              +			metadata: {
              +				uaFamily: 'CatchBot',
              +				uaName: 'CatchBot/1.0',
              +				uaUrl: 'http://www.catchbot.com/',
              +				uaCompany: 'Reed Business Information Pty Limited',
              +				uaCompanyUrl: 'http://www.reedbusiness.com/',
              +				uaIcon: 'bot_CatchBot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=CatchBot'
              +			}
              +		},
              +		'1482': {
              +			userAgent: 'CazoodleBot/0.0.2 (http://www.cazoodle.com/contact.php; cbot@cazoodle.com)',
              +			metadata: {
              +				uaFamily: 'CazoodleBot',
              +				uaName: 'CazoodleBot/0.0.2',
              +				uaUrl: 'http://www.cazoodle.com/cazoodlebot.php',
              +				uaCompany: 'Cazoodle Inc.',
              +				uaCompanyUrl: 'http://www.cazoodle.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=CazoodleBot'
              +			}
              +		},
              +		'1484': {
              +			userAgent: 'kalooga/KaloogaBot (Kalooga; http://www.kalooga.com/info.html?page=crawler; crawler@kalooga.com)',
              +			metadata: {
              +				uaFamily: 'Kalooga',
              +				uaName: 'Kalooga',
              +				uaUrl: 'http://www.kalooga.com/info.html?page=crawler',
              +				uaCompany: 'Kalooga',
              +				uaCompanyUrl: 'http://www.kalooga.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Kalooga'
              +			}
              +		},
              +		'1490': {
              +			userAgent: '192.comAgent',
              +			metadata: {
              +				uaFamily: '192.comAgent',
              +				uaName: '192.comAgent',
              +				uaUrl: 'http://www.192.com/help/tools-guides/webcrawler/',
              +				uaCompany: 'i-CD Publishing (UK) Limited',
              +				uaCompanyUrl: 'http://www.icdpublishing.co.uk/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=192.comAgent'
              +			}
              +		},
              +		'1494': {
              +			userAgent: 'Mozilla/4.0 (compatible; NaverBot/1.0; http://help.naver.com/customer_webtxt_02.jsp)',
              +			metadata: {
              +				uaFamily: 'NaverBot',
              +				uaName: 'NaverBot/1.0',
              +				uaUrl: 'http://help.naver.com/robots/',
              +				uaCompany: 'NHN Corporation',
              +				uaCompanyUrl: 'http://www.nhncorp.com/',
              +				uaIcon: 'bot_NaverBot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=NaverBot'
              +			}
              +		},
              +		'1495': {
              +			userAgent: 'copyright sheriff (+http://www.copyrightsheriff.com/)',
              +			metadata: {
              +				uaFamily: 'copyright sheriff',
              +				uaName: 'copyright sheriff',
              +				uaUrl: '',
              +				uaCompany: 'CopyrightSheriff .Com',
              +				uaCompanyUrl: 'http://www.copyrightsheriff.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=copyright sheriff'
              +			}
              +		},
              +		'1496': {
              +			userAgent: 'Mozilla/5.0 (compatible; OsO; http://oso.octopodus.com/abot.html)',
              +			metadata: {
              +				uaFamily: 'OsObot',
              +				uaName: 'OsObot',
              +				uaUrl: 'http://oso.octopodus.com/abot.html',
              +				uaCompany: 'Denis Chatelain',
              +				uaCompanyUrl: 'http://buildingasearchengine.blogspot.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=OsObot'
              +			}
              +		},
              +		'1497': {
              +			userAgent: 'msnbot/2.0b (+http://search.msn.com/msnbot.htm)',
              +			metadata: {
              +				uaFamily: 'MSNBot',
              +				uaName: 'MSNBot/2.0b',
              +				uaUrl: 'http://search.msn.com/msnbot.htm',
              +				uaCompany: 'Microsoft Corporation',
              +				uaCompanyUrl: 'http://www.microsoft.com/',
              +				uaIcon: 'bot_msnbot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MSNBot'
              +			}
              +		},
              +		'1500': {
              +			userAgent: 'Eurobot/1.1 (http://eurobot.ayell.eu)',
              +			metadata: {
              +				uaFamily: 'Eurobot',
              +				uaName: 'Eurobot/1.1',
              +				uaUrl: 'http://eurobot.ayell.de/',
              +				uaCompany: 'Ayell Euronet',
              +				uaCompanyUrl: 'http://www.ayell.eu/',
              +				uaIcon: 'bot_eurobot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Eurobot'
              +			}
              +		},
              +		'1501': {
              +			userAgent: 'Mozilla/5.0 (compatible; woriobot +http://worio.com)',
              +			metadata: {
              +				uaFamily: 'woriobot',
              +				uaName: 'woriobot',
              +				uaUrl: '',
              +				uaCompany: 'Zite',
              +				uaCompanyUrl: 'http://zite.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=woriobot'
              +			}
              +		},
              +		'1502': {
              +			userAgent: 'Mail.Ru/1.0',
              +			metadata: {
              +				uaFamily: 'Mail.Ru bot',
              +				uaName: 'Mail.Ru/1.0',
              +				uaUrl: 'http://go.mail.ru/help/robots',
              +				uaCompany: 'Mail.Ru Group',
              +				uaCompanyUrl: 'http://corp.mail.ru/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Mail.Ru bot'
              +			}
              +		},
              +		'1504': {
              +			userAgent: 'LinguaBot/v0.001-dev (MultiLinual Sarch Engine v0.001; LinguaSeek; admin at linguaseek dot com)',
              +			metadata: {
              +				uaFamily: 'LinguaBot',
              +				uaName: 'LinguaBot/v0.001-dev',
              +				uaUrl: '',
              +				uaCompany: 'linguaseek.com ',
              +				uaCompanyUrl: 'http://linguaseek.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=LinguaBot'
              +			}
              +		},
              +		'1505': {
              +			userAgent: 'urlfan-bot/1.0; +http://www.urlfan.com/site/bot/350.html',
              +			metadata: {
              +				uaFamily: 'urlfan-bot',
              +				uaName: 'urlfan-bot/1.0',
              +				uaUrl: 'http://www.urlfan.com/site/bot/350.html',
              +				uaCompany: '://URLFAN',
              +				uaCompanyUrl: 'http://www.urlfan.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=urlfan-bot'
              +			}
              +		},
              +		'1507': {
              +			userAgent: 'Mozilla/5.0 (compatible; YoudaoBot/1.0; http://www.youdao.com/help/webmaster/spider/; )',
              +			metadata: {
              +				uaFamily: 'YoudaoBot',
              +				uaName: 'YoudaoBot/1.0',
              +				uaUrl: 'http://www.youdao.com/help/webmaster/spider/',
              +				uaCompany: 'youdao.com',
              +				uaCompanyUrl: 'http://www.youdao.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=YoudaoBot'
              +			}
              +		},
              +		'1509': {
              +			userAgent: 'YowedoBot/Yowedo 1.0 (Search Engine crawler for yowedo.com; http://yowedo.com/en/partners.html; crawler@yowedo.com)',
              +			metadata: {
              +				uaFamily: 'YowedoBot',
              +				uaName: 'YowedoBot/1.0',
              +				uaUrl: 'http://yowedo.com/en/partners.html',
              +				uaCompany: 'yowedo.com',
              +				uaCompanyUrl: 'http://yowedo.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=YowedoBot'
              +			}
              +		},
              +		'1512': {
              +			userAgent: 'Yanga WorldSearch Bot v1.1/beta (http://www.yanga.co.uk/)',
              +			metadata: {
              +				uaFamily: 'Yanga',
              +				uaName: 'Yanga v1.1/beta',
              +				uaUrl: 'http://yandex.com/bots',
              +				uaCompany: 'Gigabase Ltd.',
              +				uaCompanyUrl: 'http://www.gigabase.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Yanga'
              +			}
              +		},
              +		'1516': {
              +			userAgent: 'Mozilla/5.0 (compatible; Butterfly/1.0; +http://labs.topsy.com/butterfly.html) Gecko/2009032608 Firefox/3.0.8',
              +			metadata: {
              +				uaFamily: 'Butterfly',
              +				uaName: 'Butterfly/1.0',
              +				uaUrl: 'http://labs.topsy.com/butterfly.html',
              +				uaCompany: 'Topsy Labs',
              +				uaCompanyUrl: 'http://labs.topsy.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Butterfly'
              +			}
              +		},
              +		'1517': {
              +			userAgent: 'Mozilla/5.0 (compatible; MJ12bot/v1.2.4; http://www.majestic12.co.uk/bot.php?+)',
              +			metadata: {
              +				uaFamily: 'MJ12bot',
              +				uaName: 'MJ12bot/v1.2.4',
              +				uaUrl: 'http://majestic12.co.uk/bot.php',
              +				uaCompany: 'Majestic-12',
              +				uaCompanyUrl: 'http://www.majestic12.co.uk/',
              +				uaIcon: 'bot_mj12bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MJ12bot'
              +			}
              +		},
              +		'1519': {
              +			userAgent: 'holmes/3.12.4 (http://morfeo.centrum.cz/bot)',
              +			metadata: {
              +				uaFamily: 'Holmes',
              +				uaName: 'holmes/3.12.4 - morfeo',
              +				uaUrl: 'http://www.ucw.cz/holmes/',
              +				uaCompany: 'Martin Mare\u0161 and Robert \u0160palek',
              +				uaCompanyUrl: 'http://www.ucw.cz/holmes/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Holmes'
              +			}
              +		},
              +		'1522': {
              +			userAgent: 'OOZBOT/0.20 ( Setooz v\xfdrazn\xfd ako say-th-uuz, znamen\xe1 mosty.  ; http://www.setooz.com/oozbot.html ; agentname at setooz dot_com )',
              +			metadata: {
              +				uaFamily: 'Setoozbot',
              +				uaName: 'OOZBOT/0.20 b',
              +				uaUrl: 'http://www.setooz.com/oozbot.html',
              +				uaCompany: 'SETU Software Systems (P) Ltd.',
              +				uaCompanyUrl: 'http://www.setusoftware.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Setoozbot'
              +			}
              +		},
              +		'1523': {
              +			userAgent: 'facebookexternalhit/1.0 (+http://www.facebook.com/externalhit_uatext.php)',
              +			metadata: {
              +				uaFamily: 'FacebookExternalHit',
              +				uaName: 'FacebookExternalHit/1.0',
              +				uaUrl: 'http://www.facebook.com/externalhit_uatext.php',
              +				uaCompany: 'Facebook',
              +				uaCompanyUrl: 'http://www.facebook.com/',
              +				uaIcon: 'bot_facebook.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=FacebookExternalHit'
              +			}
              +		},
              +		'1524': {
              +			userAgent: 'kalooga/KaloogaBot (Kalooga; http://www.kalooga.com/info.html?page=crawler)',
              +			metadata: {
              +				uaFamily: 'Kalooga',
              +				uaName: 'Kalooga',
              +				uaUrl: 'http://www.kalooga.com/info.html?page=crawler',
              +				uaCompany: 'Kalooga',
              +				uaCompanyUrl: 'http://www.kalooga.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Kalooga'
              +			}
              +		},
              +		'1530': {
              +			userAgent: 'Mozilla/5.0 (compatible; DBLBot/1.0; +http://www.dontbuylists.com/)',
              +			metadata: {
              +				uaFamily: 'DBLBot',
              +				uaName: 'DBLBot/1.0',
              +				uaUrl: 'http://www.dontbuylists.com/faq.htm',
              +				uaCompany: 'Dontbuylists.com',
              +				uaCompanyUrl: 'http://www.dontbuylists.com/team.htm',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=DBLBot'
              +			}
              +		},
              +		'1533': {
              +			userAgent: 'Mozilla/5.0 (compatible; Mp3Bot/0.4; +http://mp3realm.org/mp3bot/)',
              +			metadata: {
              +				uaFamily: 'Mp3Bot',
              +				uaName: 'Mp3Bot/0.4',
              +				uaUrl: 'http://mp3realm.org/mp3bot/',
              +				uaCompany: 'Mp3Realm.Org',
              +				uaCompanyUrl: 'http://mp3realm.org/',
              +				uaIcon: 'bot_Mp3Bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Mp3Bot'
              +			}
              +		},
              +		'1536': {
              +			userAgent: 'http://www.uni-koblenz.de/~flocke/robot-info.txt',
              +			metadata: {
              +				uaFamily: 'Flocke bot',
              +				uaName: 'Flocke bot',
              +				uaUrl: 'http://www.uni-koblenz.de/~flocke/robot-info.txt',
              +				uaCompany: '',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Flocke bot'
              +			}
              +		},
              +		'1540': {
              +			userAgent: 'JadynAve - http://www.jadynave.com/robot',
              +			metadata: {
              +				uaFamily: 'JadynAve',
              +				uaName: 'JadynAve',
              +				uaUrl: '',
              +				uaCompany: 'Yesup Ecommerce Solutions Inc',
              +				uaCompanyUrl: 'http://www.yesup.net/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=JadynAve'
              +			}
              +		},
              +		'1542': {
              +			userAgent: 'KeywenBot/4.1  http://www.keywen.com/Encyclopedia/Links',
              +			metadata: {
              +				uaFamily: 'KeywenBot',
              +				uaName: 'KeywenBot/4.1',
              +				uaUrl: 'http://www.keywen.com/Encyclopedia/Links/',
              +				uaCompany: 'Michael Charnine',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=KeywenBot'
              +			}
              +		},
              +		'1546': {
              +			userAgent: 'Mozilla/5.0 (compatible; heritrix/1.12.1 +http://www.webarchiv.cz)',
              +			metadata: {
              +				uaFamily: 'heritrix',
              +				uaName: 'heritrix/1.12.1',
              +				uaUrl: 'http://crawler.archive.org/',
              +				uaCompany: 'Internet Archive',
              +				uaCompanyUrl: 'http://www.archive.org/',
              +				uaIcon: 'bot_heritrix.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=heritrix'
              +			}
              +		},
              +		'1548': {
              +			userAgent: 'Y!J-BRI/0.0.1 crawler ( http://help.yahoo.co.jp/help/jp/search/indexing/indexing-15.html )',
              +			metadata: {
              +				uaFamily: 'Yahoo! JAPAN',
              +				uaName: 'Y!J-BRI/0.0.1',
              +				uaUrl: 'http://help.yahoo.co.jp/help/jp/search/indexing/indexing-15.html',
              +				uaCompany: 'Yahoo! Inc',
              +				uaCompanyUrl: 'http://www.yahoo.com/',
              +				uaIcon: 'bot_yahoo!slurp.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Yahoo! JAPAN'
              +			}
              +		},
              +		'1550': {
              +			userAgent: 'Mozilla/5.0 (compatible; akula/12.0rc-2; +http://k311.fd.cvut.cz/)',
              +			metadata: {
              +				uaFamily: 'akula',
              +				uaName: 'akula/12.0rc-2',
              +				uaUrl: 'http://k311.fd.cvut.cz/',
              +				uaCompany: '\u010cVUT Fakulta dopravn\xed',
              +				uaCompanyUrl: 'http://www.fd.cvut.cz/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=akula'
              +			}
              +		},
              +		'1555': {
              +			userAgent: 'Mozilla/5.0 (compatible; akula/k311; +http://k311.fd.cvut.cz/)',
              +			metadata: {
              +				uaFamily: 'akula',
              +				uaName: 'akula/k311',
              +				uaUrl: 'http://k311.fd.cvut.cz/',
              +				uaCompany: '\u010cVUT Fakulta dopravn\xed',
              +				uaCompanyUrl: 'http://www.fd.cvut.cz/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=akula'
              +			}
              +		},
              +		'1558': {
              +			userAgent: 'Y!J-BSC/1.0 (http://help.yahoo.co.jp/help/jp/blog-search/)',
              +			metadata: {
              +				uaFamily: 'Yahoo! JAPAN',
              +				uaName: 'Y!J-BSC/1.0',
              +				uaUrl: 'http://help.yahoo.co.jp/help/jp/search/indexing/indexing-15.html',
              +				uaCompany: 'Yahoo! Inc',
              +				uaCompanyUrl: 'http://www.yahoo.com/',
              +				uaIcon: 'bot_yahoo!slurp.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Yahoo! JAPAN'
              +			}
              +		},
              +		'1562': {
              +			userAgent: 'Shelob (shelob@gmx.net)',
              +			metadata: {
              +				uaFamily: 'Shelob',
              +				uaName: 'Shelob',
              +				uaUrl: 'http://mattwork.potsdam.edu/projects/wiki/index.php/Shelob',
              +				uaCompany: 'M@',
              +				uaCompanyUrl: 'http://mattwork.potsdam.edu/projects/wiki/index.php/Category:Me',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Shelob'
              +			}
              +		},
              +		'1563': {
              +			userAgent: 'DoCoMo/2.0 N902iS(c100;TB;W24H12)(compatible; moba-crawler; http://crawler.dena.jp/)',
              +			metadata: {
              +				uaFamily: 'moba-crawler',
              +				uaName: 'moba-crawler',
              +				uaUrl: 'http://crawler.dena.jp/',
              +				uaCompany: 'DeNA Co.,Ltd.',
              +				uaCompanyUrl: 'http://dena.jp/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=moba-crawler'
              +			}
              +		},
              +		'1564': {
              +			userAgent: 'Mozilla/5.0 (compatible; Yahoo! Slurp/3.0; http://help.yahoo.com/help/us/ysearch/slurp)',
              +			metadata: {
              +				uaFamily: 'Yahoo!',
              +				uaName: 'Yahoo! Slurp/3.0',
              +				uaUrl: 'http://help.yahoo.com/help/us/ysearch/slurp',
              +				uaCompany: 'Yahoo! Inc.',
              +				uaCompanyUrl: 'http://www.yahoo.com/',
              +				uaIcon: 'bot_yahoo!slurp.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Yahoo!'
              +			}
              +		},
              +		'1565': {
              +			userAgent: 'Mozilla/5.0 (compatible; ScoutJet; +http://www.scoutjet.com/)',
              +			metadata: {
              +				uaFamily: 'ScoutJet',
              +				uaName: 'ScoutJet old',
              +				uaUrl: 'http://www.scoutjet.com/',
              +				uaCompany: 'blekko, inc.',
              +				uaCompanyUrl: 'http://blekko.com/',
              +				uaIcon: 'bot_ScoutJet.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ScoutJet'
              +			}
              +		},
              +		'1567': {
              +			userAgent: 'Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.8.1) VoilaBot BETA 1.2 (support.voilabot@orange-ftgroup.com)',
              +			metadata: {
              +				uaFamily: 'VoilaBot',
              +				uaName: 'VoilaBot BETA 1.2',
              +				uaUrl: '',
              +				uaCompany: 'France Telecom',
              +				uaCompanyUrl: 'http://www.francetelecom.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=VoilaBot'
              +			}
              +		},
              +		'1568': {
              +			userAgent: 'DealGates Bot/1.1 by Luc Michalski (http://spider.dealgates.com/bot.html)',
              +			metadata: {
              +				uaFamily: 'DealGates Bot',
              +				uaName: 'DealGates Bot/1.1',
              +				uaUrl: 'http://www.dealgates.net/bot.html',
              +				uaCompany: 'Luc Michalski',
              +				uaCompanyUrl: 'http://www.dealgates.net/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=DealGates Bot'
              +			}
              +		},
              +		'1573': {
              +			userAgent: 'GingerCrawler/1.0 (Language Assistant for Dyslexics; www.gingersoftware.com/crawler_agent.htm; support at ginger software dot com)',
              +			metadata: {
              +				uaFamily: 'GingerCrawler',
              +				uaName: 'GingerCrawler/1.0',
              +				uaUrl: 'http://www.gingersoftware.com/crawler_agent.htm',
              +				uaCompany: 'Ginger Software',
              +				uaCompanyUrl: 'http://www.gingersoftware.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=GingerCrawler'
              +			}
              +		},
              +		'1582': {
              +			userAgent: 'flatlandbot/baypup (Flatland Industries Web Spider; http://www.flatlandindustries.com/flatlandbot; jason@flatlandindustries.com)',
              +			metadata: {
              +				uaFamily: 'Flatland Industries Web Spider',
              +				uaName: 'flatlandbot/baypup',
              +				uaUrl: 'http://www.flatlandindustries.com/flatlandbot',
              +				uaCompany: 'Flatland Industries, Inc.',
              +				uaCompanyUrl: 'http://www.flatlandindustries.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Flatland Industries Web Spider'
              +			}
              +		},
              +		'1583': {
              +			userAgent: 'holmes/3.11 (http://morfeo.centrum.cz/bot)',
              +			metadata: {
              +				uaFamily: 'Holmes',
              +				uaName: 'holmes/3.11',
              +				uaUrl: 'http://www.ucw.cz/holmes/',
              +				uaCompany: 'Martin Mare\u0161 and Robert \u0160palek',
              +				uaCompanyUrl: 'http://www.ucw.cz/holmes/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Holmes'
              +			}
              +		},
              +		'1586': {
              +			userAgent: 'voyager/2.0 (http://www.kosmix.com/crawler.html)',
              +			metadata: {
              +				uaFamily: 'voyager',
              +				uaName: 'voyager/2.0',
              +				uaUrl: 'http://www.kosmix.com/corp/crawler.html',
              +				uaCompany: 'Kosmix Corporation',
              +				uaCompanyUrl: 'http://www.kosmix.com/html/about.html',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=voyager'
              +			}
              +		},
              +		'1595': {
              +			userAgent: 'FeedCatBot/3.0 (+http://www.feedcat.net/)',
              +			metadata: {
              +				uaFamily: 'FeedCatBot',
              +				uaName: 'FeedCatBot/3.0',
              +				uaUrl: 'http://www.feedcat.net/',
              +				uaCompany: 'FEEDCAT.NET',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=FeedCatBot'
              +			}
              +		},
              +		'1599': {
              +			userAgent: 'JyxobotRSS/0.06',
              +			metadata: {
              +				uaFamily: 'Jyxobot',
              +				uaName: 'JyxobotRSS/0.06',
              +				uaUrl: '',
              +				uaCompany: 'Jyxo s.r.o.',
              +				uaCompanyUrl: 'http://jyxo.cz/',
              +				uaIcon: 'bot_Jyxobot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Jyxobot'
              +			}
              +		},
              +		'1600': {
              +			userAgent: 'SniffRSS/0.5beta (+http://www.blogator.com/)',
              +			metadata: {
              +				uaFamily: 'SniffRSS',
              +				uaName: 'SniffRSS/0.5beta',
              +				uaUrl: '',
              +				uaCompany: 'blogator.com',
              +				uaCompanyUrl: 'http://www.blogator.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SniffRSS'
              +			}
              +		},
              +		'1601': {
              +			userAgent: 'RSSMicro.com RSS/Atom Feed Robot',
              +			metadata: {
              +				uaFamily: 'RSSMicro.com RSS/Atom Feed Robot',
              +				uaName: 'RSSMicro.com RSS/Atom Feed Robot',
              +				uaUrl: '',
              +				uaCompany: 'RSSMicro.com',
              +				uaCompanyUrl: 'http://rssmicro.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=RSSMicro.com RSS/Atom Feed Robot'
              +			}
              +		},
              +		'1602': {
              +			userAgent: 'Mozilla/5.0 (compatible; MJ12bot/v1.2.1; http://www.majestic12.co.uk/bot.php?+)',
              +			metadata: {
              +				uaFamily: 'MJ12bot',
              +				uaName: 'MJ12bot/v1.2.1',
              +				uaUrl: 'http://majestic12.co.uk/bot.php',
              +				uaCompany: 'Majestic-12',
              +				uaCompanyUrl: 'http://www.majestic12.co.uk/',
              +				uaIcon: 'bot_mj12bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MJ12bot'
              +			}
              +		},
              +		'1604': {
              +			userAgent: 'yacybot (i386 Linux 2.6.28-11-generic; java 1.6.0_13; Europe/de) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'1619': {
              +			userAgent: 'voyager/1.0 (+http://www.kosmix.com/html/crawler.html)',
              +			metadata: {
              +				uaFamily: 'voyager',
              +				uaName: 'voyager/1.0',
              +				uaUrl: 'http://www.kosmix.com/corp/crawler.html',
              +				uaCompany: 'Kosmix Corporation',
              +				uaCompanyUrl: 'http://www.kosmix.com/html/about.html',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=voyager'
              +			}
              +		},
              +		'1633': {
              +			userAgent: 'Mozilla/5.0 (compatible; 80bot/0.71; http://www.80legs.com/spider.html;) Gecko/2008032620',
              +			metadata: {
              +				uaFamily: '80legs',
              +				uaName: '80legs/0.71',
              +				uaUrl: 'http://www.80legs.com/webcrawler.html',
              +				uaCompany: 'Computational Crawling, LP ',
              +				uaCompanyUrl: 'http://compucrawl.com/',
              +				uaIcon: 'bot_80legs.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=80legs'
              +			}
              +		},
              +		'1637': {
              +			userAgent: 'BlogPulseLive (support@blogpulse.com)',
              +			metadata: {
              +				uaFamily: 'BlogPulse',
              +				uaName: 'BlogPulseLive',
              +				uaUrl: 'http://www.blogpulse.com/',
              +				uaCompany: 'Nielsen Company',
              +				uaCompanyUrl: 'http://www.nielsen-online.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=BlogPulse'
              +			}
              +		},
              +		'1645': {
              +			userAgent: 'yacybot (amd64 Linux 2.6.24-23-generic; java 1.6.0_07; Europe/de) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'1650': {
              +			userAgent: 'Mozilla/5.0 (compatible; DKIMRepBot/1.0; +http://www.dkim-reputation.org)',
              +			metadata: {
              +				uaFamily: 'DKIMRepBot',
              +				uaName: 'DKIMRepBot/1.0',
              +				uaUrl: 'http://www.dkim-reputation.org/',
              +				uaCompany: 'DKIM',
              +				uaCompanyUrl: 'http://www.dkim.org/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=DKIMRepBot'
              +			}
              +		},
              +		'1653': {
              +			userAgent: 'yacybot (i386 Linux 2.6.28-gentoo-r5; java 1.5.0_18; Europe/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'1658': {
              +			userAgent: 'Mozilla/5.0 (compatible; heritrix/1.14.3 +http://archive.org)',
              +			metadata: {
              +				uaFamily: 'heritrix',
              +				uaName: 'heritrix/1.14.3',
              +				uaUrl: 'http://crawler.archive.org/',
              +				uaCompany: 'Internet Archive',
              +				uaCompanyUrl: 'http://www.archive.org/',
              +				uaIcon: 'bot_heritrix.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=heritrix'
              +			}
              +		},
              +		'1662': {
              +			userAgent: 'UptimeDog Robot (www.uptimedog.com)',
              +			metadata: {
              +				uaFamily: 'UptimeDog',
              +				uaName: 'UptimeDog',
              +				uaUrl: 'http://www.uptimedog.com/',
              +				uaCompany: 'San Pedro Software Inc.',
              +				uaCompanyUrl: 'http://mosw.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=UptimeDog'
              +			}
              +		},
              +		'1663': {
              +			userAgent: 'Mozilla/4.0 (compatible; Fooooo_Web_Video_Crawl http://fooooo.com/bot.html)',
              +			metadata: {
              +				uaFamily: 'Fooooo_Web_Video_Crawl',
              +				uaName: 'Fooooo_Web_Video_Crawl',
              +				uaUrl: 'http://fooooo.com/bot.html',
              +				uaCompany: 'Bank of innvation Inc.',
              +				uaCompanyUrl: 'http://en.boi.jp/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Fooooo_Web_Video_Crawl'
              +			}
              +		},
              +		'1676': {
              +			userAgent: 'Mozilla/5.0 (compatible; MJ12bot/v1.2.5; http://www.majestic12.co.uk/bot.php?+)',
              +			metadata: {
              +				uaFamily: 'MJ12bot',
              +				uaName: 'MJ12bot/v1.2.5',
              +				uaUrl: 'http://majestic12.co.uk/bot.php',
              +				uaCompany: 'Majestic-12',
              +				uaCompanyUrl: 'http://www.majestic12.co.uk/',
              +				uaIcon: 'bot_mj12bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MJ12bot'
              +			}
              +		},
              +		'1681': {
              +			userAgent: 'Orgbybot/OrgbyBot v1.2 (Spidering the net for Orgby; http://www.orgby.com/  ; Orgby.com Search Engine)',
              +			metadata: {
              +				uaFamily: 'OrgbyBot',
              +				uaName: 'OrgbyBot/1.2',
              +				uaUrl: 'http://orgby.com/bot/',
              +				uaCompany: 'Orgby.com',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=OrgbyBot'
              +			}
              +		},
              +		'1685': {
              +			userAgent: 'OpenAcoon v4.1.0 (www.openacoon.de)',
              +			metadata: {
              +				uaFamily: 'AcoonBot',
              +				uaName: 'OpenAcoon v4.1.0',
              +				uaUrl: 'http://www.openacoon.de/',
              +				uaCompany: 'Acoon GmbH',
              +				uaCompanyUrl: 'http://www.acoon.de/',
              +				uaIcon: 'bot_Acoon.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=AcoonBot'
              +			}
              +		},
              +		'1690': {
              +			userAgent: 'YandexSomething/1.0',
              +			metadata: {
              +				uaFamily: 'YandexBot',
              +				uaName: 'YandexSomething/1.0',
              +				uaUrl: 'http://yandex.com/bots',
              +				uaCompany: 'Yandex LLC',
              +				uaCompanyUrl: 'http://company.yandex.com/',
              +				uaIcon: 'bot_Yandex.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=YandexBot'
              +			}
              +		},
              +		'1703': {
              +			userAgent: 'OOZBOT/0.20 ( http://www.setooz.com/oozbot.html ; agentname at setooz dot_com )',
              +			metadata: {
              +				uaFamily: 'Setoozbot ',
              +				uaName: 'OOZBOT/0.20 c',
              +				uaUrl: 'http://www.setooz.com/oozbot.html',
              +				uaCompany: 'SETU Software Systems (P) Ltd.',
              +				uaCompanyUrl: 'http://www.setusoftware.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Setoozbot '
              +			}
              +		},
              +		'1704': {
              +			userAgent: 'Mozilla/5.0 (compatible; heritrix/2.0.2 +http://seekda.com)',
              +			metadata: {
              +				uaFamily: 'heritrix',
              +				uaName: 'heritrix/2.0.2',
              +				uaUrl: 'http://crawler.archive.org/',
              +				uaCompany: 'Internet Archive',
              +				uaCompanyUrl: 'http://www.archive.org/',
              +				uaIcon: 'bot_heritrix.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=heritrix'
              +			}
              +		},
              +		'1705': {
              +			userAgent: 'adidxbot/1.1 (+http://search.msn.com/msnbot.htm)',
              +			metadata: {
              +				uaFamily: 'adidxbot',
              +				uaName: 'adidxbot/1.1',
              +				uaUrl: 'http://search.msn.com/msnbot.htm',
              +				uaCompany: '\tMicrosoft Corporation',
              +				uaCompanyUrl: 'http://www.microsoft.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=adidxbot'
              +			}
              +		},
              +		'1711': {
              +			userAgent: 'Robozilla/1.0',
              +			metadata: {
              +				uaFamily: 'Robozilla',
              +				uaName: 'Robozilla/1.0',
              +				uaUrl: 'http://www.dmoz.org/guidelines/robozilla.html',
              +				uaCompany: 'DMOZ',
              +				uaCompanyUrl: 'http://www.dmoz.org/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Robozilla'
              +			}
              +		},
              +		'1712': {
              +			userAgent: 'yacybot (x86 Windows Vista 6.1; java 1.6.0_13; Europe/de) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'1717': {
              +			userAgent: 'Mozilla/5.0 (compatible; Falconsbot; +http://iws.seu.edu.cn/services/falcons/contact_us.jsp)',
              +			metadata: {
              +				uaFamily: 'Falconsbot',
              +				uaName: 'Falconsbot',
              +				uaUrl: 'http://ws.nju.edu.cn/falcons/contact_us.jsp',
              +				uaCompany: 'Institute of Web Science',
              +				uaCompanyUrl: 'http://iws.seu.edu.cn/page/english/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Falconsbot'
              +			}
              +		},
              +		'1726': {
              +			userAgent: 'Bloggsi/1.0 (http://bloggsi.com/)',
              +			metadata: {
              +				uaFamily: 'Bloggsi',
              +				uaName: 'Bloggsi/1.0',
              +				uaUrl: 'http://bloggsi.com/',
              +				uaCompany: 'Stefan Fischerl\xe4nder',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Bloggsi'
              +			}
              +		},
              +		'1727': {
              +			userAgent: 'Technoratibot/7.0',
              +			metadata: {
              +				uaFamily: 'Technoratibot',
              +				uaName: 'Technoratibot/7.0',
              +				uaUrl: '',
              +				uaCompany: 'Technorati Inc.',
              +				uaCompanyUrl: 'http://www.technorati.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Technoratibot'
              +			}
              +		},
              +		'1728': {
              +			userAgent: 'Technoratibot/8.0',
              +			metadata: {
              +				uaFamily: 'Technoratibot',
              +				uaName: 'Technoratibot/8.0',
              +				uaUrl: '',
              +				uaCompany: 'Technorati Inc.',
              +				uaCompanyUrl: 'http://www.technorati.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Technoratibot'
              +			}
              +		},
              +		'1731': {
              +			userAgent: 'Mozilla/5.0 (compatible; DNS-Digger-Explorer/1.0; +http://www.dnsdigger.com)',
              +			metadata: {
              +				uaFamily: 'DNS-Digger-Explorer',
              +				uaName: 'DNS-Digger-Explorer/1.0',
              +				uaUrl: '',
              +				uaCompany: 'DNSDigger',
              +				uaCompanyUrl: 'http://www.dnsdigger.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=DNS-Digger-Explorer'
              +			}
              +		},
              +		'1733': {
              +			userAgent: 'Nokia6680/1.0 (4.04.07) SymbianOS/8.0 Series60/2.6 Profile/MIDP-2.0 Configuration/CLDC-1.1 (botmobi find.mobi/bot.html find@mtld.mobi)',
              +			metadata: {
              +				uaFamily: 'botmobi',
              +				uaName: 'botmobi',
              +				uaUrl: 'http://find.mobi/bot.html',
              +				uaCompany: 'mTLD, Ltd.',
              +				uaCompanyUrl: 'http://mtld.mobi/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=botmobi'
              +			}
              +		},
              +		'1735': {
              +			userAgent: 'Mozilla/5.0 (compatible; AboutUsBot/0.9; +http://www.aboutus.org/AboutUsBot)',
              +			metadata: {
              +				uaFamily: 'AboutUsBot',
              +				uaName: 'AboutUsBot/0.9',
              +				uaUrl: 'http://www.aboutus.org/AboutUs:Bot',
              +				uaCompany: 'AboutUs, Inc.',
              +				uaCompanyUrl: 'http://www.aboutus.org/AboutUs.org',
              +				uaIcon: 'bot_AboutUsBot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=AboutUsBot'
              +			}
              +		},
              +		'1738': {
              +			userAgent: 'ICC-Crawler(Mozilla-compatible; ; http://kc.nict.go.jp/project1/crawl.html)',
              +			metadata: {
              +				uaFamily: 'ICC-Crawler',
              +				uaName: 'ICC-Crawler',
              +				uaUrl: 'http://kc.nict.go.jp/project1/crawl.html',
              +				uaCompany: 'NICT',
              +				uaCompanyUrl: 'http://nict.go.jp/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ICC-Crawler'
              +			}
              +		},
              +		'1751': {
              +			userAgent: 'WebImages 0.3 ( http://herbert.groot.jebbink.nl/?app=WebImages )',
              +			metadata: {
              +				uaFamily: 'WebImages',
              +				uaName: 'WebImages 0.3',
              +				uaUrl: '',
              +				uaCompany: 'Herbert Groot Jebbink',
              +				uaCompanyUrl: 'http://herbert.groot.jebbink.nl/ ',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=WebImages'
              +			}
              +		},
              +		'1752': {
              +			userAgent: 'Browsershots',
              +			metadata: {
              +				uaFamily: 'Browsershots',
              +				uaName: 'Browsershots',
              +				uaUrl: 'http://browsershots.org/faq',
              +				uaCompany: 'Browsershots.org',
              +				uaCompanyUrl: 'http://browsershots.org/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Browsershots'
              +			}
              +		},
              +		'1753': {
              +			userAgent: 'BotOnParade, http://www.bots-on-para.de/bot.html',
              +			metadata: {
              +				uaFamily: 'BotOnParade',
              +				uaName: 'BotOnParade',
              +				uaUrl: 'http://www.bots-on-para.de/bot.html',
              +				uaCompany: 'Angus Internetmarketing',
              +				uaCompanyUrl: 'http://www.angus.co.uk/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=BotOnParade'
              +			}
              +		},
              +		'1754': {
              +			userAgent: 'BlogPulse (ISSpider-3.0)',
              +			metadata: {
              +				uaFamily: 'BlogPulse',
              +				uaName: 'BlogPulse',
              +				uaUrl: 'http://www.blogpulse.com/',
              +				uaCompany: 'Nielsen Company',
              +				uaCompanyUrl: 'http://www.nielsen-online.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=BlogPulse'
              +			}
              +		},
              +		'1759': {
              +			userAgent: 'Twiceler-0.9 http://www.cuill.com/twiceler/robot.html',
              +			metadata: {
              +				uaFamily: 'Twiceler',
              +				uaName: 'Twiceler-0.9 b',
              +				uaUrl: 'http://www.cuil.com/twiceler/robot.html',
              +				uaCompany: 'Cuil, Inc.',
              +				uaCompanyUrl: 'http://www.cuil.com/',
              +				uaIcon: 'bot_Twiceler.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Twiceler'
              +			}
              +		},
              +		'1763': {
              +			userAgent: 'TwengaBot/1.1 (+http://www.twenga.com/bot.html)',
              +			metadata: {
              +				uaFamily: 'TwengaBot',
              +				uaName: 'TwengaBot/1.1',
              +				uaUrl: 'http://www.twenga.com/bot.html',
              +				uaCompany: 'Twenga SA',
              +				uaCompanyUrl: 'http://www.twenga.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=TwengaBot'
              +			}
              +		},
              +		'1765': {
              +			userAgent: 'ICC-Crawler/2.0 (Mozilla-compatible; ; http://kc.nict.go.jp/project1/crawl.html)',
              +			metadata: {
              +				uaFamily: 'ICC-Crawler',
              +				uaName: 'ICC-Crawler/2.0',
              +				uaUrl: 'http://kc.nict.go.jp/project1/crawl.html',
              +				uaCompany: 'NICT',
              +				uaCompanyUrl: 'http://nict.go.jp/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ICC-Crawler'
              +			}
              +		},
              +		'1766': {
              +			userAgent: 'Mozilla/4.0 (compatible;  Vagabondo/4.0Beta; webcrawler at wise-guys dot nl; http://webagent.wise-guys.nl/; http://www.wise-guys.nl/)',
              +			metadata: {
              +				uaFamily: 'Vagabondo',
              +				uaName: 'Vagabondo/4.0Beta',
              +				uaUrl: 'http://webagent.wise-guys.nl/',
              +				uaCompany: 'WiseGuys Internet BV',
              +				uaCompanyUrl: 'http://www.wise-guys.nl/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Vagabondo'
              +			}
              +		},
              +		'1770': {
              +			userAgent: 'baypup/1.1 (Baypup; http://www.baypup.com/; jason@baypup.com)',
              +			metadata: {
              +				uaFamily: 'baypup',
              +				uaName: 'baypup/1.1',
              +				uaUrl: '',
              +				uaCompany: 'Flatland Industries, Inc.',
              +				uaCompanyUrl: 'http://www.flatlandindustries.com/',
              +				uaIcon: 'bot_Baypup.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=baypup'
              +			}
              +		},
              +		'1771': {
              +			userAgent: 'mozilla/5.0 (compatible; discobot/1.1; +http://discoveryengine.com/discobot.html)',
              +			metadata: {
              +				uaFamily: 'discoverybot',
              +				uaName: 'discobot/1.1',
              +				uaUrl: 'http://discoveryengine.com/discoverybot.html',
              +				uaCompany: 'discoveryengine.com. ',
              +				uaCompanyUrl: 'http://www.discoveryengine.com/',
              +				uaIcon: 'bot_discobot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=discoverybot'
              +			}
              +		},
              +		'1772': {
              +			userAgent: 'Mozilla/5.0 (compatible; Tagoobot/3.0; +http://www.tagoo.ru)',
              +			metadata: {
              +				uaFamily: 'Tagoobot',
              +				uaName: 'Tagoobot/3.0',
              +				uaUrl: '',
              +				uaCompany: 'Tagoo',
              +				uaCompanyUrl: 'http://www.tagoo.ru/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Tagoobot'
              +			}
              +		},
              +		'1773': {
              +			userAgent: '50.nu/0.01 ( +http://50.nu/bot.html )',
              +			metadata: {
              +				uaFamily: '50.nu',
              +				uaName: '50.nu/0.01',
              +				uaUrl: 'http://50.nu/bot.html',
              +				uaCompany: 'Innovate it',
              +				uaCompanyUrl: 'http://innovateit.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=50.nu'
              +			}
              +		},
              +		'1776': {
              +			userAgent: 'yacybot (i386 Linux 2.6.28-13-generic; java 1.6.0_13; Europe/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'1779': {
              +			userAgent: 'Mozilla/5.0 (compatible; Scarlett/ 1.0; +http://www.ellerdale.com/crawler.html)',
              +			metadata: {
              +				uaFamily: 'Scarlett',
              +				uaName: 'Scarlett/ 1.0',
              +				uaUrl: 'http://www.ellerdale.com/crawler.html',
              +				uaCompany: 'Ellerdale Project',
              +				uaCompanyUrl: 'http://www.ellerdale.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Scarlett'
              +			}
              +		},
              +		'1780': {
              +			userAgent: 'LexxeBot/1.0 (lexxebot@lexxe.com)',
              +			metadata: {
              +				uaFamily: 'LexxeBot',
              +				uaName: 'LexxeBot/1.0',
              +				uaUrl: 'http://lexxe.com/about/webmasters.cfm',
              +				uaCompany: 'Lexxe Pty Ltd',
              +				uaCompanyUrl: 'http://lexxe.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=LexxeBot'
              +			}
              +		},
              +		'1784': {
              +			userAgent: 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.2.1; aggregator:Spinn3r (Spinn3r 3.1); http://spinn3r.com/robot) Gecko/20021130',
              +			metadata: {
              +				uaFamily: 'Spinn3r',
              +				uaName: 'Spinn3r 3.1',
              +				uaUrl: 'http://spinn3r.com/robot',
              +				uaCompany: 'Tailrank Inc',
              +				uaCompanyUrl: 'http://tailrank.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Spinn3r'
              +			}
              +		},
              +		'1793': {
              +			userAgent: 'Mozilla/5.0 (Yahoo-MMCrawler/4.0; mailto:vertical-crawl-support@yahoo-inc.com)',
              +			metadata: {
              +				uaFamily: 'Yahoo!',
              +				uaName: 'Yahoo-MMCrawler/4.0',
              +				uaUrl: 'http://help.yahoo.com/',
              +				uaCompany: 'Yahoo! Inc',
              +				uaCompanyUrl: 'http://www.yahoo.com/',
              +				uaIcon: 'bot_yahoo!slurp.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Yahoo!'
              +			}
              +		},
              +		'1798': {
              +			userAgent: 'LinkAider (http://linkaider.com/crawler/)',
              +			metadata: {
              +				uaFamily: 'LinkAider',
              +				uaName: 'LinkAider',
              +				uaUrl: 'http://linkaider.com/crawler/',
              +				uaCompany: 'Ivinco',
              +				uaCompanyUrl: 'http://linkaider.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=LinkAider'
              +			}
              +		},
              +		'1805': {
              +			userAgent: 'WinWebBot/1.0; (Balaena Ltd, UK); http://www.balaena.com/winwebbot.html; winwebbot@balaena.com;)',
              +			metadata: {
              +				uaFamily: 'WinWebBot',
              +				uaName: 'WinWebBot/1.0',
              +				uaUrl: 'http://www.balaena.com/winwebbot.html',
              +				uaCompany: 'Balaena Ltd',
              +				uaCompanyUrl: 'http://www.balaena.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=WinWebBot'
              +			}
              +		},
              +		'1815': {
              +			userAgent: 'R6_FeedFetcher(www.radian6.com/crawler)',
              +			metadata: {
              +				uaFamily: 'R6 bot',
              +				uaName: 'R6_FeedFetcher',
              +				uaUrl: 'http://www.radian6.com/crawler/',
              +				uaCompany: 'Radian6 Technologies Inc',
              +				uaCompanyUrl: 'http://www.radian6.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=R6 bot'
              +			}
              +		},
              +		'1816': {
              +			userAgent: 'http://domino.research.ibm.com/comm/research_projects.nsf/pages/sai-crawler.callingcard.html',
              +			metadata: {
              +				uaFamily: 'SAI Crawler',
              +				uaName: 'SAI Crawler',
              +				uaUrl: 'http://domino.research.ibm.com/comm/research_projects.nsf/pages/sai-crawler.callingcard.html',
              +				uaCompany: 'IBM',
              +				uaCompanyUrl: 'http://www.ibm.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SAI Crawler'
              +			}
              +		},
              +		'1818': {
              +			userAgent: 'Mozilla/5.0 (compatible;YodaoBot-Image/1.0;http://www.youdao.com/help/webmaster/spider/;)',
              +			metadata: {
              +				uaFamily: 'YodaoBot',
              +				uaName: 'YodaoBot-Image/1.0',
              +				uaUrl: 'http://www.youdao.com/help/webmaster/spider/',
              +				uaCompany: 'youdao',
              +				uaCompanyUrl: 'http://www.youdao.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=YodaoBot'
              +			}
              +		},
              +		'1838': {
              +			userAgent: 'Mozilla/5.0 (compatible; Topicbot/12.0rc-2; +http://topicbot.awardspace.us/)',
              +			metadata: {
              +				uaFamily: 'Topicbot',
              +				uaName: 'Topicbot/12.0rc-2',
              +				uaUrl: 'http://topicbot.awardspace.us/',
              +				uaCompany: 'Research Group TopicBot',
              +				uaCompanyUrl: 'http://topicbot.awardspace.us/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Topicbot'
              +			}
              +		},
              +		'1849': {
              +			userAgent: 'http://www.amagit.com/',
              +			metadata: {
              +				uaFamily: 'Amagit.COM',
              +				uaName: 'Amagit.COM',
              +				uaUrl: '',
              +				uaCompany: 'Joshua Schwarz',
              +				uaCompanyUrl: 'http://contacts.joshuaschwarz.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Amagit.COM'
              +			}
              +		},
              +		'1853': {
              +			userAgent: 'Sosospider+(+http://help.soso.com/webspider.htm)',
              +			metadata: {
              +				uaFamily: 'Sosospider',
              +				uaName: 'Sosospider',
              +				uaUrl: 'http://help.soso.com/webspider.htm',
              +				uaCompany: 'Tencent, Inc.',
              +				uaCompanyUrl: 'http://www.tencent.com/',
              +				uaIcon: 'bot_soso.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Sosospider'
              +			}
              +		},
              +		'1856': {
              +			userAgent: 'findlinks/1.1.5-beta7 (+http://wortschatz.uni-leipzig.de/findlinks/)',
              +			metadata: {
              +				uaFamily: 'findlinks',
              +				uaName: 'findlinks/1.1.4-beta7',
              +				uaUrl: 'http://wortschatz.uni-leipzig.de/findlinks/',
              +				uaCompany: 'Universit\xe4t Leipzig',
              +				uaCompanyUrl: 'http://www.uni-leipzig.de/',
              +				uaIcon: 'bot_findlinks.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=findlinks'
              +			}
              +		},
              +		'1859': {
              +			userAgent: 'Mozilla/5.0 (compatible; JadynAveBot; +http://www.jadynave.com/robot)',
              +			metadata: {
              +				uaFamily: 'JadynAveBot',
              +				uaName: 'JadynAveBot',
              +				uaUrl: 'http://www.jadynave.com/robot',
              +				uaCompany: 'Yesup Ecommerce Solutions Inc.',
              +				uaCompanyUrl: 'http://www.yesup.net/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=JadynAveBot'
              +			}
              +		},
              +		'1866': {
              +			userAgent: 'smart.apnoti.com Robot/v1.34 (http://smart.apnoti.com/en/aboutApnotiWebCrawler.html)',
              +			metadata: {
              +				uaFamily: 'smart.apnoti.com Robot',
              +				uaName: 'smart.apnoti.com Robot/v1.34',
              +				uaUrl: 'http://smart.apnoti.com/en/aboutApnotiWebCrawler.html',
              +				uaCompany: 'apnoti.com GmbH',
              +				uaCompanyUrl: 'http://www.apnoti.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=smart.apnoti.com Robot'
              +			}
              +		},
              +		'1867': {
              +			userAgent: 'MnoGoSearch/3.3.9',
              +			metadata: {
              +				uaFamily: 'MnoGoSearch',
              +				uaName: 'MnoGoSearch/3.3.9',
              +				uaUrl: 'http://www.mnogosearch.org/products.html',
              +				uaCompany: 'Lavtech.Com',
              +				uaCompanyUrl: 'http://www.lavtech.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MnoGoSearch'
              +			}
              +		},
              +		'1869': {
              +			userAgent: 'Yandex/1.01.001 (compatible; Win16; H)',
              +			metadata: {
              +				uaFamily: 'YandexBot',
              +				uaName: 'Yandex/1.01.001',
              +				uaUrl: 'http://yandex.com/bots',
              +				uaCompany: 'Yandex LLC',
              +				uaCompanyUrl: 'http://company.yandex.com/',
              +				uaIcon: 'bot_Yandex.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=YandexBot'
              +			}
              +		},
              +		'1870': {
              +			userAgent: 'FollowSite Bot ( http://www.followsite.com/bot.html )',
              +			metadata: {
              +				uaFamily: 'FollowSite Bot',
              +				uaName: 'FollowSite Bot',
              +				uaUrl: 'http://www.followsite.com/bot.html',
              +				uaCompany: 'ASX Networks ApS',
              +				uaCompanyUrl: 'http://asxnetworks.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=FollowSite Bot'
              +			}
              +		},
              +		'1871': {
              +			userAgent: 'Mozilla/5.0 (compatible; 008/0.83; http://www.80legs.com/spider.html;) Gecko/2008032620',
              +			metadata: {
              +				uaFamily: '80legs',
              +				uaName: '80legs/0.83',
              +				uaUrl: 'http://www.80legs.com/webcrawler.html',
              +				uaCompany: 'Computational Crawling, LP',
              +				uaCompanyUrl: 'http://compucrawl.com/',
              +				uaIcon: 'bot_80legs.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=80legs'
              +			}
              +		},
              +		'1872': {
              +			userAgent: 'Mozilla/5.0 (X11; U; Linux i686 (x86_64); en-US; rv:1.8.1.20) Gecko/20090429 HeartRails_Capture/0.6 (+http://capture.heartrails.com/) BonEcho/2.0.0.20',
              +			metadata: {
              +				uaFamily: 'HeartRails_Capture',
              +				uaName: 'HeartRails_Capture/0.6',
              +				uaUrl: 'http://capture.heartrails.com/help/question',
              +				uaCompany: 'HeartRails Inc.',
              +				uaCompanyUrl: 'http://www.heartrails.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=HeartRails_Capture'
              +			}
              +		},
              +		'1885': {
              +			userAgent: 'Speedy Spider (Entireweb; Beta/1.2; http://www.entireweb.com/about/search_tech/speedyspider/)',
              +			metadata: {
              +				uaFamily: 'Speedy',
              +				uaName: 'Speedy Spider Beta/1.2',
              +				uaUrl: '',
              +				uaCompany: 'Entireweb Sweden AB',
              +				uaCompanyUrl: 'http://www.entireweb.com/',
              +				uaIcon: 'bot_Speedy.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Speedy'
              +			}
              +		},
              +		'1887': {
              +			userAgent: 'Mozilla/5.0 (compatible; heritrix/1.14.2 +http://rjpower.org)',
              +			metadata: {
              +				uaFamily: 'heritrix',
              +				uaName: 'heritrix/1.14.2',
              +				uaUrl: 'http://crawler.archive.org/',
              +				uaCompany: 'Internet Archive',
              +				uaCompanyUrl: 'http://www.archive.org/',
              +				uaIcon: 'bot_heritrix.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=heritrix'
              +			}
              +		},
              +		'1894': {
              +			userAgent: 'yacybot (amd64 Windows 7 6.1; java 1.6.0_14; Europe/de) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'1895': {
              +			userAgent: 'Mozilla/5.0 (compatible; Plukkie/1.1; http://www.botje.com/plukkie.htm)',
              +			metadata: {
              +				uaFamily: 'Plukkie',
              +				uaName: 'Plukkie/1.1',
              +				uaUrl: 'http://www.botje.com/plukkie.htm',
              +				uaCompany: 'botje.com',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Plukkie'
              +			}
              +		},
              +		'1906': {
              +			userAgent: 'SanszBot/1.7(http://www.sansz.org/sanszbot, spider@sansz.org) (spider@sansz.org)',
              +			metadata: {
              +				uaFamily: 'SanszBot',
              +				uaName: 'SanszBot/1.7',
              +				uaUrl: 'http://www.sansz.org/sanszbot',
              +				uaCompany: 'Peres Levente (Sansz Foundation)',
              +				uaCompanyUrl: 'http://www.sansz.org/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SanszBot'
              +			}
              +		},
              +		'1908': {
              +			userAgent: 'Mozilla/5.0 (compatible; MJ12bot/v1.2.3; http://www.majestic12.co.uk/bot.php?+)',
              +			metadata: {
              +				uaFamily: 'MJ12bot',
              +				uaName: 'MJ12bot/v1.2.3',
              +				uaUrl: 'http://majestic12.co.uk/bot.php',
              +				uaCompany: 'Majestic-12',
              +				uaCompanyUrl: 'http://www.majestic12.co.uk/',
              +				uaIcon: 'bot_mj12bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MJ12bot'
              +			}
              +		},
              +		'1909': {
              +			userAgent: 'Mozilla/5.0 (compatible; MJ12bot/v1.3.0; http://www.majestic12.co.uk/bot.php?+)',
              +			metadata: {
              +				uaFamily: 'MJ12bot',
              +				uaName: 'MJ12bot/v1.3.0',
              +				uaUrl: 'http://majestic12.co.uk/bot.php',
              +				uaCompany: 'Majestic-12',
              +				uaCompanyUrl: 'http://www.majestic12.co.uk/',
              +				uaIcon: 'bot_mj12bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MJ12bot'
              +			}
              +		},
              +		'1932': {
              +			userAgent: 'Mozilla/5.0 (compatible; GurujiBot/1.0; +http://www.guruji.com/en/WebmasterFAQ.html)',
              +			metadata: {
              +				uaFamily: 'GurujiBot',
              +				uaName: 'GurujiBot/1.0',
              +				uaUrl: 'http://www.guruji.com/en/WebmasterFAQ.html',
              +				uaCompany: 'Guruji.com Software Private Limited',
              +				uaCompanyUrl: 'http://www.guruji.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=GurujiBot'
              +			}
              +		},
              +		'1936': {
              +			userAgent: 'Sogou-Test-Spider/4.0 (compatible; MSIE 5.5; Windows 98)',
              +			metadata: {
              +				uaFamily: 'sogou spider',
              +				uaName: 'Sogou-Test-Spider/4.0',
              +				uaUrl: 'http://www.sogou.com/docs/help/webmasters.htm#07',
              +				uaCompany: 'SOGOU.COM',
              +				uaCompanyUrl: 'http://www.sogou.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=sogou spider'
              +			}
              +		},
              +		'1938': {
              +			userAgent: 'Mozilla/5.0 (compatible;+ParchBot/1.0;++http://www.parchmenthill.com/search.htm)',
              +			metadata: {
              +				uaFamily: 'ParchBot',
              +				uaName: 'ParchBot/1.0',
              +				uaUrl: 'http://www.parchmenthill.com/search.htm',
              +				uaCompany: 'Parchment Hill',
              +				uaCompanyUrl: 'http://www.parchmenthill.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ParchBot'
              +			}
              +		},
              +		'1941': {
              +			userAgent: 'AboutUsBot',
              +			metadata: {
              +				uaFamily: 'AboutUsBot',
              +				uaName: 'AboutUsBot',
              +				uaUrl: 'http://www.aboutus.org/AboutUs:Bot',
              +				uaCompany: 'AboutUs, Inc. ',
              +				uaCompanyUrl: 'http://www.aboutus.org/AboutUs.org',
              +				uaIcon: 'bot_AboutUsBot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=AboutUsBot'
              +			}
              +		},
              +		'1943': {
              +			userAgent: 'Yandex/1.01.001 (compatible; Win16; m)',
              +			metadata: {
              +				uaFamily: 'YandexBot',
              +				uaName: 'Yandex/1.01.001',
              +				uaUrl: 'http://yandex.com/bots',
              +				uaCompany: 'Yandex LLC',
              +				uaCompanyUrl: 'http://company.yandex.com/',
              +				uaIcon: 'bot_Yandex.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=YandexBot'
              +			}
              +		},
              +		'1950': {
              +			userAgent: 'Mozilla/5.0 (compatible; SecretSerachEngineLabs.com-SBSearch/0.9; http://www.secretsearchenginelabs.com/secret-web-crawler.php)',
              +			metadata: {
              +				uaFamily: 'SBSearch',
              +				uaName: 'SBSearch/0.9',
              +				uaUrl: 'http://www.secretsearchenginelabs.com/secret-web-crawler.php',
              +				uaCompany: 'SecretSearchEngineLabs.com',
              +				uaCompanyUrl: 'http://www.secretsearchenginelabs.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SBSearch'
              +			}
              +		},
              +		'1957': {
              +			userAgent: 'yacybot (i386 Linux 2.6.23; java 1.6.0_06; Europe/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'1971': {
              +			userAgent: 'taptubot *** please read http://www.taptu.com/corp/taptubot ***',
              +			metadata: {
              +				uaFamily: 'taptubot',
              +				uaName: 'taptubot',
              +				uaUrl: 'http://www.taptu.com/corp/taptubot',
              +				uaCompany: 'Taptu Limited',
              +				uaCompanyUrl: 'http://www.taptu.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=taptubot'
              +			}
              +		},
              +		'1982': {
              +			userAgent: 'Qseero v1.0.0',
              +			metadata: {
              +				uaFamily: 'Qseero',
              +				uaName: 'Qseero 1.0.0',
              +				uaUrl: '',
              +				uaCompany: 'Qseero, Inc.',
              +				uaCompanyUrl: 'http://q0.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Qseero'
              +			}
              +		},
              +		'1992': {
              +			userAgent: 'SeznamBot/2.0 (+http://fulltext.seznam.cz/)',
              +			metadata: {
              +				uaFamily: 'SeznamBot',
              +				uaName: 'SeznamBot/2.0',
              +				uaUrl: 'http://napoveda.seznam.cz/en/indexing-the-web.html',
              +				uaCompany: 'Seznam.cz, a.s.',
              +				uaCompanyUrl: 'http://www.seznam.cz/',
              +				uaIcon: 'seznam.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SeznamBot'
              +			}
              +		},
              +		'1994': {
              +			userAgent: 'Mozilla/5.0 (compatible; Exabot/3.0 (BiggerBetter); +http://www.exabot.com/go/robot)',
              +			metadata: {
              +				uaFamily: 'Exabot',
              +				uaName: 'Exabot/3.0/BiggerBetter',
              +				uaUrl: 'http://www.exabot.com/go/robot',
              +				uaCompany: 'Exalead S.A.',
              +				uaCompanyUrl: 'http://www.exalead.com/',
              +				uaIcon: 'bot_Exabot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Exabot'
              +			}
              +		},
              +		'2003': {
              +			userAgent: 'TinEye/1.0; +http://www.tineye.com/',
              +			metadata: {
              +				uaFamily: 'TinEye',
              +				uaName: 'TinEye/1.0',
              +				uaUrl: 'http://tineye.com/crawler.html ',
              +				uaCompany: 'Id\xe9e Inc.',
              +				uaCompanyUrl: 'http://ideeinc.com/',
              +				uaIcon: 'bot_TinEye.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=TinEye'
              +			}
              +		},
              +		'2004': {
              +			userAgent: 'Thumbnail.CZ robot 1.1 (http://thumbnail.cz/why-no-robots-txt.html)',
              +			metadata: {
              +				uaFamily: 'Thumbnail.CZ robot',
              +				uaName: 'Thumbnail.CZ robot 1.1',
              +				uaUrl: 'http://thumbnail.cz/why-no-robots-txt.html',
              +				uaCompany: 'Miroslav Such\xfd',
              +				uaCompanyUrl: 'http://miroslav.suchy.cz/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Thumbnail.CZ robot'
              +			}
              +		},
              +		'2016': {
              +			userAgent: 'Mozilla/5.0 (compatible; heritrix/1.12.1b +http://netarkivet.dk/website/info.html)',
              +			metadata: {
              +				uaFamily: 'heritrix',
              +				uaName: 'heritrix/1.12.1b',
              +				uaUrl: 'http://crawler.archive.org/',
              +				uaCompany: 'Internet Archive',
              +				uaCompanyUrl: 'http://www.archive.org/',
              +				uaIcon: 'bot_heritrix.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=heritrix'
              +			}
              +		},
              +		'2017': {
              +			userAgent: 'yacybot (amd64 Linux 2.6.18-164.el5; java 1.6.0; Europe/de) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'2021': {
              +			userAgent: 'Mozilla/5.0 (compatible; heritrix/1.14.3 +http://www.webarchiv.cz)',
              +			metadata: {
              +				uaFamily: 'heritrix',
              +				uaName: 'heritrix/1.14.3',
              +				uaUrl: 'http://crawler.archive.org/',
              +				uaCompany: 'Internet Archive',
              +				uaCompanyUrl: 'http://www.archive.org/',
              +				uaIcon: 'bot_heritrix.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=heritrix'
              +			}
              +		},
              +		'2022': {
              +			userAgent: 'bitlybot',
              +			metadata: {
              +				uaFamily: 'bitlybot',
              +				uaName: 'bitlybot',
              +				uaUrl: 'http://code.google.com/p/bitly-bot/',
              +				uaCompany: 'Rahul Garg',
              +				uaCompanyUrl: 'http://www.google.com/profiles/mr.rahulgarg',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=bitlybot'
              +			}
              +		},
              +		'2024': {
              +			userAgent: 'Mozilla/5.0 (compatible; MJ12bot/v1.3.1; http://www.majestic12.co.uk/bot.php?+)',
              +			metadata: {
              +				uaFamily: 'MJ12bot',
              +				uaName: 'MJ12bot/v1.3.1',
              +				uaUrl: 'http://majestic12.co.uk/bot.php',
              +				uaCompany: 'Majestic-12',
              +				uaCompanyUrl: 'http://www.majestic12.co.uk/',
              +				uaIcon: 'bot_mj12bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MJ12bot'
              +			}
              +		},
              +		'2026': {
              +			userAgent: 'Mozilla/5.0 (compatible; heritrix/2.0.2 +http://aihit.com)',
              +			metadata: {
              +				uaFamily: 'heritrix',
              +				uaName: 'heritrix/2.0.2',
              +				uaUrl: 'http://crawler.archive.org/',
              +				uaCompany: 'Internet Archive',
              +				uaCompanyUrl: 'http://www.archive.org/',
              +				uaIcon: 'bot_heritrix.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=heritrix'
              +			}
              +		},
              +		'2028': {
              +			userAgent: 'Mozilla/5.0 (compatible; Najdi.si/3.1)',
              +			metadata: {
              +				uaFamily: 'Najdi.si',
              +				uaName: 'Najdi.si/3.1',
              +				uaUrl: 'http://www.najdi.si/help/aboutsearch.html#q5',
              +				uaCompany: 'Najdi.si d.o.o.',
              +				uaCompanyUrl: 'http://www.najdi.si/',
              +				uaIcon: 'bot_najdi.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Najdi.si'
              +			}
              +		},
              +		'2050': {
              +			userAgent: 'BabalooSpider/1.3 (BabalooSpider; http://www.babaloo.si; spider@babaloo.si)',
              +			metadata: {
              +				uaFamily: 'BabalooSpider',
              +				uaName: 'BabalooSpider/1.3',
              +				uaUrl: '',
              +				uaCompany: 'Babaloo d.o.o.',
              +				uaCompanyUrl: 'http://www.babaloo.si/',
              +				uaIcon: 'bot_BabalooSpider.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=BabalooSpider'
              +			}
              +		},
              +		'2057': {
              +			userAgent: 'http://arachnode.net 1.2',
              +			metadata: {
              +				uaFamily: 'arachnode.net',
              +				uaName: 'arachnode.net/1.2',
              +				uaUrl: 'http://arachnode.codeplex.com/',
              +				uaCompany: 'arachnode.net, llc',
              +				uaCompanyUrl: 'http://arachnode.net/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=arachnode.net'
              +			}
              +		},
              +		'2063': {
              +			userAgent: 'BDFetch',
              +			metadata: {
              +				uaFamily: 'BDFetch',
              +				uaName: 'BDFetch',
              +				uaUrl: '',
              +				uaCompany: 'BDProtect Inc.',
              +				uaCompanyUrl: 'http://www.brandprotect.com/',
              +				uaIcon: 'bot_BDFetch.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=BDFetch'
              +			}
              +		},
              +		'2071': {
              +			userAgent: 'yacybot (i386 Linux 2.6.24-23-generic; java 1.6.0_16; Europe/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'2073': {
              +			userAgent: 'Mozilla/5.0 (compatible; Plukkie/1.2; http://www.botje.com/plukkie.htm)',
              +			metadata: {
              +				uaFamily: 'Plukkie',
              +				uaName: 'Plukkie/1.2',
              +				uaUrl: 'http://www.botje.com/plukkie.htm',
              +				uaCompany: 'botje.com',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Plukkie'
              +			}
              +		},
              +		'2078': {
              +			userAgent: 'Ronzoobot/1.2 (http://www.ronzoo.com/about.php)',
              +			metadata: {
              +				uaFamily: 'Ronzoobot',
              +				uaName: 'Ronzoobot/1.2',
              +				uaUrl: 'http://www.ronzoo.com/about/',
              +				uaCompany: 'Ronzoo',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_Ronzoobot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Ronzoobot'
              +			}
              +		},
              +		'2079': {
              +			userAgent: 'Mozilla/5.0 (compatible; heritrix/3.0.0-SNAPSHOT-20091120.021634 +http://crawler.archive.org)',
              +			metadata: {
              +				uaFamily: 'heritrix',
              +				uaName: 'heritrix/3.0.0',
              +				uaUrl: 'http://crawler.archive.org/',
              +				uaCompany: 'Internet Archive',
              +				uaCompanyUrl: 'http://www.archive.org/',
              +				uaIcon: 'bot_heritrix.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=heritrix'
              +			}
              +		},
              +		'2081': {
              +			userAgent: 'Mozilla/5.0 (compatible; heritrix/1.14.3.r6601 +http://www.buddybuzz.net/yptrino)',
              +			metadata: {
              +				uaFamily: 'heritrix',
              +				uaName: 'heritrix/1.14.3.r6601',
              +				uaUrl: 'http://crawler.archive.org/',
              +				uaCompany: 'Internet Archive',
              +				uaCompanyUrl: 'http://www.archive.org/',
              +				uaIcon: 'bot_heritrix.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=heritrix'
              +			}
              +		},
              +		'2087': {
              +			userAgent: 'Zscho.de Crawler/Nutch-1.0-Zscho.de-semantic_patch (Zscho.de Crawler, collecting for machine learning; http://zscho.de/)',
              +			metadata: {
              +				uaFamily: 'Nutch',
              +				uaName: 'Nutch/1.0 at zscho.de',
              +				uaUrl: 'http://www.nutch.org/docs/en/bot.html',
              +				uaCompany: 'lucene',
              +				uaCompanyUrl: 'http://lucene.apache.org/',
              +				uaIcon: 'bot_Nutch.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Nutch'
              +			}
              +		},
              +		'2088': {
              +			userAgent: 'yacybot (i386 Linux 2.6.23; java 1.6.0_17; Europe/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'2091': {
              +			userAgent: 'yacybot (amd64 Linux 2.6.26-2-openvz-amd64; java 1.6.0_12; UTC/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'2098': {
              +			userAgent: 'Surphace Scout&v4.0 - scout at surphace dot com',
              +			metadata: {
              +				uaFamily: 'Surphace Scout',
              +				uaName: 'Surphace Scout/4.0',
              +				uaUrl: '',
              +				uaCompany: 'Surphace (AOL news)',
              +				uaCompanyUrl: 'http://www.surphace.com/',
              +				uaIcon: 'bot_Surphace_Scout.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Surphace Scout'
              +			}
              +		},
              +		'2099': {
              +			userAgent: 'Mozilla/5.0 (compatible; Steeler/3.5; http://www.tkl.iis.u-tokyo.ac.jp/~crawler/)',
              +			metadata: {
              +				uaFamily: 'Steeler',
              +				uaName: 'Steeler/3.5',
              +				uaUrl: 'http://www.tkl.iis.u-tokyo.ac.jp/~crawler/',
              +				uaCompany: 'Kitsuregawa Laboratory, The University of Tokyo',
              +				uaCompanyUrl: 'http://www.tkl.iis.u-tokyo.ac.jp/',
              +				uaIcon: 'bot_Steeler.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Steeler'
              +			}
              +		},
              +		'2102': {
              +			userAgent: 'Mozilla/5.0 (compatible; aiHitBot-DM/2.0.2 +http://www.aihit.com)',
              +			metadata: {
              +				uaFamily: 'aiHitBot',
              +				uaName: 'aiHitBot-DM/2.0.2',
              +				uaUrl: '',
              +				uaCompany: 'aiHit Ltd.',
              +				uaCompanyUrl: 'http://aihit.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=aiHitBot'
              +			}
              +		},
              +		'2110': {
              +			userAgent: 'amibot - http://www.amidalla.de - tech@amidalla.com libwww-perl/5.831',
              +			metadata: {
              +				uaFamily: 'amibot',
              +				uaName: 'amibot',
              +				uaUrl: 'http://www.amidalla.de/info.htm',
              +				uaCompany: 'amidalla.de',
              +				uaCompanyUrl: 'http://www.amidalla.de/',
              +				uaIcon: 'bot_amibot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=amibot'
              +			}
              +		},
              +		'2120': {
              +			userAgent: 'Mozilla/5.0 (compatible; Mp3Bot/0.7; +http://mp3realm.org/mp3bot/)',
              +			metadata: {
              +				uaFamily: 'Mp3Bot',
              +				uaName: 'Mp3Bot/0.7',
              +				uaUrl: 'http://mp3realm.org/mp3bot/',
              +				uaCompany: 'Mp3Realm.Org',
              +				uaCompanyUrl: 'http://mp3realm.org/',
              +				uaIcon: 'bot_Mp3Bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Mp3Bot'
              +			}
              +		},
              +		'2125': {
              +			userAgent: 'baypup/colbert (Baypup; http://sf.baypup.com/webmasters; jason@baypup.com)',
              +			metadata: {
              +				uaFamily: 'baypup',
              +				uaName: 'baypup/colbert',
              +				uaUrl: 'http://www.baypup.com/webmasters',
              +				uaCompany: 'Flatland Industries, Inc.',
              +				uaCompanyUrl: 'http://www.flatlandindustries.com/',
              +				uaIcon: 'bot_Baypup.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=baypup'
              +			}
              +		},
              +		'2132': {
              +			userAgent: 'gonzo1[P] +http://www.suchen.de/faq.html',
              +			metadata: {
              +				uaFamily: 'gonzo',
              +				uaName: 'gonzo1',
              +				uaUrl: 'http://www.suchen.de/faq.html',
              +				uaCompany: 'SEARCHTEQ',
              +				uaCompanyUrl: 'http://www.searchteq.de/',
              +				uaIcon: 'bot_gonzo.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=gonzo'
              +			}
              +		},
              +		'2133': {
              +			userAgent: 'gonzo2[P] +http://www.suchen.de/faq.html',
              +			metadata: {
              +				uaFamily: 'gonzo',
              +				uaName: 'gonzo2',
              +				uaUrl: 'http://www.suchen.de/faq.html',
              +				uaCompany: 'SEARCHTEQ',
              +				uaCompanyUrl: 'http://www.searchteq.de/',
              +				uaIcon: 'bot_gonzo.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=gonzo'
              +			}
              +		},
              +		'2135': {
              +			userAgent: 'Mozilla/5.0 (compatible; ptd-crawler; +http://bixolabs.com/crawler/ptd/; crawler@bixolabs.com)',
              +			metadata: {
              +				uaFamily: 'bixocrawler',
              +				uaName: 'ptd-crawler',
              +				uaUrl: 'http://wiki.github.com/bixo/bixo/bixocrawler',
              +				uaCompany: 'Bixo Labs',
              +				uaCompanyUrl: 'http://openbixo.org/',
              +				uaIcon: 'bot_ptd-crawler.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=bixocrawler'
              +			}
              +		},
              +		'2138': {
              +			userAgent: 'SBIder/Nutch-1.0-dev (http://www.sitesell.com/sbider.html)',
              +			metadata: {
              +				uaFamily: 'SBIder',
              +				uaName: 'SBIder/1.0',
              +				uaUrl: 'http://www.sitesell.com/sbider.html',
              +				uaCompany: 'SiteSell',
              +				uaCompanyUrl: 'http://www.sitesell.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SBIder'
              +			}
              +		},
              +		'2145': {
              +			userAgent: 'Ronzoobot/1.3 (http://www.ronzoo.com/about.php)',
              +			metadata: {
              +				uaFamily: 'Ronzoobot',
              +				uaName: 'Ronzoobot/1.3',
              +				uaUrl: 'http://www.ronzoo.com/about/',
              +				uaCompany: 'Ronzoo',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_Ronzoobot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Ronzoobot'
              +			}
              +		},
              +		'2155': {
              +			userAgent: 'Linguee Bot (http://www.linguee.com/bot)',
              +			metadata: {
              +				uaFamily: 'Linguee Bot',
              +				uaName: 'Linguee Bot',
              +				uaUrl: 'http://www.linguee.com/bot',
              +				uaCompany: 'Linguee GmbH',
              +				uaCompanyUrl: 'http://www.linguee.com/',
              +				uaIcon: 'bot_Linguee.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Linguee Bot'
              +			}
              +		},
              +		'2162': {
              +			userAgent: 'baypup/colbert (Baypup; http://www.baypup.com/webmasters; jason@baypup.com)',
              +			metadata: {
              +				uaFamily: 'baypup',
              +				uaName: 'baypup/colbert',
              +				uaUrl: 'http://www.baypup.com/webmasters',
              +				uaCompany: 'Flatland Industries, Inc.',
              +				uaCompanyUrl: 'http://www.flatlandindustries.com/',
              +				uaIcon: 'bot_Baypup.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=baypup'
              +			}
              +		},
              +		'2170': {
              +			userAgent: 'CorpusCrawler 2.0.0 (http://corpora.fi.muni.cz/crawler/)',
              +			metadata: {
              +				uaFamily: 'CorpusCrawler',
              +				uaName: 'CorpusCrawler 2.0.0',
              +				uaUrl: 'http://corpora.fi.muni.cz/crawler/',
              +				uaCompany: 'NLP - at the Faculty of Informatics, Masaryk University, Brno',
              +				uaCompanyUrl: 'http://nlp.fi.muni.cz/en/nlplab',
              +				uaIcon: 'bot_CorpusCrawler.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=CorpusCrawler'
              +			}
              +		},
              +		'2175': {
              +			userAgent: 'ThumbShots-Bot (+http://thumbshots.in/bot.html)',
              +			metadata: {
              +				uaFamily: 'ThumbShots-Bot',
              +				uaName: 'ThumbShots-Bot',
              +				uaUrl: 'http://thumbshots.in/bot.html',
              +				uaCompany: 'Kristian Fischer',
              +				uaCompanyUrl: 'http://www.kfsw.de/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ThumbShots-Bot'
              +			}
              +		},
              +		'2181': {
              +			userAgent: 'CorpusCrawler 2.0.8 (http://corpora.fi.muni.cz/crawler/)',
              +			metadata: {
              +				uaFamily: 'CorpusCrawler',
              +				uaName: 'CorpusCrawler 2.0.8',
              +				uaUrl: 'http://corpora.fi.muni.cz/crawler/',
              +				uaCompany: 'NLP - at the Faculty of Informatics, Masaryk University, Brno',
              +				uaCompanyUrl: 'http://nlp.fi.muni.cz/en/nlplab',
              +				uaIcon: 'bot_CorpusCrawler.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=CorpusCrawler'
              +			}
              +		},
              +		'2183': {
              +			userAgent: 'TinEye/1.1 (http://tineye.com/crawler.html)',
              +			metadata: {
              +				uaFamily: 'TinEye',
              +				uaName: 'TinEye/1.1',
              +				uaUrl: 'http://tineye.com/crawler.html',
              +				uaCompany: 'Id\xe9e Inc.',
              +				uaCompanyUrl: 'http://ideeinc.com/',
              +				uaIcon: 'bot_TinEye.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=TinEye'
              +			}
              +		},
              +		'2185': {
              +			userAgent: 'Mozilla/5.0 (compatible; MJ12bot/v1.3.2; http://www.majestic12.co.uk/bot.php?+)',
              +			metadata: {
              +				uaFamily: 'MJ12bot',
              +				uaName: 'MJ12bot/v1.3.2',
              +				uaUrl: 'http://majestic12.co.uk/bot.php',
              +				uaCompany: 'Majestic-12',
              +				uaCompanyUrl: 'http://www.majestic12.co.uk/',
              +				uaIcon: 'bot_mj12bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MJ12bot'
              +			}
              +		},
              +		'2188': {
              +			userAgent: 'Mozilla/5.0 (compatible; aiHitBot/1.0-DS; +http://www.aihit.com/)',
              +			metadata: {
              +				uaFamily: 'aiHitBot',
              +				uaName: 'aiHitBot/1.0-DS',
              +				uaUrl: '',
              +				uaCompany: 'aiHit Ltd.',
              +				uaCompanyUrl: 'http://aihit.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=aiHitBot'
              +			}
              +		},
              +		'2194': {
              +			userAgent: 'CorpusCrawler 2.0.9 (http://corpora.fi.muni.cz/crawler/)',
              +			metadata: {
              +				uaFamily: 'CorpusCrawler',
              +				uaName: 'CorpusCrawler 2.0.9',
              +				uaUrl: 'http://corpora.fi.muni.cz/crawler/',
              +				uaCompany: 'NLP - at the Faculty of Informatics, Masaryk University, Brno',
              +				uaCompanyUrl: 'http://nlp.fi.muni.cz/en/nlplab',
              +				uaIcon: 'bot_CorpusCrawler.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=CorpusCrawler'
              +			}
              +		},
              +		'2195': {
              +			userAgent: 'MnoGoSearch/3.2.37',
              +			metadata: {
              +				uaFamily: 'MnoGoSearch',
              +				uaName: 'MnoGoSearch/3.2.37',
              +				uaUrl: 'http://www.mnogosearch.org/products.html',
              +				uaCompany: 'Lavtech.Com',
              +				uaCompanyUrl: 'http://www.lavtech.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MnoGoSearch'
              +			}
              +		},
              +		'2196': {
              +			userAgent: 'MojeekBot/0.2 (archi; http://www.mojeek.com/bot.html)',
              +			metadata: {
              +				uaFamily: 'MojeekBot',
              +				uaName: 'MojeekBot/0.2',
              +				uaUrl: 'http://www.mojeek.com/bot.html',
              +				uaCompany: 'Mojeek Ltd.',
              +				uaCompanyUrl: 'http://www.mojeek.com/',
              +				uaIcon: 'bot_MojeekBot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MojeekBot'
              +			}
              +		},
              +		'2197': {
              +			userAgent: 'Pingdom.com_bot_version_1.4_(http://www.pingdom.com/)',
              +			metadata: {
              +				uaFamily: 'pingdom.com_bot',
              +				uaName: 'pingdom.com_bot 1.4',
              +				uaUrl: '',
              +				uaCompany: 'Pingdom AB',
              +				uaCompanyUrl: 'http://www.pingdom.com/',
              +				uaIcon: 'bot_pingdomcom_bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=pingdom.com_bot'
              +			}
              +		},
              +		'2205': {
              +			userAgent: 'Mozilla/5.0 (compatible; XmarksFetch/1.0; +http://www.xmarks.com/about/crawler; info@xmarks.com)',
              +			metadata: {
              +				uaFamily: 'XmarksFetch',
              +				uaName: 'XmarksFetch/1.0',
              +				uaUrl: 'http://www.xmarks.com/about/crawler',
              +				uaCompany: 'Xmarks, Inc.',
              +				uaCompanyUrl: 'http://www.xmarks.com/',
              +				uaIcon: 'bot_XmarksFetch.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=XmarksFetch'
              +			}
              +		},
              +		'2212': {
              +			userAgent: 'CorpusCrawler 2.0.10 (http://corpora.fi.muni.cz/crawler/)',
              +			metadata: {
              +				uaFamily: 'CorpusCrawler',
              +				uaName: 'CorpusCrawler 2.0.10',
              +				uaUrl: 'http://corpora.fi.muni.cz/crawler/',
              +				uaCompany: 'NLP - at the Faculty of Informatics, Masaryk University, Brno',
              +				uaCompanyUrl: 'http://nlp.fi.muni.cz/en/nlplab',
              +				uaIcon: 'bot_CorpusCrawler.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=CorpusCrawler'
              +			}
              +		},
              +		'2223': {
              +			userAgent: 'Mozilla/5.0 (compatible; aiHitBot/1.0; +http://www.aihit.com/)',
              +			metadata: {
              +				uaFamily: 'aiHitBot',
              +				uaName: 'aiHitBot/1.0',
              +				uaUrl: '',
              +				uaCompany: 'aiHit Ltd.',
              +				uaCompanyUrl: 'http://aihit.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=aiHitBot'
              +			}
              +		},
              +		'2233': {
              +			userAgent: 'Orgbybot/OrgbyBot v1.3 (Spider; http://orgby.com/bot/  ; Orgby.com Search Engine)',
              +			metadata: {
              +				uaFamily: 'OrgbyBot',
              +				uaName: 'OrgbyBot/1.3',
              +				uaUrl: 'http://orgby.com/bot/',
              +				uaCompany: 'Orgby.com',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=OrgbyBot'
              +			}
              +		},
              +		'2235': {
              +			userAgent: 'CorpusCrawler 2.0.12 (http://corpora.fi.muni.cz/crawler/)',
              +			metadata: {
              +				uaFamily: 'CorpusCrawler',
              +				uaName: 'CorpusCrawler 2.0.12',
              +				uaUrl: 'http://corpora.fi.muni.cz/crawler/',
              +				uaCompany: 'NLP - at the Faculty of Informatics, Masaryk University, Brno',
              +				uaCompanyUrl: 'http://nlp.fi.muni.cz/en/nlplab',
              +				uaIcon: 'bot_CorpusCrawler.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=CorpusCrawler'
              +			}
              +		},
              +		'2239': {
              +			userAgent: 'CorpusCrawler 2.0.13 (http://corpora.fi.muni.cz/crawler/)',
              +			metadata: {
              +				uaFamily: 'CorpusCrawler',
              +				uaName: 'CorpusCrawler 2.0.13',
              +				uaUrl: 'http://corpora.fi.muni.cz/crawler/',
              +				uaCompany: 'NLP - at the Faculty of Informatics, Masaryk University, Brno',
              +				uaCompanyUrl: 'http://nlp.fi.muni.cz/en/nlplab',
              +				uaIcon: 'bot_CorpusCrawler.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=CorpusCrawler'
              +			}
              +		},
              +		'2241': {
              +			userAgent: 'CorpusCrawler 2.0.14 (http://corpora.fi.muni.cz/crawler/)',
              +			metadata: {
              +				uaFamily: 'CorpusCrawler',
              +				uaName: 'CorpusCrawler 2.0.14',
              +				uaUrl: 'http://corpora.fi.muni.cz/crawler/',
              +				uaCompany: 'NLP - at the Faculty of Informatics, Masaryk University, Brno',
              +				uaCompanyUrl: 'http://nlp.fi.muni.cz/en/nlplab',
              +				uaIcon: 'bot_CorpusCrawler.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=CorpusCrawler'
              +			}
              +		},
              +		'2242': {
              +			userAgent: 'CorpusCrawler 2.0.15 (http://corpora.fi.muni.cz/crawler/)',
              +			metadata: {
              +				uaFamily: 'CorpusCrawler',
              +				uaName: 'CorpusCrawler 2.0.15',
              +				uaUrl: 'http://corpora.fi.muni.cz/crawler/',
              +				uaCompany: 'NLP - at the Faculty of Informatics, Masaryk University, Brno',
              +				uaCompanyUrl: 'http://nlp.fi.muni.cz/en/nlplab',
              +				uaIcon: 'bot_CorpusCrawler.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=CorpusCrawler'
              +			}
              +		},
              +		'2246': {
              +			userAgent: 'Mozilla/5.0 (compatible; Semager/1.4; http://www.semager.de/blog/semager-bots/)',
              +			metadata: {
              +				uaFamily: 'Semager',
              +				uaName: 'Semager/1.4',
              +				uaUrl: 'http://www.semager.de/blog/semager-bots/',
              +				uaCompany: 'NG-Marketing',
              +				uaCompanyUrl: 'http://www.ng-marketing.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Semager'
              +			}
              +		},
              +		'2279': {
              +			userAgent: 'yacybot (amd64 Linux 2.6.32-gentoo; java 1.6.0_17; Europe/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'2300': {
              +			userAgent: 'yacybot (x86 Windows 2003 5.2; java 1.6.0_16; Europe/de) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'2773': {
              +			userAgent: 'CorpusCrawler 2.0.17 (http://corpora.fi.muni.cz/crawler/);Project:CzCorpus',
              +			metadata: {
              +				uaFamily: 'CorpusCrawler',
              +				uaName: 'CorpusCrawler 2.0.17',
              +				uaUrl: 'http://corpora.fi.muni.cz/crawler/',
              +				uaCompany: 'NLP - at the Faculty of Informatics, Masaryk University, Brno',
              +				uaCompanyUrl: 'http://nlp.fi.muni.cz/en/nlplab',
              +				uaIcon: 'bot_CorpusCrawler.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=CorpusCrawler'
              +			}
              +		},
              +		'2844': {
              +			userAgent: 'CorpusCrawler 2.0.19 (http://corpora.fi.muni.cz/crawler/);Project:CzCorpus',
              +			metadata: {
              +				uaFamily: 'CorpusCrawler',
              +				uaName: 'CorpusCrawler 2.0.19',
              +				uaUrl: 'http://corpora.fi.muni.cz/crawler/',
              +				uaCompany: 'NLP - at the Faculty of Informatics, Masaryk University, Brno',
              +				uaCompanyUrl: 'http://nlp.fi.muni.cz/en/nlplab',
              +				uaIcon: 'bot_CorpusCrawler.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=CorpusCrawler'
              +			}
              +		},
              +		'2937': {
              +			userAgent: 'CorpusCrawler 2.0.20 (http://corpora.fi.muni.cz/crawler/);Project:CzCorpus',
              +			metadata: {
              +				uaFamily: 'CorpusCrawler',
              +				uaName: 'CorpusCrawler 2.0.20',
              +				uaUrl: 'http://corpora.fi.muni.cz/crawler/',
              +				uaCompany: 'NLP - at the Faculty of Informatics, Masaryk University, Brno',
              +				uaCompanyUrl: 'http://nlp.fi.muni.cz/en/nlplab',
              +				uaIcon: 'bot_CorpusCrawler.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=CorpusCrawler'
              +			}
              +		},
              +		'2947': {
              +			userAgent: 'Mozilla/5.0 (compatible; heritrix/1.14.2 +http://www.webarchiv.cz)',
              +			metadata: {
              +				uaFamily: 'heritrix',
              +				uaName: 'heritrix/1.14.2',
              +				uaUrl: 'http://crawler.archive.org/',
              +				uaCompany: 'Internet Archive',
              +				uaCompanyUrl: 'http://www.archive.org/',
              +				uaIcon: 'bot_heritrix.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=heritrix'
              +			}
              +		},
              +		'2948': {
              +			userAgent: 'CorpusCrawler 2.0.21 (http://corpora.fi.muni.cz/crawler/);Project:CzCorpus',
              +			metadata: {
              +				uaFamily: 'CorpusCrawler',
              +				uaName: 'CorpusCrawler 2.0.21',
              +				uaUrl: 'http://corpora.fi.muni.cz/crawler/',
              +				uaCompany: 'NLP - at the Faculty of Informatics, Masaryk University, Brno',
              +				uaCompanyUrl: 'http://nlp.fi.muni.cz/en/nlplab',
              +				uaIcon: 'bot_CorpusCrawler.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=CorpusCrawler'
              +			}
              +		},
              +		'2952': {
              +			userAgent: 'CorpusCrawler 2.0.22 (http://corpora.fi.muni.cz/crawler/);Project:CzCorpus',
              +			metadata: {
              +				uaFamily: 'CorpusCrawler',
              +				uaName: 'CorpusCrawler 2.0.22',
              +				uaUrl: 'http://corpora.fi.muni.cz/crawler/',
              +				uaCompany: 'NLP - at the Faculty of Informatics, Masaryk University, Brno',
              +				uaCompanyUrl: 'http://nlp.fi.muni.cz/en/nlplab',
              +				uaIcon: 'bot_CorpusCrawler.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=CorpusCrawler'
              +			}
              +		},
              +		'2999': {
              +			userAgent: 'CorpusCrawler 2.0.24 (http://corpora.fi.muni.cz/crawler/);Project:CzCorpus',
              +			metadata: {
              +				uaFamily: 'CorpusCrawler',
              +				uaName: 'CorpusCrawler 2.0.24',
              +				uaUrl: 'http://corpora.fi.muni.cz/crawler/',
              +				uaCompany: 'NLP - at the Faculty of Informatics, Masaryk University, Brno',
              +				uaCompanyUrl: 'http://nlp.fi.muni.cz/en/nlplab',
              +				uaIcon: 'bot_CorpusCrawler.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=CorpusCrawler'
              +			}
              +		},
              +		'3002': {
              +			userAgent: 'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; FeedFinder-2.0; http://bloggz.se/crawler)',
              +			metadata: {
              +				uaFamily: 'FeedFinder/bloggz.se',
              +				uaName: 'FeedFinder-2.0',
              +				uaUrl: 'http://bloggz.se/crawler/',
              +				uaCompany: 'Triop AB',
              +				uaCompanyUrl: 'http://triop.se/',
              +				uaIcon: 'bot_FeedFinder_bloggz.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=FeedFinder/bloggz.se'
              +			}
              +		},
              +		'3003': {
              +			userAgent: 'CorpusCrawler 2.0.25 (http://corpora.fi.muni.cz/crawler/);Project:CzCorpus',
              +			metadata: {
              +				uaFamily: 'CorpusCrawler',
              +				uaName: 'CorpusCrawler 2.0.25',
              +				uaUrl: 'http://corpora.fi.muni.cz/crawler/',
              +				uaCompany: 'NLP - at the Faculty of Informatics, Masaryk University, Brno',
              +				uaCompanyUrl: 'http://nlp.fi.muni.cz/en/nlplab',
              +				uaIcon: 'bot_CorpusCrawler.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=CorpusCrawler'
              +			}
              +		},
              +		'3034': {
              +			userAgent: 'yacybot (i386 Linux 2.6.26-2-686; java 1.6.0_0; Europe/de) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'3132': {
              +			userAgent: 'SeznamBot/2.0-Test (+http://fulltext.sblog.cz/robot/)',
              +			metadata: {
              +				uaFamily: 'SeznamBot',
              +				uaName: 'SeznamBot/2.0-test',
              +				uaUrl: 'http://napoveda.seznam.cz/en/indexing-the-web.html',
              +				uaCompany: 'Seznam.cz, a.s.',
              +				uaCompanyUrl: 'http://www.seznam.cz/',
              +				uaIcon: 'seznam.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SeznamBot'
              +			}
              +		},
              +		'3142': {
              +			userAgent: 'SEOENGBot/1.2 (+http://learn.seoeng.com/seoengbot.htm)',
              +			metadata: {
              +				uaFamily: 'SEOENGBot',
              +				uaName: 'SEOENGBot/1.2 old',
              +				uaUrl: 'http://www.seoengine.com/seoengbot.htm',
              +				uaCompany: 'SEO Engine',
              +				uaCompanyUrl: 'http://www.seoengine.com/',
              +				uaIcon: 'bot_SEOENGBot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SEOENGBot'
              +			}
              +		},
              +		'3203': {
              +			userAgent: 'Mozilla/5.0 (compatible; ScoutJet; http://www.scoutjet.com/)',
              +			metadata: {
              +				uaFamily: 'ScoutJet',
              +				uaName: 'ScoutJet',
              +				uaUrl: 'http://www.scoutjet.com/',
              +				uaCompany: 'blekko, inc.',
              +				uaCompanyUrl: 'http://blekko.com/',
              +				uaIcon: 'bot_ScoutJet.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ScoutJet'
              +			}
              +		},
              +		'3221': {
              +			userAgent: 'yacybot (i386 Linux 2.6.31-18-generic; java 1.6.0_0; Europe/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'3235': {
              +			userAgent: 'Mozilla/4.0 (compatible; HostTracker.com/1.0;+http://host-tracker.com/)',
              +			metadata: {
              +				uaFamily: 'HostTracker.com',
              +				uaName: 'HostTracker.com/1.0',
              +				uaUrl: 'http://host-tracker.com/',
              +				uaCompany: 'host-tracker.com ',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_HostTracker.com.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=HostTracker.com'
              +			}
              +		},
              +		'3236': {
              +			userAgent: 'Mozilla/5.0 (compatible; AportWorm/3.2; +http://www.aport.ru/help)',
              +			metadata: {
              +				uaFamily: 'AportWorm',
              +				uaName: 'AportWorm/3.2',
              +				uaUrl: 'http://www.aport.ru/help/',
              +				uaCompany: 'Golden Telecom',
              +				uaCompanyUrl: 'http://goldentelecom.ru/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=AportWorm'
              +			}
              +		},
              +		'3238': {
              +			userAgent: 'yacybot (i386 Linux 2.6.30-2-686; java 1.6.0_0; SystemV/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'3292': {
              +			userAgent: 'Karneval-Bot (Version: 1.06, powered by www.karnevalsuchmaschine.de +http://www.karnevalsuchmaschine.de/bot.html)',
              +			metadata: {
              +				uaFamily: 'Karneval-Bot',
              +				uaName: 'Karneval-Bot/1.06',
              +				uaUrl: 'http://www.karnevalsuchmaschine.de/zeige/bot.html',
              +				uaCompany: 'F\xf6deration Europ\xe4ischer Narren',
              +				uaCompanyUrl: 'http://www.fen-sued.de/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Karneval-Bot'
              +			}
              +		},
              +		'3333': {
              +			userAgent: 'Mozilla/5.0 (compatible; dotSemantic/1.0; +http://www.dotsemantic.org)',
              +			metadata: {
              +				uaFamily: 'dotSemantic',
              +				uaName: 'dotSemantic/1.0',
              +				uaUrl: 'http://www.dotsemantic.org',
              +				uaCompany: 'dotSemantic Projekt',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=dotSemantic'
              +			}
              +		},
              +		'3379': {
              +			userAgent: 'Mozilla/5.0 (compatible; spbot/1.0; +http://www.seoprofiler.com/bot/ )',
              +			metadata: {
              +				uaFamily: 'spbot',
              +				uaName: 'spbot/1.0',
              +				uaUrl: 'http://www.seoprofiler.com/bot/',
              +				uaCompany: 'Axandra GmbH',
              +				uaCompanyUrl: 'http://www.axandra.com/',
              +				uaIcon: 'bot_spbot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=spbot'
              +			}
              +		},
              +		'3398': {
              +			userAgent: 'L.webis/0.44 (http://webalgo.iit.cnr.it/index.php?pg=lwebis)',
              +			metadata: {
              +				uaFamily: 'L.webis',
              +				uaName: 'L.webis/0.44',
              +				uaUrl: 'http://webalgo.iit.cnr.it/index.php?pg=lwebis',
              +				uaCompany: 'Institute of Informatics and Telematics (IIT)',
              +				uaCompanyUrl: 'http://www.iit.cnr.it/',
              +				uaIcon: 'bot_L.webis.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=L.webis'
              +			}
              +		},
              +		'3409': {
              +			userAgent: 'Cityreview Robot (+http://www.cityreview.org/crawler/)',
              +			metadata: {
              +				uaFamily: 'cityreview',
              +				uaName: 'cityreview',
              +				uaUrl: 'http://www.cityreview.org/crawler/',
              +				uaCompany: 'SISTRIX GmbH',
              +				uaCompanyUrl: 'http://www.sistrix.com/',
              +				uaIcon: 'bot_cityreview.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=cityreview'
              +			}
              +		},
              +		'3415': {
              +			userAgent: 'Ruky-Roboter (Version: 1.06, powered by www.ruky.de +http://www.ruky.de/bot.html)',
              +			metadata: {
              +				uaFamily: 'Ruky-Roboter',
              +				uaName: 'Ruky-Roboter/1.06',
              +				uaUrl: 'http://www.ruky.de/zeige/bot.html',
              +				uaCompany: 'ruky.de',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Ruky-Roboter'
              +			}
              +		},
              +		'3422': {
              +			userAgent: 'Mozilla/5.0 (compatible; abby/1.0; +http://www.ellerdale.com/crawler.html)',
              +			metadata: {
              +				uaFamily: 'abby',
              +				uaName: 'abby/1.0',
              +				uaUrl: 'http://www.ellerdale.com/crawler.html',
              +				uaCompany: 'Ellerdale Inc.',
              +				uaCompanyUrl: 'http://www.ellerdale.com/',
              +				uaIcon: 'bot_abby.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=abby'
              +			}
              +		},
              +		'3441': {
              +			userAgent: '^Nail (http://CaretNail.com)',
              +			metadata: {
              +				uaFamily: '^Nail',
              +				uaName: '^Nail',
              +				uaUrl: 'http://caret.us.com/caretnail/index.html',
              +				uaCompany: 'HydraByte, Inc.',
              +				uaCompanyUrl: 'http://www.hydrabyte.com/',
              +				uaIcon: 'bot_Nail.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=^Nail'
              +			}
              +		},
              +		'3445': {
              +			userAgent: 'ichiro/4.0 (http://help.goo.ne.jp/door/crawler.html)',
              +			metadata: {
              +				uaFamily: 'ichiro',
              +				uaName: 'ichiro/4.0',
              +				uaUrl: 'http://search.goo.ne.jp/option/use/sub4/sub4-1/',
              +				uaCompany: 'NTT-Resonant Inc.',
              +				uaCompanyUrl: 'http://www.nttr.co.jp/',
              +				uaIcon: 'bot_ichiro.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ichiro'
              +			}
              +		},
              +		'3561': {
              +			userAgent: 'Mozilla/5.0 (compatible; spbot/1.1; +http://www.seoprofiler.com/bot/ )',
              +			metadata: {
              +				uaFamily: 'spbot',
              +				uaName: 'spbot/1.1',
              +				uaUrl: 'http://www.seoprofiler.com/bot/',
              +				uaCompany: 'Axandra GmbH',
              +				uaCompanyUrl: 'http://www.axandra.com/',
              +				uaIcon: 'bot_spbot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=spbot'
              +			}
              +		},
              +		'3589': {
              +			userAgent: 'Mozilla/5.0 (compatible; spbot/1.2; +http://www.seoprofiler.com/bot/ )',
              +			metadata: {
              +				uaFamily: 'spbot',
              +				uaName: 'spbot/1.2',
              +				uaUrl: 'http://www.seoprofiler.com/bot/',
              +				uaCompany: 'Axandra GmbH',
              +				uaCompanyUrl: 'http://www.axandra.com/',
              +				uaIcon: 'bot_spbot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=spbot'
              +			}
              +		},
              +		'3600': {
              +			userAgent: 'HolmesBot (http://holmes.ge)',
              +			metadata: {
              +				uaFamily: 'HolmesBot',
              +				uaName: 'HolmesBot',
              +				uaUrl: '',
              +				uaCompany: 'Georgian Railway Telecom',
              +				uaCompanyUrl: 'http://grt.ge/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=HolmesBot'
              +			}
              +		},
              +		'3703': {
              +			userAgent: 'Mozilla/5.0 (compatible; Falconsbot; +http://ws.nju.edu.cn/falcons/)',
              +			metadata: {
              +				uaFamily: 'Falconsbot',
              +				uaName: 'Falconsbot',
              +				uaUrl: 'http://ws.nju.edu.cn/falcons/contact_us.jsp',
              +				uaCompany: 'Institute of Web Science',
              +				uaCompanyUrl: 'http://iws.seu.edu.cn/page/english/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Falconsbot'
              +			}
              +		},
              +		'3734': {
              +			userAgent: 'Mozilla/5.0 (compatible; spbot/2.0; +http://www.seoprofiler.com/bot/ )',
              +			metadata: {
              +				uaFamily: 'spbot',
              +				uaName: 'spbot/2.0',
              +				uaUrl: 'http://www.seoprofiler.com/bot/',
              +				uaCompany: 'Axandra GmbH',
              +				uaCompanyUrl: 'http://www.axandra.com/',
              +				uaIcon: 'bot_spbot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=spbot'
              +			}
              +		},
              +		'4000': {
              +			userAgent: 'Mozilla/4.0 (Toread-Crawler/1.1; +http://news.toread.cc/crawler.php)',
              +			metadata: {
              +				uaFamily: 'Toread-Crawler',
              +				uaName: 'Toread-Crawler/1.1',
              +				uaUrl: 'http://news.toread.cc/crawler.php',
              +				uaCompany: 'sidefeed, Inc',
              +				uaCompanyUrl: 'http://sidefeed.com/',
              +				uaIcon: 'bot_Toread-Crawler.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Toread-Crawler'
              +			}
              +		},
              +		'4095': {
              +			userAgent: 'msnbot/2.0b (+http://search.msn.com/msnbot.htm).',
              +			metadata: {
              +				uaFamily: 'MSNBot',
              +				uaName: 'MSNBot/2.0b + .',
              +				uaUrl: 'http://search.msn.com/msnbot.htm',
              +				uaCompany: 'Microsoft Corporation',
              +				uaCompanyUrl: 'http://www.microsoft.com/',
              +				uaIcon: 'bot_msnbot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MSNBot'
              +			}
              +		},
              +		'4097': {
              +			userAgent: 'Mozilla/5.0 (compatible; spbot/2.0.1; +http://www.seoprofiler.com/bot/ )',
              +			metadata: {
              +				uaFamily: 'spbot',
              +				uaName: 'spbot/2.0.1',
              +				uaUrl: 'http://www.seoprofiler.com/bot/',
              +				uaCompany: 'Axandra GmbH',
              +				uaCompanyUrl: 'http://www.axandra.com/',
              +				uaIcon: 'bot_spbot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=spbot'
              +			}
              +		},
              +		'4185': {
              +			userAgent: 'Mozilla/5.0 (compatible; Speedy Spider; http://www.entireweb.com/about/search_tech/speedy_spider/)',
              +			metadata: {
              +				uaFamily: 'Speedy',
              +				uaName: 'Speedy Spider',
              +				uaUrl: '',
              +				uaCompany: 'Entireweb Sweden AB',
              +				uaCompanyUrl: 'http://www.entireweb.com/',
              +				uaIcon: 'bot_Speedy.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Speedy'
              +			}
              +		},
              +		'4264': {
              +			userAgent: 'L.webis/0.50 (http://webalgo.iit.cnr.it/index.php?pg=lwebis)',
              +			metadata: {
              +				uaFamily: 'L.webis',
              +				uaName: 'L.webis/0.50',
              +				uaUrl: 'http://webalgo.iit.cnr.it/index.php?pg=lwebis',
              +				uaCompany: 'Institute of Informatics and Telematics (IIT)',
              +				uaCompanyUrl: 'http://www.iit.cnr.it/',
              +				uaIcon: 'bot_L.webis.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=L.webis'
              +			}
              +		},
              +		'4336': {
              +			userAgent: 'Nuhk/2.4 ( http://www.neti.ee/cgi-bin/abi/Otsing/Nuhk/)',
              +			metadata: {
              +				uaFamily: 'Nuhk',
              +				uaName: 'Nuhk/2.4',
              +				uaUrl: 'http://www.neti.ee/cgi-bin/abi/Otsing/Nuhk/',
              +				uaCompany: 'Elion',
              +				uaCompanyUrl: 'http://www.neti.ee/',
              +				uaIcon: 'bot_Nuhk.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Nuhk'
              +			}
              +		},
              +		'4337': {
              +			userAgent: 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) Speedy Spider (http://www.entireweb.com/about/search_tech/speedy_spider/)',
              +			metadata: {
              +				uaFamily: 'Speedy',
              +				uaName: 'Speedy Spider',
              +				uaUrl: '',
              +				uaCompany: 'Entireweb Sweden AB',
              +				uaCompanyUrl: 'http://www.entireweb.com/',
              +				uaIcon: 'bot_Speedy.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Speedy'
              +			}
              +		},
              +		'4377': {
              +			userAgent: 'Mozilla/5.0 (compatible; spbot/2.0.2; +http://www.seoprofiler.com/bot/ )',
              +			metadata: {
              +				uaFamily: 'spbot',
              +				uaName: 'spbot/2.0.2',
              +				uaUrl: 'http://www.seoprofiler.com/bot/',
              +				uaCompany: 'Axandra GmbH',
              +				uaCompanyUrl: 'http://www.axandra.com/',
              +				uaIcon: 'bot_spbot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=spbot'
              +			}
              +		},
              +		'4411': {
              +			userAgent: 'msnbot/2.0b (+http://search.msn.com/msnbot.htm)._',
              +			metadata: {
              +				uaFamily: 'MSNBot',
              +				uaName: 'MSNBot/2.0b + ._',
              +				uaUrl: 'http://search.msn.com/msnbot.htm',
              +				uaCompany: 'Microsoft Corporation',
              +				uaCompanyUrl: 'http://www.microsoft.com/',
              +				uaIcon: 'bot_msnbot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MSNBot'
              +			}
              +		},
              +		'4423': {
              +			userAgent: 'yacybot (amd64 Linux 2.6.28-18-generic; java 1.6.0_16; GMT/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'4437': {
              +			userAgent: 'SeznamBot/3.0-alpha (+http://fulltext.sblog.cz/)',
              +			metadata: {
              +				uaFamily: 'SeznamBot',
              +				uaName: 'SeznamBot/3.0-alpha',
              +				uaUrl: 'http://napoveda.seznam.cz/en/indexing-the-web.html',
              +				uaCompany: 'Seznam.cz, a.s.',
              +				uaCompanyUrl: 'http://www.seznam.cz/',
              +				uaIcon: 'seznam.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SeznamBot'
              +			}
              +		},
              +		'4501': {
              +			userAgent: 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1 + FairShare-http://fairshare.cc)',
              +			metadata: {
              +				uaFamily: 'FairShare',
              +				uaName: 'FairShare',
              +				uaUrl: 'http://support.attributor.com/kbfairshare/doku.php',
              +				uaCompany: 'Attributor Corporation',
              +				uaCompanyUrl: 'http://www.attributor.com/',
              +				uaIcon: 'bot_FairShare.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=FairShare'
              +			}
              +		},
              +		'4512': {
              +			userAgent: 'Mozilla/5.0 (compatible; Search17Bot/1.1; http://www.search17.com/bot.php)',
              +			metadata: {
              +				uaFamily: 'Search17Bot',
              +				uaName: 'Search17Bot/1.1',
              +				uaUrl: 'http://www.search17.com/bot.php',
              +				uaCompany: 'search17.com',
              +				uaCompanyUrl: 'http://www.search17.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Search17Bot'
              +			}
              +		},
              +		'4519': {
              +			userAgent: 'Mozilla/5.0 (compatible; BlinkaCrawler/1.0; +http://www.blinka.jp/crawler/)',
              +			metadata: {
              +				uaFamily: 'BlinkaCrawler',
              +				uaName: 'BlinkaCrawler/1.0',
              +				uaUrl: 'http://www.blinka.jp/crawler/',
              +				uaCompany: 'Blinka project',
              +				uaCompanyUrl: 'http://www.blinka.jp/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=BlinkaCrawler'
              +			}
              +		},
              +		'4546': {
              +			userAgent: 'Web-sniffer/1.0.31 (+http://web-sniffer.net/)',
              +			metadata: {
              +				uaFamily: 'Web-sniffer',
              +				uaName: 'Web-sniffer/1.0.31',
              +				uaUrl: '',
              +				uaCompany: 'Lingo4you GbR',
              +				uaCompanyUrl: 'http://www.lingo4u.de/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Web-sniffer'
              +			}
              +		},
              +		'4589': {
              +			userAgent: 'MetaURI API +metauri.com',
              +			metadata: {
              +				uaFamily: 'MetaURI',
              +				uaName: 'MetaURI',
              +				uaUrl: 'http://metauri.com/static/about',
              +				uaCompany: 'Stateless Systems',
              +				uaCompanyUrl: 'http://statelesssystems.com/',
              +				uaIcon: 'bot_MetaURI.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MetaURI'
              +			}
              +		},
              +		'4590': {
              +			userAgent: 'L.webis/0.51 (http://webalgo.iit.cnr.it/index.php?pg=lwebis)',
              +			metadata: {
              +				uaFamily: 'L.webis',
              +				uaName: 'L.webis/0.51',
              +				uaUrl: 'http://webalgo.iit.cnr.it/index.php?pg=lwebis',
              +				uaCompany: 'Institute of Informatics and Telematics (IIT)',
              +				uaCompanyUrl: 'http://www.iit.cnr.it/',
              +				uaIcon: 'bot_L.webis.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=L.webis'
              +			}
              +		},
              +		'4591': {
              +			userAgent: 'L.webis/0.53 (http://webalgo.iit.cnr.it/index.php?pg=lwebis)',
              +			metadata: {
              +				uaFamily: 'L.webis',
              +				uaName: 'L.webis/0.53',
              +				uaUrl: 'http://webalgo.iit.cnr.it/index.php?pg=lwebis',
              +				uaCompany: 'Institute of Informatics and Telematics (IIT)',
              +				uaCompanyUrl: 'http://www.iit.cnr.it/',
              +				uaIcon: 'bot_L.webis.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=L.webis'
              +			}
              +		},
              +		'4722': {
              +			userAgent: 'Mozilla/5.0 (FauBot/0.1; +http://buzzvolume.com/fau/)',
              +			metadata: {
              +				uaFamily: 'FauBot',
              +				uaName: 'FauBot/0.1',
              +				uaUrl: 'http://buzzvolume.com/fau',
              +				uaCompany: 'BuzzVolume',
              +				uaCompanyUrl: 'http://buzzvolume.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=FauBot'
              +			}
              +		},
              +		'4726': {
              +			userAgent: 'Googlebot-Video/1.0',
              +			metadata: {
              +				uaFamily: 'Googlebot',
              +				uaName: 'Googlebot-Video/1.0',
              +				uaUrl: 'http://support.google.com/webmasters/bin/answer.py?hl=en&answer=1061943',
              +				uaCompany: 'Google Inc.',
              +				uaCompanyUrl: 'http://www.google.com/',
              +				uaIcon: 'bot_googlebot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Googlebot'
              +			}
              +		},
              +		'4730': {
              +			userAgent: 'Eurobot/1.2 (http://eurobot.ayell.eu)',
              +			metadata: {
              +				uaFamily: 'Eurobot',
              +				uaName: 'Eurobot/1.2',
              +				uaUrl: 'http://eurobot.ayell.eu/',
              +				uaCompany: 'Ayell Euronet',
              +				uaCompanyUrl: 'http://www.ayell.eu/',
              +				uaIcon: 'bot_eurobot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Eurobot'
              +			}
              +		},
              +		'4733': {
              +			userAgent: 'Mozilla/5.0 (compatible; bixolabs/1.0; +http://bixolabs.com/crawler/general; crawler@bixolabs.com)',
              +			metadata: {
              +				uaFamily: 'bixocrawler',
              +				uaName: 'bixolabs/1.0',
              +				uaUrl: 'http://wiki.github.com/bixo/bixo/bixocrawler',
              +				uaCompany: 'Bixo Labs',
              +				uaCompanyUrl: 'http://openbixo.org/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=bixocrawler'
              +			}
              +		},
              +		'4747': {
              +			userAgent: 'yacybot (x86 Windows XP 5.1; java 1.6.0_18; Europe/de) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'4830': {
              +			userAgent: 'yacybot (i386 Linux 2.6.31-21-generic; java 1.6.0_0; Europe/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'4844': {
              +			userAgent: 'livedoor ScreenShot/0.10',
              +			metadata: {
              +				uaFamily: 'livedoor ScreenShot',
              +				uaName: 'livedoor ScreenShot/0.10',
              +				uaUrl: 'http://helpguide.livedoor.com/help/screenshot/qa/grp584?id=3042',
              +				uaCompany: 'livedoor Co.,Ltd.',
              +				uaCompanyUrl: 'http://corp.livedoor.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=livedoor ScreenShot'
              +			}
              +		},
              +		'4846': {
              +			userAgent: 'Mozilla/5.0 (compatible; MJ12bot/v1.3.3; http://www.majestic12.co.uk/bot.php?+)',
              +			metadata: {
              +				uaFamily: 'MJ12bot',
              +				uaName: 'MJ12bot/v1.3.3',
              +				uaUrl: 'http://majestic12.co.uk/bot.php',
              +				uaCompany: 'Majestic-12',
              +				uaCompanyUrl: 'http://www.majestic12.co.uk/',
              +				uaIcon: 'bot_mj12bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MJ12bot'
              +			}
              +		},
              +		'4853': {
              +			userAgent: 'findlinks/1.1.6-beta1 (+http://wortschatz.uni-leipzig.de/findlinks/)',
              +			metadata: {
              +				uaFamily: 'findlinks',
              +				uaName: 'findlinks/1.1.6-beta1',
              +				uaUrl: 'http://wortschatz.uni-leipzig.de/findlinks/',
              +				uaCompany: 'Universit\xe4t Leipzig',
              +				uaCompanyUrl: 'http://www.uni-leipzig.de/',
              +				uaIcon: 'bot_findlinks.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=findlinks'
              +			}
              +		},
              +		'4866': {
              +			userAgent: 'nodestackbot/0.1 (bot@nodestack.com http://nodestack.com/bot.html)',
              +			metadata: {
              +				uaFamily: 'nodestackbot',
              +				uaName: 'nodestackbot/0.1',
              +				uaUrl: 'http://nodestack.com/bot.html',
              +				uaCompany: 'nodestack.com',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=nodestackbot'
              +			}
              +		},
              +		'4876': {
              +			userAgent: 'Mozilla/5.0 (compatible; Plukkie/1.3; http://www.botje.com/plukkie.htm)',
              +			metadata: {
              +				uaFamily: 'Plukkie',
              +				uaName: 'Plukkie/1.3',
              +				uaUrl: 'http://www.botje.com/plukkie.htm',
              +				uaCompany: 'botje.com',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Plukkie'
              +			}
              +		},
              +		'4888': {
              +			userAgent: 'Mozilla/5.0 ( compatible; SETOOZBOT/0.30 ; http://www.setooz.com/bot.html )',
              +			metadata: {
              +				uaFamily: 'Setoozbot',
              +				uaName: 'SETOOZBOT/0.30 a',
              +				uaUrl: 'http://www.setooz.com/oozbot.html',
              +				uaCompany: 'SETU Software Systems (P) Ltd.',
              +				uaCompanyUrl: 'http://www.setusoftware.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Setoozbot'
              +			}
              +		},
              +		'4898': {
              +			userAgent: 'Yaanb/1.5.001 (compatible; Win64;)',
              +			metadata: {
              +				uaFamily: 'Yaanb',
              +				uaName: 'Yaanb/1.5.001',
              +				uaUrl: 'http://www.yaanb.com/company/?p=bot',
              +				uaCompany: 'Yaanb',
              +				uaCompanyUrl: 'http://www.yaanb.com/company/',
              +				uaIcon: 'bot_Yaanb.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Yaanb'
              +			}
              +		},
              +		'4907': {
              +			userAgent: 'Mozilla/5.0 ( compatible; SETOOZBOT/0.30 ; http://www.setooz.com/bot.html ; agentname at setooz dot_com )',
              +			metadata: {
              +				uaFamily: 'Setoozbot',
              +				uaName: 'SETOOZBOT/0.30 b',
              +				uaUrl: 'http://www.setooz.com/oozbot.html',
              +				uaCompany: 'SETU Software Systems (P) Ltd.',
              +				uaCompanyUrl: 'http://www.setusoftware.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Setoozbot'
              +			}
              +		},
              +		'4911': {
              +			userAgent: 'Mozilla/5.0 (compatible; spbot/2.0.3; +http://www.seoprofiler.com/bot/ )',
              +			metadata: {
              +				uaFamily: 'spbot',
              +				uaName: 'spbot/2.0.3',
              +				uaUrl: 'http://www.seoprofiler.com/bot/',
              +				uaCompany: 'Axandra GmbH',
              +				uaCompanyUrl: 'http://www.axandra.com/',
              +				uaIcon: 'bot_spbot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=spbot'
              +			}
              +		},
              +		'4914': {
              +			userAgent: 'Yaanb/1.5.001 (compatible; Win64;+http://www.yaanb.com/company/bot.hmtl)',
              +			metadata: {
              +				uaFamily: 'Yaanb',
              +				uaName: 'Yaanb/1.5.001 b',
              +				uaUrl: 'http://www.yaanb.com/company/?p=bot',
              +				uaCompany: 'Yaanb',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_Yaanb.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Yaanb'
              +			}
              +		},
              +		'4922': {
              +			userAgent: 'Mozilla/5.0 (compatible; spbot/2.0.4; +http://www.seoprofiler.com/bot )',
              +			metadata: {
              +				uaFamily: 'spbot',
              +				uaName: 'spbot/2.0.4',
              +				uaUrl: 'http://www.seoprofiler.com/bot/',
              +				uaCompany: 'Axandra GmbH',
              +				uaCompanyUrl: 'http://www.axandra.com/',
              +				uaIcon: 'bot_spbot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=spbot'
              +			}
              +		},
              +		'4936': {
              +			userAgent: 'R6_CommentReader(www.radian6.com/crawler)',
              +			metadata: {
              +				uaFamily: 'R6 bot',
              +				uaName: 'R6_CommentReader',
              +				uaUrl: 'http://www.radian6.com/crawler/',
              +				uaCompany: 'Radian6 Technologies Inc',
              +				uaCompanyUrl: 'http://www.radian6.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=R6 bot'
              +			}
              +		},
              +		'4939': {
              +			userAgent: 'CamontSpider/1.0 +http://epweb2.ph.bham.ac.uk/user/slater/camont/info.html',
              +			metadata: {
              +				uaFamily: 'CamontSpider',
              +				uaName: 'CamontSpider/1.0',
              +				uaUrl: 'http://epweb2.ph.bham.ac.uk/user/slater/camont/info.html',
              +				uaCompany: 'Camtology consortium',
              +				uaCompanyUrl: 'http://www.hep.phy.cam.ac.uk/~parker/camtology/about.html',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=CamontSpider'
              +			}
              +		},
              +		'4940': {
              +			userAgent: 'Pompos/1.3 http://dir.com/pompos.html',
              +			metadata: {
              +				uaFamily: 'Pompos',
              +				uaName: 'Pompos/1.3',
              +				uaUrl: 'http://dir.com/pompos.html',
              +				uaCompany: 'Iliad',
              +				uaCompanyUrl: 'http://www.iliad.fr/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Pompos'
              +			}
              +		},
              +		'4946': {
              +			userAgent: 'FyberSpider/1.3 (http://www.fybersearch.com/fyberspider.php)',
              +			metadata: {
              +				uaFamily: 'FyberSpider',
              +				uaName: 'FyberSpider/1.3',
              +				uaUrl: 'http://www.fybersearch.com/fyberspider.php',
              +				uaCompany: 'FyberSearch',
              +				uaCompanyUrl: 'http://www.fybersearch.com/',
              +				uaIcon: 'bot_FyberSpider.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=FyberSpider'
              +			}
              +		},
              +		'4966': {
              +			userAgent: 'Googlebot/2.1 (+http://www.google.com/bot.html)',
              +			metadata: {
              +				uaFamily: 'Googlebot',
              +				uaName: 'Googlebot/2.1',
              +				uaUrl: 'http://support.google.com/webmasters/bin/answer.py?hl=en&answer=1061943',
              +				uaCompany: 'Google Inc.',
              +				uaCompanyUrl: 'http://www.google.com/',
              +				uaIcon: 'bot_googlebot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Googlebot'
              +			}
              +		},
              +		'4974': {
              +			userAgent: 'yacybot (amd64 Linux 2.6.26-2-amd64; java 1.6.0_0; Europe/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'4975': {
              +			userAgent: 'yacybot (i386 Linux 2.6.32-22-generic; java 1.6.0_20; Europe/de) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'4977': {
              +			userAgent: 'CatchBot/2.0; +http://www.catchbot.com',
              +			metadata: {
              +				uaFamily: 'CatchBot',
              +				uaName: 'CatchBot/2.0',
              +				uaUrl: 'http://www.catchbot.com/',
              +				uaCompany: 'Reed Business Information Pty Limited',
              +				uaCompanyUrl: 'http://www.reedbusiness.com/',
              +				uaIcon: 'bot_CatchBot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=CatchBot'
              +			}
              +		},
              +		'4996': {
              +			userAgent: 'magpie-crawler/1.1 (U; Linux amd64; en-GB; +http://www.brandwatch.net)',
              +			metadata: {
              +				uaFamily: 'magpie-crawler',
              +				uaName: 'magpie-crawler/1.1',
              +				uaUrl: 'http://www.brandwatch.com/how-it-works/gathering-data/',
              +				uaCompany: 'Brandwatch',
              +				uaCompanyUrl: 'http://www.brandwatch.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=magpie-crawler'
              +			}
              +		},
              +		'4999': {
              +			userAgent: 'Mozilla/5.0 (compatible; XML Sitemaps Generator; http://www.xml-sitemaps.com) Gecko XML-Sitemaps/1.0',
              +			metadata: {
              +				uaFamily: 'XML Sitemaps Generator',
              +				uaName: 'XML Sitemaps Generator/1.0',
              +				uaUrl: 'http://www.xml-sitemaps.com/',
              +				uaCompany: 'xml-sitemaps.com',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=XML Sitemaps Generator'
              +			}
              +		},
              +		'5003': {
              +			userAgent: 'Mozilla/5.0 (compatible; Nigma.ru/3.0; crawler@nigma.ru)',
              +			metadata: {
              +				uaFamily: 'Nigma.ru',
              +				uaName: 'Nigma.ru/3.0',
              +				uaUrl: '',
              +				uaCompany: 'Nigma.ru',
              +				uaCompanyUrl: 'http://nigma.ru/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Nigma.ru'
              +			}
              +		},
              +		'5006': {
              +			userAgent: 'TwengaBot-Discover (http://www.twenga.fr/bot-discover.html)',
              +			metadata: {
              +				uaFamily: 'TwengaBot',
              +				uaName: 'TwengaBot-Discover',
              +				uaUrl: 'http://www.twenga.com/bot.html',
              +				uaCompany: 'Twenga SA',
              +				uaCompanyUrl: 'http://www.twenga.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=TwengaBot'
              +			}
              +		},
              +		'5007': {
              +			userAgent: 'Zookabot/2.0;++http://zookabot.com',
              +			metadata: {
              +				uaFamily: 'Zookabot',
              +				uaName: 'Zookabot/2.0',
              +				uaUrl: 'http://zookabot.com/',
              +				uaCompany: 'Hwacha ApS',
              +				uaCompanyUrl: 'http://hwacha.dk/',
              +				uaIcon: 'bot_Zookabot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Zookabot'
              +			}
              +		},
              +		'5010': {
              +			userAgent: 'Mozilla/5.0 (compatible; YandexBot/3.0; +http://yandex.com/bots)',
              +			metadata: {
              +				uaFamily: 'YandexBot',
              +				uaName: 'YandexBot/3.0',
              +				uaUrl: 'http://yandex.com/bots',
              +				uaCompany: 'Yandex LLC',
              +				uaCompanyUrl: 'http://company.yandex.com/',
              +				uaIcon: 'bot_Yandex.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=YandexBot'
              +			}
              +		},
              +		'5014': {
              +			userAgent: 'Mozilla/5.0 (compatible; YandexImages/3.0; +http://yandex.com/bots)',
              +			metadata: {
              +				uaFamily: 'YandexBot',
              +				uaName: 'YandexImages/3.0',
              +				uaUrl: 'http://yandex.com/bots',
              +				uaCompany: 'Yandex LLC',
              +				uaCompanyUrl: 'http://company.yandex.com/',
              +				uaIcon: 'bot_Yandex.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=YandexBot'
              +			}
              +		},
              +		'5016': {
              +			userAgent: 'Mozilla/5.0 (compatible; YandexBot/3.0; MirrorDetector; +http://yandex.com/bots)',
              +			metadata: {
              +				uaFamily: 'YandexBot',
              +				uaName: 'YandexBot/3.0-MirrorDetector',
              +				uaUrl: 'http://yandex.com/bots',
              +				uaCompany: 'Yandex LLC',
              +				uaCompanyUrl: 'http://company.yandex.com/',
              +				uaIcon: 'bot_Yandex.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=YandexBot'
              +			}
              +		},
              +		'5052': {
              +			userAgent: 'findlinks/1.1.6-beta2 (+http://wortschatz.uni-leipzig.de/findlinks/)',
              +			metadata: {
              +				uaFamily: 'findlinks',
              +				uaName: 'findlinks/1.1.6-beta2',
              +				uaUrl: 'http://wortschatz.uni-leipzig.de/findlinks/',
              +				uaCompany: 'Universit\xe4t Leipzig',
              +				uaCompanyUrl: 'http://www.uni-leipzig.de/',
              +				uaIcon: 'bot_findlinks.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=findlinks'
              +			}
              +		},
              +		'5056': {
              +			userAgent: 'netEstate RSS crawler (+http://www.rss-directory.info/)',
              +			metadata: {
              +				uaFamily: 'netEstate Crawler',
              +				uaName: 'netEstate RSS crawler',
              +				uaUrl: '',
              +				uaCompany: 'netEstate GmbH',
              +				uaCompanyUrl: 'http://www.netestate.de/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=netEstate Crawler'
              +			}
              +		},
              +		'5057': {
              +			userAgent: 'Mozilla/5.0 (compatible; Qualidator.com Bot 1.0;)',
              +			metadata: {
              +				uaFamily: 'Qualidator.com Bot',
              +				uaName: 'Qualidator.com Bot 1.0',
              +				uaUrl: 'http://www.qualidator.com/Web/de/Support/FAQ_OnlineTestStatistiken.htm',
              +				uaCompany: 'seven49.net GmbH',
              +				uaCompanyUrl: 'http://www.seven49.net/',
              +				uaIcon: 'bot_Qualidator.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Qualidator.com Bot'
              +			}
              +		},
              +		'5065': {
              +			userAgent: 'Mozilla/5.0 (compatible; VideoSurf_bot +http://www.videosurf.com/bot.html)',
              +			metadata: {
              +				uaFamily: 'VideoSurf_bot',
              +				uaName: 'VideoSurf_bot',
              +				uaUrl: 'http://www.videosurf.com/bot.html',
              +				uaCompany: 'VideoSurf Inc.',
              +				uaCompanyUrl: 'http://www.videosurf.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=VideoSurf_bot'
              +			}
              +		},
              +		'5066': {
              +			userAgent: 'Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.0.19; aggregator:Spinn3r (Spinn3r 3.1); http://spinn3r.com/robot) Gecko/2010040121 Firefox/3.0.19',
              +			metadata: {
              +				uaFamily: 'Spinn3r',
              +				uaName: 'Spinn3r 3.1',
              +				uaUrl: 'http://spinn3r.com/robot',
              +				uaCompany: 'Tailrank Inc',
              +				uaCompanyUrl: 'http://tailrank.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Spinn3r'
              +			}
              +		},
              +		'5077': {
              +			userAgent: 'Mozilla/5.0 (compatible; AboutUsBot Johnny5/2.0; +http://www.AboutUs.org/)',
              +			metadata: {
              +				uaFamily: 'AboutUsBot',
              +				uaName: 'AboutUsBot Johnny5/2.0',
              +				uaUrl: 'http://www.aboutus.org/AboutUs:Bot',
              +				uaCompany: 'AboutUs, Inc.',
              +				uaCompanyUrl: 'http://www.aboutus.org/AboutUs.org',
              +				uaIcon: 'bot_AboutUsBot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=AboutUsBot'
              +			}
              +		},
              +		'5090': {
              +			userAgent: 'Mozilla/5.0 (compatible; YandexWebmaster/2.0; +http://yandex.com/bots)',
              +			metadata: {
              +				uaFamily: 'YandexBot',
              +				uaName: 'YandexWebmaster/2.0',
              +				uaUrl: 'http://yandex.com/bots',
              +				uaCompany: 'Yandex LLC',
              +				uaCompanyUrl: 'http://company.yandex.com/',
              +				uaIcon: 'bot_Yandex.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=YandexBot'
              +			}
              +		},
              +		'5092': {
              +			userAgent: 'nrsbot/6.0(loopip.com/robot.html)',
              +			metadata: {
              +				uaFamily: 'NetResearchServer',
              +				uaName: 'nrsbot/6.0',
              +				uaUrl: 'http://loopip.com/robot.html',
              +				uaCompany: 'LoopIP LLC',
              +				uaCompanyUrl: 'http://loopip.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=NetResearchServer'
              +			}
              +		},
              +		'5100': {
              +			userAgent: 'Mozilla/5.0 (compatible; Butterfly/1.0; +http://labs.topsy.com/butterfly/) Gecko/2009032608 Firefox/3.0.8',
              +			metadata: {
              +				uaFamily: 'Butterfly',
              +				uaName: 'Butterfly/1.0 a',
              +				uaUrl: 'http://labs.topsy.com/butterfly.html',
              +				uaCompany: 'Topsy Labs',
              +				uaCompanyUrl: 'http://labs.topsy.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Butterfly'
              +			}
              +		},
              +		'5145': {
              +			userAgent: 'StatoolsBot (+http://www.statools.com/bot.html)',
              +			metadata: {
              +				uaFamily: 'StatoolsBot',
              +				uaName: 'StatoolsBot',
              +				uaUrl: 'http://www.statools.com/bot.html',
              +				uaCompany: 'StaTools.com',
              +				uaCompanyUrl: 'http://www.statools.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=StatoolsBot'
              +			}
              +		},
              +		'5165': {
              +			userAgent: 'Mozilla/5.0 (compatible; Hailoobot/1.2; +http://www.hailoo.com/spider.html)',
              +			metadata: {
              +				uaFamily: 'Hailoobot',
              +				uaName: 'Hailoobot/1.2',
              +				uaUrl: 'http://www.hailoo.com/spider.html',
              +				uaCompany: 'Hailoo',
              +				uaCompanyUrl: 'http://www.hailoo.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Hailoobot'
              +			}
              +		},
              +		'5176': {
              +			userAgent: 'yacybot (amd64 Linux 2.6.26-2-amd64; java 1.6.0_20; Europe/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'5180': {
              +			userAgent: 'Lijit Crawler (+http://www.lijit.com/robot/crawler)',
              +			metadata: {
              +				uaFamily: 'Lijit',
              +				uaName: 'Lijit',
              +				uaUrl: 'http://www.lijit.com/robot/crawler',
              +				uaCompany: 'Lijit Networks Inc.',
              +				uaCompanyUrl: 'http://www.lijit.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Lijit'
              +			}
              +		},
              +		'5183': {
              +			userAgent: 'WMCAI-robot (http://www.topicmaster.jp/wmcai/crawler.html)',
              +			metadata: {
              +				uaFamily: 'WMCAI_robot',
              +				uaName: 'WMCAI_robot',
              +				uaUrl: 'http://www.topicmaster.jp/wmcai/crawler.html',
              +				uaCompany: 'NTT Corporation',
              +				uaCompanyUrl: 'http://www.ntt.co.jp/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=WMCAI_robot'
              +			}
              +		},
              +		'5187': {
              +			userAgent: 'eCairn-Grabber/1.0 (+http://ecairn.com/grabber) curl/7.15',
              +			metadata: {
              +				uaFamily: 'eCairn-Grabber',
              +				uaName: 'eCairn-Grabber/1.0',
              +				uaUrl: 'http://ecairn.com/grabber',
              +				uaCompany: 'eCairn Inc.',
              +				uaCompanyUrl: 'http://ecairn.com/',
              +				uaIcon: 'bot_eCairn-Grabber.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=eCairn-Grabber'
              +			}
              +		},
              +		'5188': {
              +			userAgent: 'Stroke.cz (http://stroke.cz)',
              +			metadata: {
              +				uaFamily: 'Strokebot',
              +				uaName: 'Strokebot',
              +				uaUrl: 'http://stroke.cz/oou/',
              +				uaCompany: 'care4u, s. r. o.',
              +				uaCompanyUrl: 'http://care4u.cz/',
              +				uaIcon: 'bot_strokebot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Strokebot'
              +			}
              +		},
              +		'5202': {
              +			userAgent: 'JUST-CRAWLER(+http://www.justsystems.com/jp/tech/crawler/)',
              +			metadata: {
              +				uaFamily: 'JUST-CRAWLER',
              +				uaName: 'JUST-CRAWLER',
              +				uaUrl: 'http://www.justsystems.com/jp/tech/crawler/',
              +				uaCompany: 'JustSystems Corporation',
              +				uaCompanyUrl: 'http://www.justsystems.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=JUST-CRAWLER'
              +			}
              +		},
              +		'5216': {
              +			userAgent: 'yacybot (x86 Windows 2003 5.2; java 1.6.0_20; America/de) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'5218': {
              +			userAgent: 'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0; DomainDB-1.1; http://domaindb.com/crawler/)',
              +			metadata: {
              +				uaFamily: 'DomainDB',
              +				uaName: 'DomainDB/1.1',
              +				uaUrl: 'http://domaindb.com/crawler/',
              +				uaCompany: 'Triop AB',
              +				uaCompanyUrl: 'http://triop.se/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=DomainDB'
              +			}
              +		},
              +		'5228': {
              +			userAgent: 'Ocelli/1.4 (http://www.globalspec.com/Ocelli)',
              +			metadata: {
              +				uaFamily: 'Ocelli',
              +				uaName: 'Ocelli/1.4',
              +				uaUrl: 'http://www.globalspec.com/Ocelli',
              +				uaCompany: 'GlobalSpec, Inc.',
              +				uaCompanyUrl: 'http://www.globalspec.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Ocelli'
              +			}
              +		},
              +		'5231': {
              +			userAgent: 'Mozilla/5.0 (compatible; SSLBot/1.0;  http://www.sslstats.com/sslbot)',
              +			metadata: {
              +				uaFamily: 'SSLBot',
              +				uaName: 'SSLBot/1.0',
              +				uaUrl: 'http://www.sslstats.com/sslbot/',
              +				uaCompany: 'sslstats.com',
              +				uaCompanyUrl: 'http://www.sslstats.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SSLBot'
              +			}
              +		},
              +		'5238': {
              +			userAgent: 'Mozilla/5.0 (compatible; bixolabs/1.0; +http://bixolabs.com/crawler/general; crawler@mail.bixolabs.com)',
              +			metadata: {
              +				uaFamily: 'bixocrawler',
              +				uaName: 'bixolabs/1.0',
              +				uaUrl: 'http://wiki.github.com/bixo/bixo/bixocrawler',
              +				uaCompany: 'Bixo Labs',
              +				uaCompanyUrl: 'http://openbixo.org/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=bixocrawler'
              +			}
              +		},
              +		'5243': {
              +			userAgent: 'findlinks/1.1.6-beta1 (+http://wortschatz.uni-leipzig.de/findlinks/; YaCy 0.1; yacy.net)',
              +			metadata: {
              +				uaFamily: 'findlinks',
              +				uaName: 'findlinks/1.1.6-beta1 Yacy',
              +				uaUrl: 'http://wortschatz.uni-leipzig.de/findlinks/',
              +				uaCompany: 'Universit\xe4t Leipzig',
              +				uaCompanyUrl: 'http://www.uni-leipzig.de/',
              +				uaIcon: 'bot_findlinks.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=findlinks'
              +			}
              +		},
              +		'5249': {
              +			userAgent: 'yacybot (x86 Windows XP 5.1; java 1.6.0_21; Europe/de) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'5272': {
              +			userAgent: 'Mozilla/5.0 (compatible; archive.org_bot +http://www.archive.org/details/archive.org_bot)',
              +			metadata: {
              +				uaFamily: 'archive.org_bot',
              +				uaName: 'archive.org_bot',
              +				uaUrl: 'http://www.archive.org/details/archive.org_bot',
              +				uaCompany: 'Internet Archive',
              +				uaCompanyUrl: 'http://www.archive.org/',
              +				uaIcon: 'bot_heritrix.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=archive.org_bot'
              +			}
              +		},
              +		'5275': {
              +			userAgent: 'Mozilla/4.0 (compatible;  Vagabondo/4.0; http://webagent.wise-guys.nl/)',
              +			metadata: {
              +				uaFamily: 'Vagabondo',
              +				uaName: 'Vagabondo/4.0',
              +				uaUrl: 'http://webagent.wise-guys.nl/',
              +				uaCompany: 'WiseGuys Internet BV',
              +				uaCompanyUrl: 'http://www.wise-guys.nl/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Vagabondo'
              +			}
              +		},
              +		'5276': {
              +			userAgent: 'yacybot (amd64 Linux 2.6.18-164.15.1.el5xen; java 1.6.0_0; Europe/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'5277': {
              +			userAgent: 'findlinks/1.1.6-beta3 (+http://wortschatz.uni-leipzig.de/findlinks/)',
              +			metadata: {
              +				uaFamily: 'findlinks',
              +				uaName: 'findlinks/1.1.6-beta3',
              +				uaUrl: 'http://wortschatz.uni-leipzig.de/findlinks/',
              +				uaCompany: 'Universit\xe4t Leipzig',
              +				uaCompanyUrl: 'http://www.uni-leipzig.de/',
              +				uaIcon: 'bot_findlinks.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=findlinks'
              +			}
              +		},
              +		'5278': {
              +			userAgent: 'yacybot (amd64 Windows 7 6.1; java 1.6.0_18; Europe/de) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'5280': {
              +			userAgent: 'Mozilla/5.0 (compatible; MetamojiCrawler/1.0; +http://www.metamoji.com/jp/crawler.html',
              +			metadata: {
              +				uaFamily: 'MetamojiCrawler',
              +				uaName: 'MetamojiCrawler/1.0',
              +				uaUrl: 'http://www.metamoji.com/jp/crawler.html',
              +				uaCompany: 'MetaMoJi Corporation',
              +				uaCompanyUrl: 'http://www.metamoji.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MetamojiCrawler'
              +			}
              +		},
              +		'5281': {
              +			userAgent: 'yacybot (amd64 Windows 7 6.1; java 1.6.0_21; Europe/fr) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'5292': {
              +			userAgent: 'findlinks/1.1.6-beta4 (+http://wortschatz.uni-leipzig.de/findlinks/)',
              +			metadata: {
              +				uaFamily: 'findlinks',
              +				uaName: 'findlinks/1.1.6-beta4',
              +				uaUrl: 'http://wortschatz.uni-leipzig.de/findlinks/',
              +				uaCompany: 'Universit\xe4t Leipzig',
              +				uaCompanyUrl: 'http://www.uni-leipzig.de/',
              +				uaIcon: 'bot_findlinks.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=findlinks'
              +			}
              +		},
              +		'5302': {
              +			userAgent: 'HuaweiSymantecSpider/1.0+DSE-support@huaweisymantec.com+(compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR ; http://www.huaweisymantec.com/en/IRL/spider)',
              +			metadata: {
              +				uaFamily: 'HuaweiSymantecSpider',
              +				uaName: 'HuaweiSymantecSpider/1.0',
              +				uaUrl: 'http://www.huaweisymantec.com/en/IRL/spider/',
              +				uaCompany: 'Huawei Symantec Technologies Co.,Ltd.',
              +				uaCompanyUrl: 'http://www.huaweisymantec.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=HuaweiSymantecSpider'
              +			}
              +		},
              +		'5311': {
              +			userAgent: 'Mozilla/5.0 (compatible; 008/0.83; http://www.80legs.com/webcrawler.html;) Gecko/2008032620',
              +			metadata: {
              +				uaFamily: '80legs',
              +				uaName: '80legs/0.83 b',
              +				uaUrl: 'http://www.80legs.com/webcrawler.html',
              +				uaCompany: 'Computational Crawling, LP',
              +				uaCompanyUrl: 'http://compucrawl.com/',
              +				uaIcon: 'bot_80legs.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=80legs'
              +			}
              +		},
              +		'5322': {
              +			userAgent: 'yacybot (amd64 Linux 2.6.31-22-server; java 1.6.0_18; Asia/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'5352': {
              +			userAgent: 'findlinks/1.1.6-beta5 (+http://wortschatz.uni-leipzig.de/findlinks/)',
              +			metadata: {
              +				uaFamily: 'findlinks',
              +				uaName: 'findlinks/1.1.6-beta5',
              +				uaUrl: 'http://wortschatz.uni-leipzig.de/findlinks/',
              +				uaCompany: 'Universit\xe4t Leipzig',
              +				uaCompanyUrl: 'http://www.uni-leipzig.de/',
              +				uaIcon: 'bot_findlinks.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=findlinks'
              +			}
              +		},
              +		'5357': {
              +			userAgent: 'Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)',
              +			metadata: {
              +				uaFamily: 'bingbot',
              +				uaName: 'bingbot/2.0',
              +				uaUrl: 'http://www.bing.com/webmaster/help/which-crawlers-does-bing-use-8c184ec0',
              +				uaCompany: 'Microsoft Corporation',
              +				uaCompanyUrl: 'http://www.microsoft.com/',
              +				uaIcon: 'bot_msnbot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=bingbot'
              +			}
              +		},
              +		'5360': {
              +			userAgent: 'PostPost/1.0 (+http://postpo.st/crawlers)',
              +			metadata: {
              +				uaFamily: 'PostPost',
              +				uaName: 'PostPost/1.0',
              +				uaUrl: 'http://postpost.com/crawlers',
              +				uaCompany: 'Boathouse group',
              +				uaCompanyUrl: 'http://www.boathouseinc.com/',
              +				uaIcon: 'bot_PostPost.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=PostPost'
              +			}
              +		},
              +		'5361': {
              +			userAgent: 'WebWatch/Robot_txtChecker',
              +			metadata: {
              +				uaFamily: 'WebWatch/Robot_txtChecker',
              +				uaName: 'WebWatch/Robot_txtChecker',
              +				uaUrl: 'http://www.ukoln.ac.uk/web-focus/webwatch/services/robots-txt/',
              +				uaCompany: 'UKOLN',
              +				uaCompanyUrl: 'http://www.ukoln.ac.uk/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=WebWatch/Robot_txtChecker'
              +			}
              +		},
              +		'5362': {
              +			userAgent: 'Robots_Tester_http_www.searchenginepromotionhelp.com',
              +			metadata: {
              +				uaFamily: 'Robots_Tester',
              +				uaName: 'Robots_Tester',
              +				uaUrl: 'http://www.searchenginepromotionhelp.com/m/robots-text-tester/robots-checker.php',
              +				uaCompany: 'Search Engine Promotion Help',
              +				uaCompanyUrl: 'http://www.searchenginepromotionhelp.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Robots_Tester'
              +			}
              +		},
              +		'5376': {
              +			userAgent: 'Mozilla/5.0 (compatible; Peew/1.0; http://www.peew.de/crawler/)',
              +			metadata: {
              +				uaFamily: 'Peew',
              +				uaName: 'Peew/1.0',
              +				uaUrl: 'http://www.peew.de/crawler/',
              +				uaCompany: 'Marco Schmidt',
              +				uaCompanyUrl: 'http://www.peew.de/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Peew'
              +			}
              +		},
              +		'5380': {
              +			userAgent: 'gonzo/1[P] (+http://www.suchen.de/faq.html)',
              +			metadata: {
              +				uaFamily: 'gonzo',
              +				uaName: 'gonzo/1',
              +				uaUrl: 'http://www.suchen.de/faq.html',
              +				uaCompany: 'SEARCHTEQ',
              +				uaCompanyUrl: 'http://www.searchteq.de/',
              +				uaIcon: 'bot_gonzo.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=gonzo'
              +			}
              +		},
              +		'5386': {
              +			userAgent: 'Mozilla/5.0 (compatible; spbot/2.1; +http://www.seoprofiler.com/bot )',
              +			metadata: {
              +				uaFamily: 'spbot',
              +				uaName: 'spbot/2.1',
              +				uaUrl: 'http://www.seoprofiler.com/bot/',
              +				uaCompany: 'Axandra GmbH',
              +				uaCompanyUrl: 'http://www.axandra.com/',
              +				uaIcon: 'bot_spbot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=spbot'
              +			}
              +		},
              +		'5389': {
              +			userAgent: 'WikioFeedBot 1.0 (http://www.wikio.com)',
              +			metadata: {
              +				uaFamily: 'WikioFeedBot',
              +				uaName: 'WikioFeedBot 1.0',
              +				uaUrl: '',
              +				uaCompany: 'Wikio',
              +				uaCompanyUrl: 'http://www.wikio.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=WikioFeedBot'
              +			}
              +		},
              +		'5611': {
              +			userAgent: 'facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)',
              +			metadata: {
              +				uaFamily: 'FacebookExternalHit',
              +				uaName: 'FacebookExternalHit/1.1',
              +				uaUrl: 'http://www.facebook.com/externalhit_uatext.php',
              +				uaCompany: 'Facebook',
              +				uaCompanyUrl: 'http://www.facebook.com/',
              +				uaIcon: 'bot_facebook.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=FacebookExternalHit'
              +			}
              +		},
              +		'5620': {
              +			userAgent: 'Qirina Hurdler v. 1.05 10.11.01 (+http://www.qirina.com/hurdler.html)',
              +			metadata: {
              +				uaFamily: 'Qirina Hurdler',
              +				uaName: 'Qirina Hurdler v. 1.05 10.11.01',
              +				uaUrl: 'http://www.qirina.com/hurdler.html',
              +				uaCompany: 'Locust Swarm',
              +				uaCompanyUrl: 'http://www.locustswarm.com/',
              +				uaIcon: 'bot_QirinaHurdler.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Qirina Hurdler'
              +			}
              +		},
              +		'5623': {
              +			userAgent: 'Mozilla/5.0 (compatible; AntBot/1.0; +http://www.ant.com/)',
              +			metadata: {
              +				uaFamily: 'AntBot',
              +				uaName: 'AntBot/1.0',
              +				uaUrl: '',
              +				uaCompany: 'Ant.com',
              +				uaCompanyUrl: 'http://www.ant.com/',
              +				uaIcon: 'bot_AntBot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=AntBot'
              +			}
              +		},
              +		'5635': {
              +			userAgent: 'WatchMouse/18990 (http://watchmouse.com/ ; d2.watchmouse.com)',
              +			metadata: {
              +				uaFamily: 'WatchMouse',
              +				uaName: 'WatchMouse/18990 d2.watchmouse.com',
              +				uaUrl: 'http://www.watchmouse.com/',
              +				uaCompany: 'WatchMouse',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_WatchMouse.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=WatchMouse'
              +			}
              +		},
              +		'5636': {
              +			userAgent: 'WatchMouse/18990 (http://watchmouse.com/ ; liz)',
              +			metadata: {
              +				uaFamily: 'WatchMouse',
              +				uaName: 'WatchMouse/18990 liz',
              +				uaUrl: 'http://www.watchmouse.com/',
              +				uaCompany: 'WatchMouse',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_WatchMouse.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=WatchMouse'
              +			}
              +		},
              +		'5637': {
              +			userAgent: 'WatchMouse/18990 (http://watchmouse.com/ ; d3.watchmouse.com)',
              +			metadata: {
              +				uaFamily: 'WatchMouse',
              +				uaName: 'WatchMouse/18990 d3.watchmouse.com',
              +				uaUrl: 'http://www.watchmouse.com/',
              +				uaCompany: 'WatchMouse',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_WatchMouse.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=WatchMouse'
              +			}
              +		},
              +		'5638': {
              +			userAgent: 'WatchMouse/18990 (http://watchmouse.com/ ; gab)',
              +			metadata: {
              +				uaFamily: 'WatchMouse',
              +				uaName: 'WatchMouse/18990 gab',
              +				uaUrl: 'http://www.watchmouse.com/',
              +				uaCompany: 'WatchMouse',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_WatchMouse.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=WatchMouse'
              +			}
              +		},
              +		'5639': {
              +			userAgent: 'WatchMouse/18990 (http://watchmouse.com/ ; ny)',
              +			metadata: {
              +				uaFamily: 'WatchMouse',
              +				uaName: 'WatchMouse/18990 ny',
              +				uaUrl: 'http://www.watchmouse.com/',
              +				uaCompany: 'WatchMouse',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_WatchMouse.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=WatchMouse'
              +			}
              +		},
              +		'5640': {
              +			userAgent: 'WatchMouse/18990 (http://watchmouse.com/ ; se.watchmouse.com)',
              +			metadata: {
              +				uaFamily: 'WatchMouse',
              +				uaName: 'WatchMouse/18990 se.watchmouse.com',
              +				uaUrl: 'http://www.watchmouse.com/',
              +				uaCompany: 'WatchMouse',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_WatchMouse.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=WatchMouse'
              +			}
              +		},
              +		'5641': {
              +			userAgent: 'WatchMouse/18990 (http://watchmouse.com/ ; it)',
              +			metadata: {
              +				uaFamily: 'WatchMouse',
              +				uaName: 'WatchMouse/18990 it',
              +				uaUrl: 'http://www.watchmouse.com/',
              +				uaCompany: 'WatchMouse',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_WatchMouse.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=WatchMouse'
              +			}
              +		},
              +		'5642': {
              +			userAgent: 'WatchMouse/18990 (http://watchmouse.com/ ; hk)',
              +			metadata: {
              +				uaFamily: 'WatchMouse',
              +				uaName: 'WatchMouse/18990 hk',
              +				uaUrl: 'http://www.watchmouse.com/',
              +				uaCompany: 'WatchMouse',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_WatchMouse.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=WatchMouse'
              +			}
              +		},
              +		'5643': {
              +			userAgent: 'WatchMouse/18990 (http://watchmouse.com/ ; bc.watchmouse.com)',
              +			metadata: {
              +				uaFamily: 'WatchMouse',
              +				uaName: 'WatchMouse/18990 bc',
              +				uaUrl: 'http://www.watchmouse.com/',
              +				uaCompany: 'WatchMouse',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_WatchMouse.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=WatchMouse'
              +			}
              +		},
              +		'5644': {
              +			userAgent: 'WatchMouse/18990 (http://watchmouse.com/ ; uk)',
              +			metadata: {
              +				uaFamily: 'WatchMouse',
              +				uaName: 'WatchMouse/18990 uk',
              +				uaUrl: 'http://www.watchmouse.com/',
              +				uaCompany: 'WatchMouse',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_WatchMouse.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=WatchMouse'
              +			}
              +		},
              +		'5646': {
              +			userAgent: 'findlinks/2.0 (+http://wortschatz.uni-leipzig.de/findlinks/)',
              +			metadata: {
              +				uaFamily: 'findlinks',
              +				uaName: 'findlinks/2.0',
              +				uaUrl: 'http://wortschatz.uni-leipzig.de/findlinks/',
              +				uaCompany: 'Universit\xe4t Leipzig',
              +				uaCompanyUrl: 'http://www.uni-leipzig.de/',
              +				uaIcon: 'bot_findlinks.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=findlinks'
              +			}
              +		},
              +		'5655': {
              +			userAgent: 'Zookabot/2.1;++http://zookabot.com',
              +			metadata: {
              +				uaFamily: 'ZookaBot',
              +				uaName: 'ZookaBot/2.1',
              +				uaUrl: 'http://zookabot.com/',
              +				uaCompany: 'Hwacha ApS',
              +				uaCompanyUrl: 'http://hwacha.dk/',
              +				uaIcon: 'bot_Zookabot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ZookaBot'
              +			}
              +		},
              +		'5665': {
              +			userAgent: 'CatchBot/3.0; +http://www.catchbot.com',
              +			metadata: {
              +				uaFamily: 'CatchBot',
              +				uaName: 'CatchBot/3.0',
              +				uaUrl: 'http://www.catchbot.com/',
              +				uaCompany: 'Reed Business Information Pty Limited',
              +				uaCompanyUrl: 'http://www.reedbusiness.com/',
              +				uaIcon: 'bot_CatchBot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=CatchBot'
              +			}
              +		},
              +		'5683': {
              +			userAgent: 'Mozilla/5.0 (compatible; MojeekBot/0.2; http://www.mojeek.com/bot.html#relaunch)',
              +			metadata: {
              +				uaFamily: 'MojeekBot',
              +				uaName: 'MojeekBot/0.2 Relaunch',
              +				uaUrl: 'http://www.mojeek.com/bot.html',
              +				uaCompany: 'Mojeek Ltd.',
              +				uaCompanyUrl: 'http://www.mojeek.com/',
              +				uaIcon: 'bot_MojeekBot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MojeekBot'
              +			}
              +		},
              +		'5685': {
              +			userAgent: 'findlinks/1.1.6-beta6 (+http://wortschatz.uni-leipzig.de/findlinks/)',
              +			metadata: {
              +				uaFamily: 'findlinks',
              +				uaName: 'findlinks/1.1.6-beta6',
              +				uaUrl: 'http://wortschatz.uni-leipzig.de/findlinks/',
              +				uaCompany: 'Universit\xe4t Leipzig',
              +				uaCompanyUrl: 'http://www.uni-leipzig.de/',
              +				uaIcon: 'bot_findlinks.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=findlinks'
              +			}
              +		},
              +		'5701': {
              +			userAgent: 'WebAlta Crawler/1.3.25 (http://www.webalta.net/ru/about_webmaster.html) (Windows; U; Windows NT 5.1; ru-RU)',
              +			metadata: {
              +				uaFamily: 'WebAlta Crawler',
              +				uaName: 'WebAlta Crawler/1.3.25',
              +				uaUrl: 'http://www.webalta.net/ru/about_webmaster.html',
              +				uaCompany: 'Webalta',
              +				uaCompanyUrl: 'http://www.webalta.ru/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=WebAlta Crawler'
              +			}
              +		},
              +		'5710': {
              +			userAgent: 'wikiwix-bot-3.0',
              +			metadata: {
              +				uaFamily: 'wikiwix-bot',
              +				uaName: 'wikiwix-bot/3.0',
              +				uaUrl: '',
              +				uaCompany: 'wikiwix.com',
              +				uaCompanyUrl: 'http://www.wikiwix.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=wikiwix-bot'
              +			}
              +		},
              +		'5715': {
              +			userAgent: 'findlinks/2.0.1 (+http://wortschatz.uni-leipzig.de/findlinks/)',
              +			metadata: {
              +				uaFamily: 'findlinks',
              +				uaName: 'findlinks/2.0.1',
              +				uaUrl: 'http://wortschatz.uni-leipzig.de/findlinks/',
              +				uaCompany: 'Universit\xe4t Leipzig',
              +				uaCompanyUrl: 'http://www.uni-leipzig.de/',
              +				uaIcon: 'bot_findlinks.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=findlinks'
              +			}
              +		},
              +		'5718': {
              +			userAgent: 'yrspider (Mozilla/5.0 (compatible; YRSpider; +http://www.yunrang.com/yrspider.html))',
              +			metadata: {
              +				uaFamily: 'YRSpider',
              +				uaName: 'YRSpider',
              +				uaUrl: 'http://www.yunrang.com/yrspider.html',
              +				uaCompany: 'yunrang',
              +				uaCompanyUrl: 'http://www.yunrang.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=YRSpider'
              +			}
              +		},
              +		'5727': {
              +			userAgent: 'Mozilla/5.0 (compatible; Urlfilebot/2.2; +http://urlfile.com/bot.html)',
              +			metadata: {
              +				uaFamily: 'Urlfilebot (Urlbot)',
              +				uaName: 'Urlfilebot/2.2',
              +				uaUrl: 'http://urlfile.com/bot.html',
              +				uaCompany: 'Urlfile',
              +				uaCompanyUrl: 'http://urlfile.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Urlfilebot (Urlbot)'
              +			}
              +		},
              +		'5748': {
              +			userAgent: 'Mozilla/5.0 (compatible; spbot/3.0; +http://www.seoprofiler.com/bot )',
              +			metadata: {
              +				uaFamily: 'spbot',
              +				uaName: 'spbot/3.0',
              +				uaUrl: 'http://www.seoprofiler.com/bot/',
              +				uaCompany: 'Axandra GmbH',
              +				uaCompanyUrl: 'http://www.axandra.com/',
              +				uaIcon: 'bot_spbot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=spbot'
              +			}
              +		},
              +		'5802': {
              +			userAgent: 'Mozilla/5.0 (compatible; suggybot v0.01a, http://blog.suggy.com/was-ist-suggy/suggy-webcrawler/)',
              +			metadata: {
              +				uaFamily: 'suggybot',
              +				uaName: 'suggybot/0.01a',
              +				uaUrl: 'http://blog.suggy.com/was-ist-suggy/suggy-webcrawler/',
              +				uaCompany: 'Suggy GbR',
              +				uaCompanyUrl: 'http://www.suggy.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=suggybot'
              +			}
              +		},
              +		'5806': {
              +			userAgent: 'EuripBot/1.1 (+http://www.eurip.com) GetRobots',
              +			metadata: {
              +				uaFamily: 'EuripBot',
              +				uaName: 'EuripBot/1.1',
              +				uaUrl: 'http://www.eurip.com/service/webmaster/euripbot.html',
              +				uaCompany: 'EURIP - European Internet Portal',
              +				uaCompanyUrl: 'http://www.eurip.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=EuripBot'
              +			}
              +		},
              +		'5818': {
              +			userAgent: 'Mozilla/5.0 (compatible; Ezooms/1.0; ezooms.bot@gmail.com)',
              +			metadata: {
              +				uaFamily: 'Ezooms',
              +				uaName: 'Ezooms/1.0',
              +				uaUrl: '',
              +				uaCompany: 'dotnetdotcom.org',
              +				uaCompanyUrl: 'http://www.dotnetdotcom.org/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Ezooms'
              +			}
              +		},
              +		'5828': {
              +			userAgent: 'thumbshots-de-bot (+http://www.thumbshots.de/)',
              +			metadata: {
              +				uaFamily: 'thumbshots-de-Bot',
              +				uaName: 'thumbshots-de-bot',
              +				uaUrl: 'http://www.thumbshots.de/content-39-seite_auszuschliessen.html',
              +				uaCompany: 'Mobile & More Mobilkommunikation GmbH',
              +				uaCompanyUrl: 'http://www.mobile-more.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=thumbshots-de-Bot'
              +			}
              +		},
              +		'5839': {
              +			userAgent: 'TwengaBot',
              +			metadata: {
              +				uaFamily: 'TwengaBot',
              +				uaName: 'TwengaBot',
              +				uaUrl: 'http://www.twenga.com/bot.html',
              +				uaCompany: 'Twenga SA',
              +				uaCompanyUrl: 'http://www.twenga.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=TwengaBot'
              +			}
              +		},
              +		'5843': {
              +			userAgent: 'findlinks/2.0.2 (+http://wortschatz.uni-leipzig.de/findlinks/)',
              +			metadata: {
              +				uaFamily: 'findlinks',
              +				uaName: 'findlinks/2.0.2',
              +				uaUrl: 'http://wortschatz.uni-leipzig.de/findlinks/',
              +				uaCompany: 'Universit\xe4t Leipzig',
              +				uaCompanyUrl: 'http://www.uni-leipzig.de/',
              +				uaIcon: 'bot_findlinks.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=findlinks'
              +			}
              +		},
              +		'5846': {
              +			userAgent: 'Mozilla/5.0 (compatible; YandexMedia/3.0; +http://yandex.com/bots)',
              +			metadata: {
              +				uaFamily: 'YandexBot',
              +				uaName: 'Mozilla/5.0 (compatible; YandexMedia/3.0',
              +				uaUrl: 'http://yandex.com/bots',
              +				uaCompany: 'Yandex LLC',
              +				uaCompanyUrl: 'http://company.yandex.com/',
              +				uaIcon: 'bot_Yandex.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=YandexBot'
              +			}
              +		},
              +		'5857': {
              +			userAgent: 'SeznamBot/3.0-beta (+http://fulltext.sblog.cz/)',
              +			metadata: {
              +				uaFamily: 'SeznamBot',
              +				uaName: 'SeznamBot/3.0-beta',
              +				uaUrl: 'http://napoveda.seznam.cz/en/indexing-the-web.html',
              +				uaCompany: 'Seznam.cz, a.s.',
              +				uaCompanyUrl: 'http://www.seznam.cz/',
              +				uaIcon: 'seznam.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SeznamBot'
              +			}
              +		},
              +		'5859': {
              +			userAgent: 'OpenCalaisSemanticProxy',
              +			metadata: {
              +				uaFamily: 'OpenCalaisSemanticProxy',
              +				uaName: 'OpenCalaisSemanticProxy',
              +				uaUrl: 'http://www.opencalais.com/open-calais-semanticproxy-robot-agent-name',
              +				uaCompany: 'Thomson Reuters',
              +				uaCompanyUrl: 'http://thomsonreuters.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=OpenCalaisSemanticProxy'
              +			}
              +		},
              +		'5860': {
              +			userAgent: 'Covario-IDS/1.0 (Covario; http://www.covario.com/ids; support at covario dot com)',
              +			metadata: {
              +				uaFamily: 'Covario-IDS',
              +				uaName: 'Covario-IDS/1.0',
              +				uaUrl: 'http://www.covario.com/ids',
              +				uaCompany: 'Covario Inc.',
              +				uaCompanyUrl: 'http://www.covario.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Covario-IDS'
              +			}
              +		},
              +		'5862': {
              +			userAgent: 'Mozilla/5.0 (X11; U; Linux i686; de; rv:1.9.0.1; compatible; iCjobs Stellenangebote Jobs; http://www.icjobs.de) Gecko/20100401 iCjobs/3.2.3',
              +			metadata: {
              +				uaFamily: 'iCjobs',
              +				uaName: 'iCjobs/3.2.3',
              +				uaUrl: 'http://www.icjobs.de/bot.htm',
              +				uaCompany: 'Intelligence Competence Center AG',
              +				uaCompanyUrl: 'http://www.iccenter.net/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=iCjobs'
              +			}
              +		},
              +		'5902': {
              +			userAgent: 'ichiro/5.0 (http://help.goo.ne.jp/door/crawler.html)',
              +			metadata: {
              +				uaFamily: 'ichiro',
              +				uaName: 'ichiro/5.0',
              +				uaUrl: 'http://search.goo.ne.jp/option/use/sub4/sub4-1/',
              +				uaCompany: 'NTT-Resonant Inc.',
              +				uaCompanyUrl: 'http://www.nttr.co.jp/',
              +				uaIcon: 'bot_ichiro.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ichiro'
              +			}
              +		},
              +		'5909': {
              +			userAgent: 'Mozilla/5.0 (compatible; CligooRobot/2.0; +http://www.cligoo.de/wk/technik.php)',
              +			metadata: {
              +				uaFamily: 'CligooRobot',
              +				uaName: 'CligooRobot/2.0',
              +				uaUrl: 'http://www.cligoo.de/wk/technik.php',
              +				uaCompany: 'cligoo medien service UG',
              +				uaCompanyUrl: 'http://www.cligoo.de/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=CligooRobot'
              +			}
              +		},
              +		'5939': {
              +			userAgent: 'nWormFeedFinder (http://www.nworm.com)',
              +			metadata: {
              +				uaFamily: 'nworm',
              +				uaName: 'nwormFeedFinder',
              +				uaUrl: 'http://www.nworm.com/crawlers.php',
              +				uaCompany: 'Daniel Schlicker (mangora IT)',
              +				uaCompanyUrl: 'http://www.mangora.de/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=nworm'
              +			}
              +		},
              +		'5960': {
              +			userAgent: 'MetaGeneratorCrawler/1.1 (www.metagenerator.info)',
              +			metadata: {
              +				uaFamily: 'MetaGeneratorCrawler',
              +				uaName: 'MetaGeneratorCrawler/1.1',
              +				uaUrl: 'http://www.metagenerator.info/',
              +				uaCompany: 'Jan Bogutzki',
              +				uaCompanyUrl: 'http://jan.bogutzki.de/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MetaGeneratorCrawler'
              +			}
              +		},
              +		'5982': {
              +			userAgent: 'Y!J-BRO/YFSJ crawler (compatible; Mozilla 4.0; MSIE 5.5; http://help.yahoo.co.jp/help/jp/search/indexing/indexing-15.html; YahooFeedSeekerJp/2.0)',
              +			metadata: {
              +				uaFamily: 'Yahoo! JAPAN',
              +				uaName: 'Y!J-BRO/YFSJ',
              +				uaUrl: 'http://help.yahoo.co.jp/help/jp/search/indexing/indexing-15.html',
              +				uaCompany: 'Yahoo! Inc',
              +				uaCompanyUrl: 'http://www.yahoo.com/',
              +				uaIcon: 'bot_yahoo!slurp.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Yahoo! JAPAN'
              +			}
              +		},
              +		'5987': {
              +			userAgent: 'Mozilla/5.0 (compatible; oBot/2.3.1; +http://www-935.ibm.com/services/us/index.wss/detail/iss/a1029077?cntxt=a1027244)',
              +			metadata: {
              +				uaFamily: 'oBot',
              +				uaName: 'oBot/2.3.1 b',
              +				uaUrl: 'http://filterdb.iss.net/crawler/',
              +				uaCompany: 'IBM Germany Research & Development GmbH',
              +				uaCompanyUrl: 'http://www.ibm.com/ibm/de/de/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=oBot'
              +			}
              +		},
              +		'5999': {
              +			userAgent: 'SEOENGBot/1.2 (+http://learn.seoengine.com/seoengbot.htm)',
              +			metadata: {
              +				uaFamily: 'SEOENGBot',
              +				uaName: 'SEOENGBot/1.2',
              +				uaUrl: 'http://www.seoengine.com/seoengbot.htm',
              +				uaCompany: 'SEO Engine',
              +				uaCompanyUrl: 'http://www.seoengine.com/',
              +				uaIcon: 'bot_SEOENGBot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SEOENGBot'
              +			}
              +		},
              +		'6001': {
              +			userAgent: 'Zookabot/2.2;++http://zookabot.com',
              +			metadata: {
              +				uaFamily: 'Zookabot',
              +				uaName: 'Zookabot/2.2',
              +				uaUrl: 'http://zookabot.com/',
              +				uaCompany: 'Hwacha ApS',
              +				uaCompanyUrl: 'http://hwacha.dk/',
              +				uaIcon: 'bot_Zookabot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Zookabot'
              +			}
              +		},
              +		'6010': {
              +			userAgent: 'msnbot-NewsBlogs/2.0b (+http://search.msn.com/msnbot.htm)',
              +			metadata: {
              +				uaFamily: 'MSNBot',
              +				uaName: 'msnbot-NewsBlogs/2.0b',
              +				uaUrl: 'http://search.msn.com/msnbot.htm',
              +				uaCompany: 'Microsoft Corporation',
              +				uaCompanyUrl: 'http://www.microsoft.com/',
              +				uaIcon: 'bot_msnbot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MSNBot'
              +			}
              +		},
              +		'6011': {
              +			userAgent: 'findlinks/2.0.4 (+http://wortschatz.uni-leipzig.de/findlinks/)',
              +			metadata: {
              +				uaFamily: 'findlinks',
              +				uaName: 'findlinks/2.0.4',
              +				uaUrl: 'http://wortschatz.uni-leipzig.de/findlinks/',
              +				uaCompany: 'Universit\xe4t Leipzig',
              +				uaCompanyUrl: 'http://www.uni-leipzig.de/',
              +				uaIcon: 'bot_findlinks.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=findlinks'
              +			}
              +		},
              +		'6024': {
              +			userAgent: 'quickobot/quickobot-1 (Quicko Labs; http://quicko.co; robot at quicko dot co)',
              +			metadata: {
              +				uaFamily: 'quickobot',
              +				uaName: 'quickobot-1',
              +				uaUrl: 'http://www.searchenabler.com/quickobot/',
              +				uaCompany: 'Quicko Labs Pvt Ltd. ',
              +				uaCompanyUrl: 'http://www.searchenabler.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=quickobot'
              +			}
              +		},
              +		'6038': {
              +			userAgent: 'SeznamBot/3.0-beta (+http://fulltext.sblog.cz/), I',
              +			metadata: {
              +				uaFamily: 'SeznamBot',
              +				uaName: 'SeznamBot/3.0-beta',
              +				uaUrl: 'http://napoveda.seznam.cz/en/indexing-the-web.html',
              +				uaCompany: 'Seznam.cz, a.s.',
              +				uaCompanyUrl: 'http://www.seznam.cz/',
              +				uaIcon: 'seznam.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SeznamBot'
              +			}
              +		},
              +		'6040': {
              +			userAgent: 'Mozilla/5.0 (compatible; SEODat/0.1 http://crawler.seodat.com)',
              +			metadata: {
              +				uaFamily: 'SEODat',
              +				uaName: 'SEODat/0.1',
              +				uaUrl: '',
              +				uaCompany: 'SEODAT',
              +				uaCompanyUrl: 'http://www.seodat.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SEODat'
              +			}
              +		},
              +		'6044': {
              +			userAgent: 'linkdex.com/v2.0',
              +			metadata: {
              +				uaFamily: 'linkdex.com',
              +				uaName: 'linkdex.com/v2.0',
              +				uaUrl: '',
              +				uaCompany: 'Linkdex Limited',
              +				uaCompanyUrl: 'http://www.linkdex.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=linkdex.com'
              +			}
              +		},
              +		'6065': {
              +			userAgent: 'UnwindFetchor/1.0 (+http://www.gnip.com/)',
              +			metadata: {
              +				uaFamily: 'UnwindFetchor',
              +				uaName: 'UnwindFetchor/1.0',
              +				uaUrl: '',
              +				uaCompany: 'Gnip, inc.',
              +				uaCompanyUrl: 'http://gnip.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=UnwindFetchor'
              +			}
              +		},
              +		'6068': {
              +			userAgent: 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6 (FlipboardProxy/0.0.5; +http://flipboard.com/browserproxy)',
              +			metadata: {
              +				uaFamily: 'FlipboardProxy',
              +				uaName: 'FlipboardProxy/0.0.5',
              +				uaUrl: 'http://flipboard.com/browserproxy',
              +				uaCompany: 'Flipboard, Inc.',
              +				uaCompanyUrl: 'http://flipboard.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=FlipboardProxy'
              +			}
              +		},
              +		'6109': {
              +			userAgent: 'Sitedomain-Bot(Sitedomain-Bot 1.0, http://www.sitedomain.de/sitedomain-bot/)',
              +			metadata: {
              +				uaFamily: 'Sitedomain-Bot',
              +				uaName: 'Sitedomain-Bot 1.0',
              +				uaUrl: 'http://www.sitedomain.de/sitedomain-bot/',
              +				uaCompany: 'Sitedomain.de',
              +				uaCompanyUrl: 'http://www.sitedomain.de/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Sitedomain-Bot'
              +			}
              +		},
              +		'6114': {
              +			userAgent: 'Nuhk/2.4 (+http://www.neti.ee/cgi-bin/abi/otsing.html)',
              +			metadata: {
              +				uaFamily: 'Nuhk',
              +				uaName: 'Nuhk/2.4 b',
              +				uaUrl: 'http://www.neti.ee/cgi-bin/abi/Otsing/Nuhk/',
              +				uaCompany: 'Elion',
              +				uaCompanyUrl: 'http://www.neti.ee/',
              +				uaIcon: 'bot_Nuhk.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Nuhk'
              +			}
              +		},
              +		'6134': {
              +			userAgent: 'Mail.RU/2.0',
              +			metadata: {
              +				uaFamily: 'Mail.Ru bot',
              +				uaName: 'Mail.RU/2.0',
              +				uaUrl: 'http://go.mail.ru/help/robots',
              +				uaCompany: 'Mail.Ru Group',
              +				uaCompanyUrl: 'http://corp.mail.ru/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Mail.Ru bot'
              +			}
              +		},
              +		'6146': {
              +			userAgent: 'Mozilla/5.0 (Windows; U; Windows NT 6.0; en-GB; rv:1.0; trendictionbot0.4.2; trendiction media ssppiiddeerr; http://www.trendiction.com/bot/; please let us know of any problems; ssppiiddeerr at trendiction.com) Gecko/20071127 Firefox/2.0.0.11',
              +			metadata: {
              +				uaFamily: 'trendictionbot',
              +				uaName: 'trendictionbot0.4.2',
              +				uaUrl: 'http://www.trendiction.de/bot',
              +				uaCompany: 'Trendiction S.A.',
              +				uaCompanyUrl: 'http://www.trendiction.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=trendictionbot'
              +			}
              +		},
              +		'6177': {
              +			userAgent: 'findlinks/1.1.3-beta9 (+http://wortschatz.uni-leipzig.de/findlinks/)',
              +			metadata: {
              +				uaFamily: 'findlinks',
              +				uaName: 'findlinks/1.1.3-beta9',
              +				uaUrl: 'http://wortschatz.uni-leipzig.de/findlinks/',
              +				uaCompany: 'Universit\xe4t Leipzig',
              +				uaCompanyUrl: 'http://www.uni-leipzig.de/',
              +				uaIcon: 'bot_findlinks.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=findlinks'
              +			}
              +		},
              +		'6189': {
              +			userAgent: 'SeznamBot/3.0 (+http://fulltext.sblog.cz/)',
              +			metadata: {
              +				uaFamily: 'SeznamBot',
              +				uaName: 'SeznamBot/3.0',
              +				uaUrl: 'http://napoveda.seznam.cz/en/indexing-the-web.html',
              +				uaCompany: 'Seznam.cz, a.s.',
              +				uaCompanyUrl: 'http://www.seznam.cz/',
              +				uaIcon: 'seznam.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SeznamBot'
              +			}
              +		},
              +		'6192': {
              +			userAgent: 'SeznamBot/3.0-test (+http://fulltext.sblog.cz/)',
              +			metadata: {
              +				uaFamily: 'SeznamBot',
              +				uaName: 'SeznamBot/3.0-test',
              +				uaUrl: 'http://napoveda.seznam.cz/en/indexing-the-web.html',
              +				uaCompany: 'Seznam.cz, a.s.',
              +				uaCompanyUrl: 'http://www.seznam.cz/',
              +				uaIcon: 'seznam.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SeznamBot'
              +			}
              +		},
              +		'6202': {
              +			userAgent: 'FlightDeckReportsBot/2.0 (http://www.flightdeckreports.com/pages/bot)',
              +			metadata: {
              +				uaFamily: 'FlightDeckReportsBot',
              +				uaName: 'FlightDeckReportsBot/2.0',
              +				uaUrl: 'http://www.flightdeckreports.com/pages/bot',
              +				uaCompany: 'Flight Deck Reports, LLC.',
              +				uaCompanyUrl: 'http://www.flightdeckreports.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=FlightDeckReportsBot'
              +			}
              +		},
              +		'6214': {
              +			userAgent: 'SeznamBot/3.0-test (+http://fulltext.sblog.cz/), I',
              +			metadata: {
              +				uaFamily: 'SeznamBot',
              +				uaName: 'SeznamBot/3.0-test',
              +				uaUrl: 'http://napoveda.seznam.cz/en/indexing-the-web.html',
              +				uaCompany: 'Seznam.cz, a.s.',
              +				uaCompanyUrl: 'http://www.seznam.cz/',
              +				uaIcon: 'seznam.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SeznamBot'
              +			}
              +		},
              +		'6225': {
              +			userAgent: 'Mozilla/5.0 (compatible; NetcraftSurveyAgent/1.0; +info@netcraft.com)',
              +			metadata: {
              +				uaFamily: 'NetcraftSurveyAgent',
              +				uaName: 'NetcraftSurveyAgent/1.0',
              +				uaUrl: '',
              +				uaCompany: 'Netcraft Ltd',
              +				uaCompanyUrl: 'http://www.netcraft.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=NetcraftSurveyAgent'
              +			}
              +		},
              +		'6226': {
              +			userAgent: 'GarlikCrawler/1.1 (http://garlik.com/, crawler@garik.com)',
              +			metadata: {
              +				uaFamily: 'GarlikCrawler',
              +				uaName: 'GarlikCrawler/1.1',
              +				uaUrl: '',
              +				uaCompany: 'Garlik Limited',
              +				uaCompanyUrl: 'http://www.garlik.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=GarlikCrawler'
              +			}
              +		},
              +		'6229': {
              +			userAgent: 'Setooz/Nutch-1.0 (http://www.setooz.com)',
              +			metadata: {
              +				uaFamily: 'Setoozbot',
              +				uaName: 'Setoozbot/1.0',
              +				uaUrl: 'http://www.setooz.com/oozbot.html',
              +				uaCompany: 'SETU Software Systems (P) Ltd.',
              +				uaCompanyUrl: 'http://www.setusoftware.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Setoozbot'
              +			}
              +		},
              +		'6231': {
              +			userAgent: 'BacklinkCrawler (http://www.backlinktest.com/crawler.html)',
              +			metadata: {
              +				uaFamily: 'BacklinkCrawler',
              +				uaName: 'BacklinkCrawler',
              +				uaUrl: 'http://www.backlinktest.com/crawler.html',
              +				uaCompany: '2.0Promotion GbR',
              +				uaCompanyUrl: 'http://2.0promotion.de/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=BacklinkCrawler'
              +			}
              +		},
              +		'6234': {
              +			userAgent: 'OpenWebSpider v0.1.2.B (http://www.openwebspider.org/)',
              +			metadata: {
              +				uaFamily: 'OpenWebSpider',
              +				uaName: 'OpenWebSpider v0.1.2.B',
              +				uaUrl: 'http://www.openwebspider.org/',
              +				uaCompany: 'Stefano Alimonti',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=OpenWebSpider'
              +			}
              +		},
              +		'6237': {
              +			userAgent: 'http://arachnode.net 2.5',
              +			metadata: {
              +				uaFamily: 'arachnode.net',
              +				uaName: 'arachnode.net/2.5',
              +				uaUrl: 'http://arachnode.codeplex.com/',
              +				uaCompany: 'arachnode.net, llc',
              +				uaCompanyUrl: 'http://arachnode.net/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=arachnode.net'
              +			}
              +		},
              +		'6243': {
              +			userAgent: 'Mozilla/5.0 (compatible; Evrinid Iudex 1.0.0; +http://www.evri.com/evrinid)',
              +			metadata: {
              +				uaFamily: 'EvriNid',
              +				uaName: 'EvriNid/1.0.0',
              +				uaUrl: 'http://corporate.evri.com/about-us/evrinid/',
              +				uaCompany: 'Evri Inc.',
              +				uaCompanyUrl: 'http://corporate.evri.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=EvriNid'
              +			}
              +		},
              +		'6244': {
              +			userAgent: 'Mozilla/5.0 (compatible; discobot/1.0; +http://discoveryengine.com/discobot.html)',
              +			metadata: {
              +				uaFamily: 'discoverybot',
              +				uaName: 'discobot/1.0',
              +				uaUrl: 'http://discoveryengine.com/discoverybot.html',
              +				uaCompany: 'discoveryengine.com. ',
              +				uaCompanyUrl: 'http://www.discoveryengine.com/',
              +				uaIcon: 'bot_discobot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=discoverybot'
              +			}
              +		},
              +		'6245': {
              +			userAgent: 'Nymesis/2.0 (http://nymesis.com)',
              +			metadata: {
              +				uaFamily: 'Nymesis',
              +				uaName: 'Nymesis/2.0',
              +				uaUrl: 'http://www.nymesis.com/about/',
              +				uaCompany: 'nymesis.com',
              +				uaCompanyUrl: 'http://www.nymesis.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Nymesis'
              +			}
              +		},
              +		'6246': {
              +			userAgent: 'Abrave Spider v4 Robot 1 (http://robot.abrave.co.uk)',
              +			metadata: {
              +				uaFamily: 'Abrave Spider',
              +				uaName: 'Abrave Spider/4-1',
              +				uaUrl: 'http://robot.abrave.co.uk/',
              +				uaCompany: 'Gallent Limited',
              +				uaCompanyUrl: 'http://www.gallent.co.uk/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Abrave Spider'
              +			}
              +		},
              +		'6247': {
              +			userAgent: 'Abrave Spider v4 Robot 2 (http://robot.abrave.co.uk)',
              +			metadata: {
              +				uaFamily: 'Abrave Spider',
              +				uaName: 'Abrave Spider/4-2',
              +				uaUrl: 'http://robot.abrave.co.uk/',
              +				uaCompany: 'Gallent Limited',
              +				uaCompanyUrl: 'http://www.gallent.co.uk/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Abrave Spider'
              +			}
              +		},
              +		'6252': {
              +			userAgent: 'RankurBot/Rankur2.1 (http://rankur.com; info at rankur dot com)',
              +			metadata: {
              +				uaFamily: 'RankurBot',
              +				uaName: 'RankurBot/2.1',
              +				uaUrl: 'http://rankur.com/technology.html',
              +				uaCompany: 'Advance Solutions EU Ltd.',
              +				uaCompanyUrl: 'http://www.advancesolutions.eu/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=RankurBot'
              +			}
              +		},
              +		'6270': {
              +			userAgent: 'Mozilla/5.0 (compatible; MJ12bot/v1.4.0; http://www.majestic12.co.uk/bot.php?+)',
              +			metadata: {
              +				uaFamily: 'MJ12bot',
              +				uaName: 'MJ12bot/v1.4.0',
              +				uaUrl: 'http://majestic12.co.uk/bot.php',
              +				uaCompany: 'Majestic-12',
              +				uaCompanyUrl: 'http://www.majestic12.co.uk/',
              +				uaIcon: 'bot_mj12bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MJ12bot'
              +			}
              +		},
              +		'6280': {
              +			userAgent: 'crawler4j (http://code.google.com/p/crawler4j/)',
              +			metadata: {
              +				uaFamily: 'Crawler4j',
              +				uaName: 'Crawler4j',
              +				uaUrl: 'http://code.google.com/p/crawler4j/',
              +				uaCompany: 'Yasser Ganjisaffar',
              +				uaCompanyUrl: 'http://www.ics.uci.edu/~yganjisa/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Crawler4j'
              +			}
              +		},
              +		'6288': {
              +			userAgent: 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) Speedy Spider for SpeedyAds (http://www.entireweb.com/about/search_tech/speedy_spider/)',
              +			metadata: {
              +				uaFamily: 'Speedy',
              +				uaName: 'Speedy Spider',
              +				uaUrl: '',
              +				uaCompany: 'Entireweb Sweden AB',
              +				uaCompanyUrl: 'http://www.entireweb.com/',
              +				uaIcon: 'bot_Speedy.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Speedy'
              +			}
              +		},
              +		'6298': {
              +			userAgent: 'findlinks/2.0.9 (+http://wortschatz.uni-leipzig.de/findlinks/)',
              +			metadata: {
              +				uaFamily: 'findlinks',
              +				uaName: 'findlinks/2.0.9',
              +				uaUrl: 'http://wortschatz.uni-leipzig.de/findlinks/',
              +				uaCompany: 'Universit\xe4t Leipzig',
              +				uaCompanyUrl: 'http://www.uni-leipzig.de/',
              +				uaIcon: 'bot_findlinks.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=findlinks'
              +			}
              +		},
              +		'6304': {
              +			userAgent: 'Mozilla/5.0 (compatible; NerdByNature.Bot; http://www.nerdbynature.net/bot)',
              +			metadata: {
              +				uaFamily: 'NerdByNature.Bot',
              +				uaName: 'NerdByNature.Bot',
              +				uaUrl: 'http://www.nerdbynature.net/bot',
              +				uaCompany: 'W3 Solutions GmbH',
              +				uaCompanyUrl: 'http://www.w3solutions.de/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=NerdByNature.Bot'
              +			}
              +		},
              +		'6312': {
              +			userAgent: 'findlinks/2.1 (+http://wortschatz.uni-leipzig.de/findlinks/)',
              +			metadata: {
              +				uaFamily: 'findlinks',
              +				uaName: 'findlinks/2.1',
              +				uaUrl: 'http://wortschatz.uni-leipzig.de/findlinks/',
              +				uaCompany: 'Universit\xe4t Leipzig',
              +				uaCompanyUrl: 'http://www.uni-leipzig.de/',
              +				uaIcon: 'bot_findlinks.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=findlinks'
              +			}
              +		},
              +		'6326': {
              +			userAgent: 'findlinks/2.1.3 (+http://wortschatz.uni-leipzig.de/findlinks/)',
              +			metadata: {
              +				uaFamily: 'findlinks',
              +				uaName: 'findlinks/2.1.3',
              +				uaUrl: 'http://wortschatz.uni-leipzig.de/findlinks/',
              +				uaCompany: 'Universit\xe4t Leipzig',
              +				uaCompanyUrl: 'http://www.uni-leipzig.de/',
              +				uaIcon: 'bot_findlinks.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=findlinks'
              +			}
              +		},
              +		'6329': {
              +			userAgent: 'Mozilla/5.0 (compatible; SISTRIX Crawler; http://crawler.sistrix.net/)',
              +			metadata: {
              +				uaFamily: 'sistrix',
              +				uaName: 'sistrix',
              +				uaUrl: 'http://crawler.sistrix.net/',
              +				uaCompany: 'SISTRIX GmbH',
              +				uaCompanyUrl: 'http://www.sistrix.de/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=sistrix'
              +			}
              +		},
              +		'6352': {
              +			userAgent: 'Mozilla/5.0 (compatible; Plukkie/1.4; http://www.botje.com/plukkie.htm)',
              +			metadata: {
              +				uaFamily: 'Plukkie',
              +				uaName: 'Plukkie/1.4',
              +				uaUrl: 'http://www.botje.com/plukkie.htm',
              +				uaCompany: 'botje.com',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Plukkie'
              +			}
              +		},
              +		'6353': {
              +			userAgent: 'GarlikCrawler/1.1 (http://garlik.com/, crawler@garlik.com)',
              +			metadata: {
              +				uaFamily: 'GarlikCrawler',
              +				uaName: 'GarlikCrawler/1.1 b',
              +				uaUrl: '',
              +				uaCompany: 'Garlik Limited',
              +				uaCompanyUrl: 'http://www.garlik.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=GarlikCrawler'
              +			}
              +		},
              +		'6399': {
              +			userAgent: 'Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)',
              +			metadata: {
              +				uaFamily: 'Baiduspider',
              +				uaName: 'Baiduspider/2.0',
              +				uaUrl: 'http://www.baidu.com/search/spider.htm',
              +				uaCompany: 'Baidu',
              +				uaCompanyUrl: 'http://www.baidu.com/',
              +				uaIcon: 'bot_baiduspider.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Baiduspider'
              +			}
              +		},
              +		'6404': {
              +			userAgent: 'Mozilla/5.0 (compatible; AhrefsBot/1.0; +http://ahrefs.com/robot/)',
              +			metadata: {
              +				uaFamily: 'AhrefsBot',
              +				uaName: 'AhrefsBot/1.0',
              +				uaUrl: 'http://ahrefs.com/robot/',
              +				uaCompany: 'Ahrefs.com',
              +				uaCompanyUrl: 'http://ahrefs.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=AhrefsBot'
              +			}
              +		},
              +		'6436': {
              +			userAgent: 'Mozilla/5.0 (compatible; MojeekBot/0.2; http://www.mojeek.com/bot.html)',
              +			metadata: {
              +				uaFamily: 'MojeekBot',
              +				uaName: 'MojeekBot/0.2',
              +				uaUrl: 'http://www.mojeek.com/bot.html',
              +				uaCompany: 'Mojeek Ltd.',
              +				uaCompanyUrl: 'http://www.mojeek.com/',
              +				uaIcon: 'bot_MojeekBot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MojeekBot'
              +			}
              +		},
              +		'6506': {
              +			userAgent: 'SEOENGWorldBot/1.0 (+http://www.seoengine.com/seoengbot.htm)',
              +			metadata: {
              +				uaFamily: 'SEOENGBot',
              +				uaName: 'SEOENGBot/1.0',
              +				uaUrl: 'http://www.seoengine.com/seoengbot.htm',
              +				uaCompany: 'SEO Engine',
              +				uaCompanyUrl: 'http://www.seoengine.com/',
              +				uaIcon: 'bot_SEOENGBot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SEOENGBot'
              +			}
              +		},
              +		'6514': {
              +			userAgent: 'Mozilla/5.0 (compatible; socketcrawler; http://nlp.fi.muni.cz/projects/biwec/)',
              +			metadata: {
              +				uaFamily: 'biwec',
              +				uaName: 'biwec',
              +				uaUrl: 'http://nlp.fi.muni.cz/projects/biwec/',
              +				uaCompany: 'Centre for Natural Language Processing',
              +				uaCompanyUrl: 'http://muni.cz/fi/335300?lang=en',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=biwec'
              +			}
              +		},
              +		'6515': {
              +			userAgent: 'Wotbox/2.0 (bot@wotbox.com; http://www.wotbox.com)',
              +			metadata: {
              +				uaFamily: 'Wotbox',
              +				uaName: 'Wotbox/2.0',
              +				uaUrl: 'http://www.wotbox.com/bot/',
              +				uaCompany: 'Wotbox Team',
              +				uaCompanyUrl: 'http://www.wotbox.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Wotbox'
              +			}
              +		},
              +		'6578': {
              +			userAgent: 'Mozilla/5.0 (compatible; Thumbshots.ru; +http://thumbshots.ru/bot) Firefox/3',
              +			metadata: {
              +				uaFamily: 'Thumbshots.ru',
              +				uaName: 'Thumbshots.ru',
              +				uaUrl: 'http://thumbshots.ru/bot',
              +				uaCompany: 'Sonorth Technologies',
              +				uaCompanyUrl: 'http://www.sonorth.com/tech/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Thumbshots.ru'
              +			}
              +		},
              +		'6583': {
              +			userAgent: 'JikeSpider Mozilla/5.0 (compatible; JikeSpider; +http://shoulu.jike.com/spider.html)',
              +			metadata: {
              +				uaFamily: 'JikeSpider',
              +				uaName: 'JikeSpider',
              +				uaUrl: 'http://shoulu.jike.com/spider.html',
              +				uaCompany: 'jike.com',
              +				uaCompanyUrl: 'http://www.jike.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=JikeSpider'
              +			}
              +		},
              +		'6592': {
              +			userAgent: 'Aboundex/0.2 (http://www.aboundex.com/crawler/)',
              +			metadata: {
              +				uaFamily: 'Aboundexbot',
              +				uaName: 'Aboundexbot/0.2',
              +				uaUrl: 'http://www.aboundex.com/crawler/',
              +				uaCompany: 'Aboundex.com',
              +				uaCompanyUrl: 'http://www.aboundex.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Aboundexbot'
              +			}
              +		},
              +		'6598': {
              +			userAgent: 'Mozilla/5.0 (compatible; SEOkicks-Robot +http://www.seokicks.de/robot.html)',
              +			metadata: {
              +				uaFamily: 'SEOkicks-Robot',
              +				uaName: 'SEOkicks-Robot',
              +				uaUrl: 'http://www.seokicks.de/robot.html',
              +				uaCompany: 'Torsten R\xfcckert Internetdienstleistungen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SEOkicks-Robot'
              +			}
              +		},
              +		'6603': {
              +			userAgent: 'Y!J-BRW/1.0 crawler (http://help.yahoo.co.jp/help/jp/search/indexing/indexing-15.html)',
              +			metadata: {
              +				uaFamily: 'Yahoo! JAPAN',
              +				uaName: 'Y!J-BRW/1.0',
              +				uaUrl: 'http://help.yahoo.co.jp/help/jp/search/indexing/indexing-15.html',
              +				uaCompany: 'Yahoo! Inc',
              +				uaCompanyUrl: 'http://www.yahoo.com/',
              +				uaIcon: 'bot_yahoo!slurp.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Yahoo! JAPAN'
              +			}
              +		},
              +		'6612': {
              +			userAgent: 'The Lemur Web Crawler/Nutch-1.3 (Lemur Web Crawler; http://boston.lti.cs.cmu.edu/crawler_12/; admin@lemurproject.org)',
              +			metadata: {
              +				uaFamily: 'LemurWebCrawler',
              +				uaName: 'LemurWebCrawler',
              +				uaUrl: 'http://boston.lti.cs.cmu.edu/crawler_12/',
              +				uaCompany: 'Language Technologies Institute',
              +				uaCompanyUrl: 'http://www.lti.cs.cmu.edu/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=LemurWebCrawler'
              +			}
              +		},
              +		'6625': {
              +			userAgent: 'LapozzBot/1.5 (+http://robot.lapozz.hu) ',
              +			metadata: {
              +				uaFamily: 'LapozzBot',
              +				uaName: 'LapozzBot/1.5',
              +				uaUrl: 'http://robot.lapozz.hu/',
              +				uaCompany: 'lapozz.hu',
              +				uaCompanyUrl: 'http://www.lapozz.hu/',
              +				uaIcon: 'bot_lapozzbot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=LapozzBot'
              +			}
              +		},
              +		'6630': {
              +			userAgent: 'CovarioIDS/1.1 (http://www.covario.com/ids; support at covario dot com)',
              +			metadata: {
              +				uaFamily: 'Covario-IDS',
              +				uaName: 'CovarioIDS/1.1',
              +				uaUrl: 'http://www.covario.com/ids',
              +				uaCompany: 'Covario, Inc.',
              +				uaCompanyUrl: 'http://www.covario.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Covario-IDS'
              +			}
              +		},
              +		'6647': {
              +			userAgent: 'Mozilla/5.0 (compatible; heritrix/3.1.0-RC1 +http://boston.lti.cs.cmu.edu/crawler_12/)',
              +			metadata: {
              +				uaFamily: 'LemurWebCrawler',
              +				uaName: 'LemurWebCrawler',
              +				uaUrl: 'http://boston.lti.cs.cmu.edu/crawler_12/',
              +				uaCompany: 'Language Technologies Institute',
              +				uaCompanyUrl: 'http://www.lti.cs.cmu.edu/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=LemurWebCrawler'
              +			}
              +		},
              +		'6679': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Linux 2.6.32-34-server; java 1.6.0_26; Europe/de) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'6680': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Windows 7 6.1; java 1.6.0_29; Europe/fr) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'6708': {
              +			userAgent: 'SEOENGBot/1.2 (+http://www.seoengine.com/seoengbot.htm)',
              +			metadata: {
              +				uaFamily: 'SEOENGBot',
              +				uaName: 'SEOENGBot/1.2 new',
              +				uaUrl: 'http://www.seoengine.com/seoengbot.htm',
              +				uaCompany: 'SEO Engine',
              +				uaCompanyUrl: 'http://www.seoengine.com/',
              +				uaIcon: 'bot_SEOENGBot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SEOENGBot'
              +			}
              +		},
              +		'6712': {
              +			userAgent: 'findlinks/2.1.5 (+http://wortschatz.uni-leipzig.de/findlinks/)',
              +			metadata: {
              +				uaFamily: 'findlinks',
              +				uaName: 'findlinks/2.1.5',
              +				uaUrl: 'http://wortschatz.uni-leipzig.de/findlinks/',
              +				uaCompany: 'Universit\xe4t Leipzig',
              +				uaCompanyUrl: 'http://www.uni-leipzig.de/',
              +				uaIcon: 'bot_findlinks.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=findlinks'
              +			}
              +		},
              +		'6721': {
              +			userAgent: 'Ronzoobot/1.5 (http://www.ronzoo.com/about/)',
              +			metadata: {
              +				uaFamily: 'Ronzoobot',
              +				uaName: 'Ronzoobot/1.5',
              +				uaUrl: 'http://www.ronzoo.com/about/',
              +				uaCompany: 'Ronzoo',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_Ronzoobot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Ronzoobot'
              +			}
              +		},
              +		'6735': {
              +			userAgent: 'netEstate NE Crawler (+http://www.sengine.info/)',
              +			metadata: {
              +				uaFamily: 'netEstate Crawler',
              +				uaName: 'netEstate NE Crawler',
              +				uaUrl: '',
              +				uaCompany: 'netEstate GmbH',
              +				uaCompanyUrl: 'http://www.netestate.de/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=netEstate Crawler'
              +			}
              +		},
              +		'6739': {
              +			userAgent: 'PagePeeker.com',
              +			metadata: {
              +				uaFamily: 'PagePeeker',
              +				uaName: 'PagePeeker',
              +				uaUrl: 'http://pagepeeker.com/robots',
              +				uaCompany: 'PagePeeker.com',
              +				uaCompanyUrl: 'http://pagepeeker.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=PagePeeker'
              +			}
              +		},
              +		'6751': {
              +			userAgent: 'Mozilla/5.0 (compatible; AhrefsBot/2.0; +http://ahrefs.com/robot/)',
              +			metadata: {
              +				uaFamily: 'AhrefsBot',
              +				uaName: 'AhrefsBot/2.0',
              +				uaUrl: 'http://ahrefs.com/robot/',
              +				uaCompany: 'Ahrefs.com',
              +				uaCompanyUrl: 'http://ahrefs.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=AhrefsBot'
              +			}
              +		},
              +		'6770': {
              +			userAgent: 'SemrushBot/0.9',
              +			metadata: {
              +				uaFamily: 'SemrushBot',
              +				uaName: 'SemrushBot/0.9',
              +				uaUrl: 'http://www.semrush.com/bot.html',
              +				uaCompany: 'SEOQuake Team',
              +				uaCompanyUrl: 'http://www.seoquaketeam.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SemrushBot'
              +			}
              +		},
              +		'6776': {
              +			userAgent: 'Mozilla/5.0 (compatible; WBSearchBot/1.1; +http://www.warebay.com/bot.html)',
              +			metadata: {
              +				uaFamily: 'WBSearchBot',
              +				uaName: 'WBSearchBot/1.1',
              +				uaUrl: 'http://www.warebay.com/bot.html',
              +				uaCompany: 'Ware Bay',
              +				uaCompanyUrl: 'http://www.warebay.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=WBSearchBot'
              +			}
              +		},
              +		'6802': {
              +			userAgent: 'Mozilla/5.0 (compatible; DCPbot/1.0; +http://domains.checkparams.com/)',
              +			metadata: {
              +				uaFamily: 'DCPbot',
              +				uaName: 'DCPbot/1.0',
              +				uaUrl: 'http://domains.checkparams.com/',
              +				uaCompany: 'CheckParams',
              +				uaCompanyUrl: 'http://checkparams.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=DCPbot'
              +			}
              +		},
              +		'6816': {
              +			userAgent: 'Mozilla/5.0 (compatible; SpiderLing (a SPIDER for LINGustic research); http://nlp.fi.muni.cz/projects/biwec/)',
              +			metadata: {
              +				uaFamily: 'SpiderLing',
              +				uaName: 'SpiderLing',
              +				uaUrl: 'http://nlp.fi.muni.cz/projects/biwec/',
              +				uaCompany: 'Natural Language Processing Centre',
              +				uaCompanyUrl: 'http://nlp.fi.muni.cz/en/nlpc',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SpiderLing'
              +			}
              +		},
              +		'6826': {
              +			userAgent: 'Mozilla/5.0 (compatible; oBot/2.3.1; +http://filterdb.iss.net/crawler/)',
              +			metadata: {
              +				uaFamily: 'oBot',
              +				uaName: 'oBot/2.3.1',
              +				uaUrl: 'http://filterdb.iss.net/crawler/',
              +				uaCompany: 'IBM Germany Research &amp; Development GmbH',
              +				uaCompanyUrl: 'http://www.ibm.com/ibm/de/de/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=oBot'
              +			}
              +		},
              +		'6829': {
              +			userAgent: 'Mozilla/5.0 (compatible; JikeSpider; +http://shoulu.jike.com/spider.html)',
              +			metadata: {
              +				uaFamily: 'JikeSpider',
              +				uaName: 'JikeSpider b',
              +				uaUrl: 'http://shoulu.jike.com/spider.html',
              +				uaCompany: 'jike.com',
              +				uaCompanyUrl: 'http://www.jike.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=JikeSpider'
              +			}
              +		},
              +		'6835': {
              +			userAgent: 'SETOOZBOT/5.0 ( compatible; SETOOZBOT/0.30 ; http://www.setooz.com/bot.html )',
              +			metadata: {
              +				uaFamily: 'Setoozbot',
              +				uaName: 'SETOOZBOT/0.30',
              +				uaUrl: 'http://www.setooz.com/oozbot.html',
              +				uaCompany: 'SETU Software Systems (P) Ltd.',
              +				uaCompanyUrl: 'http://www.setusoftware.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Setoozbot'
              +			}
              +		},
              +		'6837': {
              +			userAgent: 'SETOOZBOT/5.0 ( http://www.setooz.com/bot.html )',
              +			metadata: {
              +				uaFamily: 'Setoozbot',
              +				uaName: 'SETOOZBOT/5.0',
              +				uaUrl: 'http://www.setooz.com/oozbot.html',
              +				uaCompany: 'SETU Software Systems (P) Ltd.',
              +				uaCompanyUrl: 'http://www.setusoftware.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Setoozbot'
              +			}
              +		},
              +		'6840': {
              +			userAgent: 'Updownerbot (+http://www.updowner.com/bot)',
              +			metadata: {
              +				uaFamily: 'Updownerbot',
              +				uaName: 'Updownerbot',
              +				uaUrl: 'http://www.updowner.com/bot',
              +				uaCompany: 'updowner.com',
              +				uaCompanyUrl: 'http://www.updowner.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Updownerbot'
              +			}
              +		},
              +		'6877': {
              +			userAgent: 'Mozilla/5.0 (compatible; MJ12bot/v1.4.1; http://www.majestic12.co.uk/bot.php?+)',
              +			metadata: {
              +				uaFamily: 'MJ12bot',
              +				uaName: 'MJ12bot/v1.4.1',
              +				uaUrl: 'http://majestic12.co.uk/bot.php',
              +				uaCompany: 'Majestic-12',
              +				uaCompanyUrl: 'http://www.majestic12.co.uk/',
              +				uaIcon: 'bot_mj12bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MJ12bot'
              +			}
              +		},
              +		'6884': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Linux 3.0.0-14-generic; java 1.6.0_23; Europe/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'6892': {
              +			userAgent: 'Mozilla/5.0 (compatible; Semager/1.4c; +http://www.semager.de/blog/semager-bots/)',
              +			metadata: {
              +				uaFamily: 'Semager',
              +				uaName: 'Semager/1.4c',
              +				uaUrl: 'http://www.semager.de/blog/semager-bots/',
              +				uaCompany: 'NG-Marketing',
              +				uaCompanyUrl: 'http://www.ng-marketing.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Semager'
              +			}
              +		},
              +		'6896': {
              +			userAgent: 'yacybot (freeworld/global; i386 Linux 2.6.37.6-0.5-desktop; java 1.6.0_20; Europe/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'6905': {
              +			userAgent: 'Acoon v4.1.0 (www.acoon.de)',
              +			metadata: {
              +				uaFamily: 'AcoonBot',
              +				uaName: 'Acoon v4.1.0',
              +				uaUrl: 'http://www.acoon.de/robot.asp',
              +				uaCompany: 'Acoon GmbH',
              +				uaCompanyUrl: 'http://www.acoon.de/',
              +				uaIcon: 'bot_Acoon.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=AcoonBot'
              +			}
              +		},
              +		'6914': {
              +			userAgent: 'Mozilla/5.0 (compatible; OpenindexDeepSpider/Nutch-1.5-dev; +http://openindex.io/spider.html; systemsATopenindexDOTio)',
              +			metadata: {
              +				uaFamily: 'OpenindexSpider',
              +				uaName: 'OpenindexDeepSpider',
              +				uaUrl: 'http://www.openindex.io/en/webmasters/spider.html',
              +				uaCompany: 'Openindex B.V.',
              +				uaCompanyUrl: 'http://www.openindex.io/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=OpenindexSpider'
              +			}
              +		},
              +		'6921': {
              +			userAgent: 'Yeti-FeedItemCrawler/1.0 (NHN Corp.; http://help.naver.com/robots/)',
              +			metadata: {
              +				uaFamily: 'NaverBot',
              +				uaName: 'Yeti-FeedItemCrawler/1.0',
              +				uaUrl: 'http://help.naver.com/robots/',
              +				uaCompany: 'NHN Corporation',
              +				uaCompanyUrl: 'http://www.nhncorp.com/',
              +				uaIcon: 'bot_NaverBot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=NaverBot'
              +			}
              +		},
              +		'6922': {
              +			userAgent: 'Mozilla/5.0 (compatible; discobot/2.0; +http://discoveryengine.com/discobot.html)',
              +			metadata: {
              +				uaFamily: 'discoverybot',
              +				uaName: 'discobot/2.0',
              +				uaUrl: 'http://discoveryengine.com/discoverybot.html',
              +				uaCompany: 'discoveryengine.com. ',
              +				uaCompanyUrl: 'http://www.discoveryengine.com/',
              +				uaIcon: 'bot_discobot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=discoverybot'
              +			}
              +		},
              +		'6929': {
              +			userAgent: 'Mozilla/5.0 (compatible; WASALive-Bot ; http://blog.wasalive.com/wasalive-bots/)',
              +			metadata: {
              +				uaFamily: 'WASALive-Bot',
              +				uaName: ' WASALive-Bot',
              +				uaUrl: 'http://blog.wasalive.com/wasalive-bots/',
              +				uaCompany: 'WASALive',
              +				uaCompanyUrl: 'http://www.wasalive.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=WASALive-Bot'
              +			}
              +		},
              +		'6937': {
              +			userAgent: 'Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.0.5) Gecko/2010033101 Gentoo Firefox/3.0.5 (Dot TK - spider 3.0)',
              +			metadata: {
              +				uaFamily: 'Dot TK - spider',
              +				uaName: 'Dot TK - spider 3.0',
              +				uaUrl: '',
              +				uaCompany: 'Dot TK Limited',
              +				uaCompanyUrl: 'http://www.dot.tk/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Dot TK - spider'
              +			}
              +		},
              +		'6945': {
              +			userAgent: 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.51 (KHTML, like Gecko; Google Web Preview) Chrome/12.0.742 Safari/534.51',
              +			metadata: {
              +				uaFamily: 'Googlebot',
              +				uaName: 'Google Web Preview',
              +				uaUrl: 'http://support.google.com/webmasters/bin/answer.py?hl=en&answer=1062498',
              +				uaCompany: 'Google Inc.',
              +				uaCompanyUrl: 'http://www.google.com/',
              +				uaIcon: 'bot_googlebot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Googlebot'
              +			}
              +		},
              +		'6947': {
              +			userAgent: 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.24 (KHTML, like Gecko; Google Web Preview) Chrome/11.0.696 Safari/534.24 ',
              +			metadata: {
              +				uaFamily: 'Googlebot',
              +				uaName: 'Google Web Preview',
              +				uaUrl: 'http://support.google.com/webmasters/bin/answer.py?hl=en&answer=1062498',
              +				uaCompany: 'Google Inc.',
              +				uaCompanyUrl: 'http://www.google.com/',
              +				uaIcon: 'bot_googlebot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Googlebot'
              +			}
              +		},
              +		'6948': {
              +			userAgent: 'Mozilla/5.0 (en-us) AppleWebKit/525.13 (KHTML, like Gecko; Google Web Preview) Version/3.1 Safari/525.13',
              +			metadata: {
              +				uaFamily: 'Googlebot',
              +				uaName: 'Google Web Preview',
              +				uaUrl: 'http://support.google.com/webmasters/bin/answer.py?hl=en&answer=1062498',
              +				uaCompany: 'Google Inc.',
              +				uaCompanyUrl: 'http://www.google.com/',
              +				uaIcon: 'bot_googlebot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Googlebot'
              +			}
              +		},
              +		'6961': {
              +			userAgent: 'Visbot/2.0 (+http://www.visvo.com/en/webmasters.jsp;bot@visvo.com)',
              +			metadata: {
              +				uaFamily: 'Visbot',
              +				uaName: 'Visbot/2.0',
              +				uaUrl: 'http://www.visvo.com/webmasters.htm',
              +				uaCompany: 'Visvo Inc.',
              +				uaCompanyUrl: 'http://www.visvo.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Visbot'
              +			}
              +		},
              +		'6962': {
              +			userAgent: 'Mozilla/5.0 (compatible; UASlinkChecker/1.0; +http://user-agent-string.info/UASlinkChecker)',
              +			metadata: {
              +				uaFamily: 'UASlinkChecker',
              +				uaName: 'UASlinkChecker/1.0',
              +				uaUrl: 'http://user-agent-string.info/UASlinkChecker',
              +				uaCompany: 'Jaroslav Mallat',
              +				uaCompanyUrl: 'http://mallat.cz/',
              +				uaIcon: 'bot_UASlinkChecker.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=UASlinkChecker'
              +			}
              +		},
              +		'6968': {
              +			userAgent: 'yacybot (webportal/global; amd64 Linux 2.6.32-5-amd64; java 1.6.0_18; Europe/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'6974': {
              +			userAgent: 'PostPost/1.0 (+http://postpost.com/crawlers)',
              +			metadata: {
              +				uaFamily: 'PostPost',
              +				uaName: 'PostPost/1.0',
              +				uaUrl: 'http://postpost.com/crawlers',
              +				uaCompany: 'Boathouse group',
              +				uaCompanyUrl: 'http://www.boathouseinc.com/',
              +				uaIcon: 'bot_PostPost.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=PostPost'
              +			}
              +		},
              +		'6977': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Linux 2.6.32-5-amd64; java 1.6.0_18; Europe/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'6978': {
              +			userAgent: 'Pixray-Seeker/1.1 (Pixray-Seeker; crawler@pixray.com)',
              +			metadata: {
              +				uaFamily: 'Pixray-Seeker',
              +				uaName: 'Pixray-Seeker/1.1',
              +				uaUrl: 'http://www.pixray.com/pixraybot',
              +				uaCompany: 'PIXRAY GmbH.',
              +				uaCompanyUrl: 'http://www.pixray.com/',
              +				uaIcon: 'bot_PixraySeeker.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Pixray-Seeker'
              +			}
              +		},
              +		'6999': {
              +			userAgent: 'ichiro/3.0 (http://help.goo.ne.jp/help/article/1142)',
              +			metadata: {
              +				uaFamily: 'ichiro',
              +				uaName: 'ichiro/3.0',
              +				uaUrl: 'http://search.goo.ne.jp/option/use/sub4/sub4-1/',
              +				uaCompany: 'NTT-Resonant Inc.',
              +				uaCompanyUrl: 'http://www.nttr.co.jp/',
              +				uaIcon: 'bot_ichiro.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ichiro'
              +			}
              +		},
              +		'7001': {
              +			userAgent: 'Acoon v4.9.5 (www.acoon.de)',
              +			metadata: {
              +				uaFamily: 'AcoonBot',
              +				uaName: 'Acoon v4.9.5',
              +				uaUrl: 'http://www.acoon.de/robot.asp',
              +				uaCompany: 'Acoon GmbH',
              +				uaCompanyUrl: 'http://www.acoon.de/',
              +				uaIcon: 'bot_Acoon.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=AcoonBot'
              +			}
              +		},
              +		'7005': {
              +			userAgent: 'Mozilla/5.0 (compatible; MJ12bot/v1.4.2; http://www.majestic12.co.uk/bot.php?+)',
              +			metadata: {
              +				uaFamily: 'MJ12bot',
              +				uaName: 'MJ12bot/v1.4.2',
              +				uaUrl: 'http://majestic12.co.uk/bot.php',
              +				uaCompany: 'Majestic-12',
              +				uaCompanyUrl: 'http://www.majestic12.co.uk/',
              +				uaIcon: 'bot_mj12bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MJ12bot'
              +			}
              +		},
              +		'7008': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Linux 3.0.0-15-server; java 1.6.0_23; Europe/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'7009': {
              +			userAgent: 'Acoon v4.10.1 (www.acoon.de)',
              +			metadata: {
              +				uaFamily: 'AcoonBot',
              +				uaName: 'Acoon v4.10.1',
              +				uaUrl: 'http://www.acoon.de/robot.asp',
              +				uaCompany: 'Acoon GmbH',
              +				uaCompanyUrl: 'http://www.acoon.de/',
              +				uaIcon: 'bot_Acoon.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=AcoonBot'
              +			}
              +		},
              +		'7012': {
              +			userAgent: 'Mozilla/5.0 (compatible; Moatbot/2.2; +http://www.moat.com/pages/moatbot)',
              +			metadata: {
              +				uaFamily: 'Moatbot',
              +				uaName: 'Moatbot/2.2',
              +				uaUrl: 'http://www.moat.com/pages/moatbot',
              +				uaCompany: 'Moat Inc.',
              +				uaCompanyUrl: 'http://www.moat.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Moatbot'
              +			}
              +		},
              +		'7013': {
              +			userAgent: 'Mozilla/5.0 (compatible; YandexNews/3.0; +http://yandex.com/bots)',
              +			metadata: {
              +				uaFamily: 'YandexBot',
              +				uaName: 'YandexNews/3.0',
              +				uaUrl: 'http://yandex.com/bots',
              +				uaCompany: 'Yandex LLC',
              +				uaCompanyUrl: 'http://company.yandex.com/',
              +				uaIcon: 'bot_Yandex.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=YandexBot'
              +			}
              +		},
              +		'7014': {
              +			userAgent: 'Mozilla/5.0 (compatible; Konqueror/3.5; Linux) KHTML/3.5.5 (like Gecko) (Exabot-Thumbnails)',
              +			metadata: {
              +				uaFamily: 'Exabot',
              +				uaName: 'Exabot-Thumbnails',
              +				uaUrl: 'http://www.exabot.com/go/robot',
              +				uaCompany: 'Exalead S.A.',
              +				uaCompanyUrl: 'http://www.exalead.com/',
              +				uaIcon: 'bot_Exabot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Exabot'
              +			}
              +		},
              +		'7015': {
              +			userAgent: 'Mozilla/5.0 (compatible; Apercite; +http://www.apercite.fr/robot/index.html)',
              +			metadata: {
              +				uaFamily: 'Apercite',
              +				uaName: 'Apercite',
              +				uaUrl: 'http://www.apercite.fr/robot/index.html',
              +				uaCompany: 'Apercite',
              +				uaCompanyUrl: 'http://www.apercite.fr/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Apercite'
              +			}
              +		},
              +		'7018': {
              +			userAgent: 'Mozilla/5.0 (compatible; YandexMetrika/2.0; +http://yandex.com/bots)',
              +			metadata: {
              +				uaFamily: 'YandexBot',
              +				uaName: 'YandexMetrika/2.0',
              +				uaUrl: 'http://yandex.com/bots',
              +				uaCompany: 'Yandex LLC',
              +				uaCompanyUrl: 'http://company.yandex.com/',
              +				uaIcon: 'bot_Yandex.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=YandexBot'
              +			}
              +		},
              +		'7039': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Linux 3.2.1-gentoo-r2; java 1.6.0_22; Europe/de) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'7044': {
              +			userAgent: 'Ronzoobot/1.6 (http://www.ronzoo.com/about/)',
              +			metadata: {
              +				uaFamily: 'Ronzoobot',
              +				uaName: 'Ronzoobot/1.6',
              +				uaUrl: 'http://www.ronzoo.com/about/',
              +				uaCompany: 'Ronzoo',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_Ronzoobot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Ronzoobot'
              +			}
              +		},
              +		'7045': {
              +			userAgent: 'Mozilla/5.0 (compatible; OpenindexDeepSpider/Nutch-1.5-dev; +http://www.openindex.io/en/webmasters/spider.html; systemsATopenindexDOTio)',
              +			metadata: {
              +				uaFamily: 'OpenindexSpider',
              +				uaName: 'OpenindexDeepSpider',
              +				uaUrl: 'http://www.openindex.io/en/webmasters/spider.html',
              +				uaCompany: 'Openindex B.V.',
              +				uaCompanyUrl: 'http://www.openindex.io/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=OpenindexSpider'
              +			}
              +		},
              +		'7051': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Linux 3.0.0-12-generic; java 1.6.0_26; Europe/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'7053': {
              +			userAgent: 'gonzo2[p] (+http://www.suchen.de/faq.html)',
              +			metadata: {
              +				uaFamily: 'gonzo',
              +				uaName: 'gonzo2',
              +				uaUrl: 'http://www.suchen.de/faq.html',
              +				uaCompany: 'SEARCHTEQ',
              +				uaCompanyUrl: 'http://www.searchteq.de/',
              +				uaIcon: 'bot_gonzo.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=gonzo'
              +			}
              +		},
              +		'7055': {
              +			userAgent: 'Mozilla/5.0 (compatible; OpenindexShallowSpider/Nutch-1.5-dev; +http://www.openindex.io/en/webmasters/spider.html; systemsATopenindexDOTio)',
              +			metadata: {
              +				uaFamily: 'OpenindexSpider',
              +				uaName: 'OpenindexShalooowSpider',
              +				uaUrl: 'http://www.openindex.io/en/webmasters/spider.html',
              +				uaCompany: 'Openindex B.V.',
              +				uaCompanyUrl: 'http://www.openindex.io/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=OpenindexSpider'
              +			}
              +		},
              +		'7060': {
              +			userAgent: 'SemrushBot/Nutch-1.5-SNAPSHOT',
              +			metadata: {
              +				uaFamily: 'SemrushBot',
              +				uaName: 'SemrushBot',
              +				uaUrl: 'http://www.semrush.com/bot.html',
              +				uaCompany: 'SEOQuake Team',
              +				uaCompanyUrl: 'http://www.seoquaketeam.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SemrushBot'
              +			}
              +		},
              +		'7063': {
              +			userAgent: 'Pixray-Seeker/1.1 (Pixray-Seeker; http://www.pixray.com/pixraybot; crawler@pixray.com)',
              +			metadata: {
              +				uaFamily: 'Pixray-Seeker',
              +				uaName: 'Pixray-Seeker/1.1',
              +				uaUrl: 'http://www.pixray.com/pixraybot',
              +				uaCompany: 'PIXRAY GmbH.',
              +				uaCompanyUrl: 'http://www.pixray.com/',
              +				uaIcon: 'bot_PixraySeeker.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Pixray-Seeker'
              +			}
              +		},
              +		'7070': {
              +			userAgent: 'PagePeeker.com (info: http://pagepeeker.com/robots)',
              +			metadata: {
              +				uaFamily: 'PagePeeker',
              +				uaName: 'PagePeeker',
              +				uaUrl: 'http://pagepeeker.com/robots',
              +				uaCompany: 'PagePeeker.com',
              +				uaCompanyUrl: 'http://pagepeeker.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=PagePeeker'
              +			}
              +		},
              +		'7072': {
              +			userAgent: 'Mozilla/5.0 (compatible;WI Job Roboter Spider Version 3;+http://www.webintegration.at)',
              +			metadata: {
              +				uaFamily: 'Job Roboter Spider',
              +				uaName: 'Job Roboter Spider 3',
              +				uaUrl: 'http://www.webintegration.at/jobroboter_suchmaschine',
              +				uaCompany: 'Web Integration IT Service GmbH',
              +				uaCompanyUrl: 'http://www.webintegration.at/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Job Roboter Spider'
              +			}
              +		},
              +		'7079': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Linux 3.2.1-gentoo-r2; java 1.6.0_24; Europe/de) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'7083': {
              +			userAgent: 'EdisterBot (http://www.edister.com/bot.html)',
              +			metadata: {
              +				uaFamily: 'EdisterBot',
              +				uaName: 'EdisterBot',
              +				uaUrl: 'http://www.edister.com/bot.html',
              +				uaCompany: 'Jonathan Leger',
              +				uaCompanyUrl: 'http://www.jonathanleger.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=EdisterBot'
              +			}
              +		},
              +		'7084': {
              +			userAgent: 'Factbot 1.09 (see http://www.factbites.com/webmasters.php)',
              +			metadata: {
              +				uaFamily: 'factbot',
              +				uaName: 'Factbot 1.09',
              +				uaUrl: 'http://www.factbites.com/webmasters.php',
              +				uaCompany: 'Rapid Intelligence Pty Ltd',
              +				uaCompanyUrl: 'http://www.rapint.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=factbot'
              +			}
              +		},
              +		'7092': {
              +			userAgent: 'yacybot (webportal-global; amd64 Linux 2.6.32-5-amd64; java 1.6.0_18; Europe/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'7096': {
              +			userAgent: 'SemrushBot/0.91',
              +			metadata: {
              +				uaFamily: 'SemrushBot',
              +				uaName: 'SemrushBot/0.91',
              +				uaUrl: 'http://www.semrush.com/bot.html',
              +				uaCompany: 'SEOQuake Team',
              +				uaCompanyUrl: 'http://www.seoquaketeam.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SemrushBot'
              +			}
              +		},
              +		'7106': {
              +			userAgent: 'Mozilla/5.0 (compatible; heritrix/1.14.3 +http://www.accelobot.com)',
              +			metadata: {
              +				uaFamily: 'Accelobot',
              +				uaName: 'Accelobot',
              +				uaUrl: 'http://www.accelobot.com/',
              +				uaCompany: 'NetBase Solutions, Inc.',
              +				uaCompanyUrl: 'http://www.netbase.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Accelobot'
              +			}
              +		},
              +		'7107': {
              +			userAgent: 'Mozilla/5.0 (compatible; OpenindexDeepSpider/Nutch-1.5-dev; +http://www.openindex.io/en/webmasters/spider.html)',
              +			metadata: {
              +				uaFamily: 'OpenindexSpider',
              +				uaName: 'OpenindexDeepSpider',
              +				uaUrl: 'http://www.openindex.io/en/webmasters/spider.html',
              +				uaCompany: 'Openindex B.V.',
              +				uaCompanyUrl: 'http://www.openindex.io/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=OpenindexSpider'
              +			}
              +		},
              +		'7112': {
              +			userAgent: 'Acoon v4.10.3 (www.acoon.de)',
              +			metadata: {
              +				uaFamily: 'AcoonBot',
              +				uaName: 'Acoon v4.10.3',
              +				uaUrl: 'http://www.acoon.de/robot.asp',
              +				uaCompany: 'Acoon GmbH',
              +				uaCompanyUrl: 'http://www.acoon.de/',
              +				uaIcon: 'bot_Acoon.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=AcoonBot'
              +			}
              +		},
              +		'7113': {
              +			userAgent: 'Mozilla/5.0 (compatible; IstellaBot/1.01.18 +http://www.tiscali.it/)',
              +			metadata: {
              +				uaFamily: 'IstellaBot',
              +				uaName: 'IstellaBot/1.01.18',
              +				uaUrl: '',
              +				uaCompany: 'Tiscali Italia S.p.a',
              +				uaCompanyUrl: 'http://www.tiscali.it/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=IstellaBot'
              +			}
              +		},
              +		'7119': {
              +			userAgent: 'Mozilla/5.0 (compatible; imbot/0.1 +http://internetmemory.org/en/)',
              +			metadata: {
              +				uaFamily: 'imbot',
              +				uaName: 'imbot/0.1',
              +				uaUrl: '',
              +				uaCompany: 'Internet Memory Foundation (formerly European Archive)',
              +				uaCompanyUrl: 'http://internetmemory.org/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=imbot'
              +			}
              +		},
              +		'7126': {
              +			userAgent: 'SeznamBot/3.0 (HaF+http://fulltext.sblog.cz/)',
              +			metadata: {
              +				uaFamily: 'SeznamBot',
              +				uaName: 'SeznamBot/3.0',
              +				uaUrl: 'http://napoveda.seznam.cz/en/indexing-the-web.html',
              +				uaCompany: 'Seznam.cz, a.s.',
              +				uaCompanyUrl: 'http://www.seznam.cz/',
              +				uaIcon: 'seznam.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SeznamBot'
              +			}
              +		},
              +		'7132': {
              +			userAgent: 'Mozilla/5.0 (compatible; OpenindexShallowSpider/Nutch-1.5-dev; +http://www.openindex.io/en/webmasters/spider.html)',
              +			metadata: {
              +				uaFamily: 'OpenindexSpider',
              +				uaName: 'OpenindexShalooowSpider',
              +				uaUrl: 'http://www.openindex.io/en/webmasters/spider.html',
              +				uaCompany: 'Openindex B.V.',
              +				uaCompanyUrl: 'http://www.openindex.io/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=OpenindexSpider'
              +			}
              +		},
              +		'7133': {
              +			userAgent: 'Mozilla/5.0 (compatible; YioopBot; +http://www.yioop.com/bot.php)',
              +			metadata: {
              +				uaFamily: 'YioopBot',
              +				uaName: 'YioopBot',
              +				uaUrl: 'http://www.yioop.com/bot.php',
              +				uaCompany: 'Chris Pollett',
              +				uaCompanyUrl: 'http://pollett.org/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=YioopBot'
              +			}
              +		},
              +		'7138': {
              +			userAgent: 'Mozilla/5.0 (compatible; SWEBot/1.0; +http://swebot.net)',
              +			metadata: {
              +				uaFamily: 'SWEBot',
              +				uaName: 'SWEBot/1.0',
              +				uaUrl: 'http://swebot.net/',
              +				uaCompany: 'swebot.net',
              +				uaCompanyUrl: 'http://swebot.net/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SWEBot'
              +			}
              +		},
              +		'7139': {
              +			userAgent: 'Zookabot/2.4;++http://zookabot.com',
              +			metadata: {
              +				uaFamily: 'Zookabot',
              +				uaName: 'Zookabot/2.4',
              +				uaUrl: 'http://zookabot.com/',
              +				uaCompany: 'Hwacha ApS',
              +				uaCompanyUrl: 'http://hwacha.dk/',
              +				uaIcon: 'bot_Zookabot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Zookabot'
              +			}
              +		},
              +		'7143': {
              +			userAgent: 'DuckDuckPreview/1.0; (+http://duckduckgo.com/duckduckpreview.html)',
              +			metadata: {
              +				uaFamily: 'DuckDuckPreview',
              +				uaName: 'DuckDuckPreview/1.0',
              +				uaUrl: 'http://duckduckgo.com/duckduckpreview.html',
              +				uaCompany: 'DuckDuckGo, Inc.',
              +				uaCompanyUrl: 'http://duckduckgo.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=DuckDuckPreview'
              +			}
              +		},
              +		'7153': {
              +			userAgent: 'percbotspider <ops@percolate.com>',
              +			metadata: {
              +				uaFamily: 'percbotspider',
              +				uaName: 'percbotspider',
              +				uaUrl: '',
              +				uaCompany: 'Percolate Industries, Inc.',
              +				uaCompanyUrl: 'http://percolate.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=percbotspider'
              +			}
              +		},
              +		'7155': {
              +			userAgent: 'Mozilla/5.0 (compatible; SWEBot/1.0; +http://swebot-crawler.net)',
              +			metadata: {
              +				uaFamily: 'SWEBot',
              +				uaName: 'SWEBot/1.0',
              +				uaUrl: 'http://swebot.net/',
              +				uaCompany: 'swebot.net',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SWEBot'
              +			}
              +		},
              +		'7159': {
              +			userAgent: 'Mozilla/5.0 (compatible; YandexCatalog/3.0; +http://yandex.com/bots)',
              +			metadata: {
              +				uaFamily: 'YandexBot',
              +				uaName: 'YandexCatalog/3.0',
              +				uaUrl: 'http://yandex.com/bots',
              +				uaCompany: 'Yandex LLC',
              +				uaCompanyUrl: 'http://company.yandex.com/',
              +				uaIcon: 'bot_Yandex.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=YandexBot'
              +			}
              +		},
              +		'7160': {
              +			userAgent: 'Mozilla/5.0 (compatible; YandexDirect/3.0; +http://yandex.com/bots)',
              +			metadata: {
              +				uaFamily: 'YandexBot',
              +				uaName: 'YandexDirect/3.0',
              +				uaUrl: 'http://yandex.com/bots',
              +				uaCompany: 'Yandex LLC',
              +				uaCompanyUrl: 'http://company.yandex.com/',
              +				uaIcon: 'bot_Yandex.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=YandexBot'
              +			}
              +		},
              +		'7161': {
              +			userAgent: 'Mozilla/5.0 (compatible; YandexImageResizer/2.0; +http://yandex.com/bots)',
              +			metadata: {
              +				uaFamily: 'YandexBot',
              +				uaName: 'YandexImageResizer/2.0',
              +				uaUrl: 'http://yandex.com/bots',
              +				uaCompany: 'Yandex LLC',
              +				uaCompanyUrl: 'http://company.yandex.com/',
              +				uaIcon: 'bot_Yandex.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=YandexBot'
              +			}
              +		},
              +		'7162': {
              +			userAgent: 'Castabot/0.1 (+http://topixtream.com/)',
              +			metadata: {
              +				uaFamily: 'Castabot',
              +				uaName: 'Castabot/0.1',
              +				uaUrl: '',
              +				uaCompany: 'Ronan Amicel',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Castabot'
              +			}
              +		},
              +		'7163': {
              +			userAgent: 'ShowyouBot (http://showyou.com/crawler)',
              +			metadata: {
              +				uaFamily: 'ShowyouBot',
              +				uaName: 'ShowyouBot',
              +				uaUrl: '',
              +				uaCompany: 'Remixation, Inc',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ShowyouBot'
              +			}
              +		},
              +		'7164': {
              +			userAgent: 'Mozilla/5.0 (compatible; DCPbot/1.1; +http://domains.checkparams.com/)',
              +			metadata: {
              +				uaFamily: 'DCPbot',
              +				uaName: 'DCPbot/1.1',
              +				uaUrl: 'http://domains.checkparams.com/',
              +				uaCompany: 'CheckParams',
              +				uaCompanyUrl: 'http://checkparams.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=DCPbot'
              +			}
              +		},
              +		'7172': {
              +			userAgent: 'Yandex.Server/2009.5',
              +			metadata: {
              +				uaFamily: 'YandexBot',
              +				uaName: 'Yandex.Server/2009.5',
              +				uaUrl: 'http://yandex.com/bots',
              +				uaCompany: 'Yandex LLC',
              +				uaCompanyUrl: 'http://company.yandex.com/',
              +				uaIcon: 'bot_Yandex.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=YandexBot'
              +			}
              +		},
              +		'7173': {
              +			userAgent: 'Yandex.Server/2010.9',
              +			metadata: {
              +				uaFamily: 'YandexBot',
              +				uaName: 'Yandex.Server/2010.9',
              +				uaUrl: 'http://yandex.com/bots',
              +				uaCompany: 'Yandex LLC',
              +				uaCompanyUrl: 'http://company.yandex.com/',
              +				uaIcon: 'bot_Yandex.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=YandexBot'
              +			}
              +		},
              +		'7177': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Linux 2.6.32-5-amd64; java 1.6.0_18; Europe/de) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'7178': {
              +			userAgent: 'Acoon v4.10.4 (www.acoon.de)',
              +			metadata: {
              +				uaFamily: 'AcoonBot',
              +				uaName: 'Acoon v4.10.4',
              +				uaUrl: 'http://www.acoon.de/robot.asp',
              +				uaCompany: 'Acoon GmbH',
              +				uaCompanyUrl: 'http://www.acoon.de/',
              +				uaIcon: 'bot_Acoon.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=AcoonBot'
              +			}
              +		},
              +		'7211': {
              +			userAgent: 'Mozilla/5.0 (compatible; MetaJobBot; http://www.metajob.at/crawler)',
              +			metadata: {
              +				uaFamily: 'MetaJobBot',
              +				uaName: 'MetaJobBot',
              +				uaUrl: 'http://www.metajob.at/the/crawler',
              +				uaCompany: 'Dr. Manfred Schauer',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MetaJobBot'
              +			}
              +		},
              +		'7217': {
              +			userAgent: 'RADaR-Bot/Nutch-1.3 (http://radar-bot.com/)',
              +			metadata: {
              +				uaFamily: 'RADaR-Bot',
              +				uaName: 'RADaR-Bot',
              +				uaUrl: 'http://radar-bot.com/',
              +				uaCompany: 'Queryable Corp',
              +				uaCompanyUrl: 'http://www.inboxq.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=RADaR-Bot'
              +			}
              +		},
              +		'7225': {
              +			userAgent: 'Mozilla/5.0 (compatible; heritrix/3.1.1-SNAPSHOT-20120116.200628 +http://www.archive.org/details/archive.org_bot)',
              +			metadata: {
              +				uaFamily: 'heritrix',
              +				uaName: 'heritrix/3.1.1',
              +				uaUrl: 'http://www.archive.org/details/archive.org_bot',
              +				uaCompany: 'Internet Archive',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_heritrix.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=heritrix'
              +			}
              +		},
              +		'7230': {
              +			userAgent: 'AddThis.com robot tech.support@clearspring.com',
              +			metadata: {
              +				uaFamily: 'AddThis.com',
              +				uaName: 'AddThis.com robot',
              +				uaUrl: '',
              +				uaCompany: 'Clearspring Technologies, Inc.',
              +				uaCompanyUrl: 'http://www.clearspring.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=AddThis.com'
              +			}
              +		},
              +		'7238': {
              +			userAgent: 'Mozilla/5.0 (compatible; Netseer crawler/2.0; +http://www.netseer.com/crawler.html; crawler@netseer.com)',
              +			metadata: {
              +				uaFamily: 'Netseer',
              +				uaName: 'Netseer crawler/2.0',
              +				uaUrl: 'http://www.netseer.com/crawler.html',
              +				uaCompany: 'NetSeer, Inc.',
              +				uaCompanyUrl: 'http://www.netseer.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Netseer'
              +			}
              +		},
              +		'7243': {
              +			userAgent: 'Mozilla/5.0 (compatible; EventGuruBot/1.0; +http://www.eventguru.com/spider.html)',
              +			metadata: {
              +				uaFamily: 'EventGuruBot',
              +				uaName: 'EventGuruBot/1.0',
              +				uaUrl: 'http://www.eventguru.com/spider.html',
              +				uaCompany: 'Matt Wells',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=EventGuruBot'
              +			}
              +		},
              +		'7252': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Linux 2.6.26-2-amd64; java 1.6.0_18; Europe/de) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'7253': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Windows Server 2008 6.0; java 1.7.0_03; Europe/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'7258': {
              +			userAgent: 'SAMSUNG-SGH-E250/1.0 Profile/MIDP-2.0 Configuration/CLDC-1.1 UP.Browser/6.2.3.3.c.1.101 (GUI) MMP/2.0 (compatible; Googlebot-Mobile/2.1; +http://www.google.com/bot.html)',
              +			metadata: {
              +				uaFamily: 'Googlebot',
              +				uaName: 'Googlebot-Mobile/2.1',
              +				uaUrl: 'http://googlewebmastercentral.blogspot.com/2011/12/introducing-smartphone-googlebot-mobile.html',
              +				uaCompany: 'Google Inc.',
              +				uaCompanyUrl: 'http://www.google.com/',
              +				uaIcon: 'bot_googlebot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Googlebot'
              +			}
              +		},
              +		'7259': {
              +			userAgent: 'DoCoMo/2.0 N905i(c100;TB;W24H16) (compatible; Googlebot-Mobile/2.1; +http://www.google.com/bot.html)',
              +			metadata: {
              +				uaFamily: 'Googlebot',
              +				uaName: 'Googlebot-Mobile/2.1',
              +				uaUrl: 'http://googlewebmastercentral.blogspot.com/2011/12/introducing-smartphone-googlebot-mobile.html',
              +				uaCompany: 'Google Inc.',
              +				uaCompanyUrl: 'http://www.google.com/',
              +				uaIcon: 'bot_googlebot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Googlebot'
              +			}
              +		},
              +		'7260': {
              +			userAgent: 'Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_1 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8B117 Safari/6531.22.7 (compatible; Googlebot-Mobile/2.1; +http://www.google.com/bot.html)',
              +			metadata: {
              +				uaFamily: 'Googlebot',
              +				uaName: 'Googlebot-Mobile/2.1',
              +				uaUrl: 'http://googlewebmastercentral.blogspot.com/2011/12/introducing-smartphone-googlebot-mobile.html',
              +				uaCompany: 'Google Inc.',
              +				uaCompanyUrl: 'http://www.google.com/',
              +				uaIcon: 'bot_googlebot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Googlebot'
              +			}
              +		},
              +		'7263': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Windows 7 6.1; java 1.6.0_24; Europe/de) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'7265': {
              +			userAgent: 'Acoon v4.10.5 (www.acoon.de)',
              +			metadata: {
              +				uaFamily: 'AcoonBot',
              +				uaName: 'Acoon v4.10.5',
              +				uaUrl: 'http://www.acoon.de/robot.asp',
              +				uaCompany: 'Acoon GmbH',
              +				uaCompanyUrl: 'http://www.acoon.de/',
              +				uaIcon: 'bot_Acoon.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=AcoonBot'
              +			}
              +		},
              +		'7267': {
              +			userAgent: 'SemrushBot/0.92',
              +			metadata: {
              +				uaFamily: 'SemrushBot',
              +				uaName: 'SemrushBot/0.92',
              +				uaUrl: 'http://www.semrush.com/bot.html',
              +				uaCompany: 'SEOQuake Team',
              +				uaCompanyUrl: 'http://www.seoquaketeam.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SemrushBot'
              +			}
              +		},
              +		'7278': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Linux 2.6.32-custom; java 1.6.0_26; Europe/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'7285': {
              +			userAgent: 'OpenAcoon v4.10.5 (www.openacoon.de)',
              +			metadata: {
              +				uaFamily: 'AcoonBot',
              +				uaName: 'OpenAcoon v4.10.5',
              +				uaUrl: 'http://www.openacoon.de/',
              +				uaCompany: 'Acoon GmbH',
              +				uaCompanyUrl: 'http://www.acoon.de/',
              +				uaIcon: 'bot_Acoon.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=AcoonBot'
              +			}
              +		},
              +		'7300': {
              +			userAgent: 'Mozilla/5.0 (compatible; gofind; +http://govid.mobi/bot.php)',
              +			metadata: {
              +				uaFamily: 'YioopBot',
              +				uaName: 'gofind',
              +				uaUrl: 'http://govid.mobi/bot.php',
              +				uaCompany: 'Chris Pollett',
              +				uaCompanyUrl: 'http://pollett.org/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=YioopBot'
              +			}
              +		},
              +		'7303': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Linux 3.1.10-hardened; java 1.7.0_03-icedtea; Europe/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'7304': {
              +			userAgent: 'yacybot (freeworld/global; x86_64 Mac OS X 10.6.8; java 1.6.0_29; Asia/ru) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'7305': {
              +			userAgent: 'yacybot (freeworld/global; i386 Linux 2.6.32-39-generic-pae; java 1.6.0_20; Europe/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'7306': {
              +			userAgent: 'yacybot (freeworld/global; i386 Linux 3.0.0-17-generic-pae; java 1.6.0_23; Europe/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'7307': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Linux 2.6.32-5-amd64; java 1.6.0_26; Atlantic/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'7308': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Linux 3.0.0-17-generic; java 1.6.0_23; Europe/de) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'7309': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Linux 3.2.13-1-ARCH; java 1.7.0_03-icedtea; Europe/fr) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'7317': {
              +			userAgent: 'Twikle/1.0 , http://twikle.com , contact@twikle.com',
              +			metadata: {
              +				uaFamily: 'Twikle',
              +				uaName: 'Twikle/1.0',
              +				uaUrl: '',
              +				uaCompany: 'NATEVIA',
              +				uaCompanyUrl: 'http://www.natevia.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Twikle'
              +			}
              +		},
              +		'7320': {
              +			userAgent: 'Mozilla/5.0 (compatible; aiHitBot/1.1; +http://www.aihit.com/)',
              +			metadata: {
              +				uaFamily: 'aiHitBot',
              +				uaName: 'aiHitBot/1.1',
              +				uaUrl: '',
              +				uaCompany: 'aiHit Ltd.',
              +				uaCompanyUrl: 'http://aihit.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=aiHitBot'
              +			}
              +		},
              +		'7321': {
              +			userAgent: 'AcoonBot/4.10.5 (+http://www.acoon.de)',
              +			metadata: {
              +				uaFamily: 'AcoonBot',
              +				uaName: 'AcoonBot/4.10.5',
              +				uaUrl: 'http://www.acoon.de/robot.asp',
              +				uaCompany: 'Acoon GmbH',
              +				uaCompanyUrl: 'http://www.acoon.de/',
              +				uaIcon: 'bot_Acoon.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=AcoonBot'
              +			}
              +		},
              +		'7322': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Linux 3.0.0-17-generic; java 1.6.0_23; America/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'7323': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Linux 2.6.32-5-xen-amd64; java 1.6.0_18; Europe/fr) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'7324': {
              +			userAgent: 'yacybot (freeworld/global; i386 Linux 3.0.0-17-generic; java 1.6.0_23; America/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'7325': {
              +			userAgent: 'yacybot (freeworld/global; x86 Windows 7 6.1; java 1.6.0_31; Europe/de) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'7333': {
              +			userAgent: 'Mozilla/5.0 (compatible; AhrefsBot/3.0; +http://ahrefs.com/robot/)',
              +			metadata: {
              +				uaFamily: 'AhrefsBot',
              +				uaName: 'AhrefsBot/3.0',
              +				uaUrl: 'http://ahrefs.com/robot/',
              +				uaCompany: 'Ahrefs.com',
              +				uaCompanyUrl: 'http://ahrefs.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=AhrefsBot'
              +			}
              +		},
              +		'7338': {
              +			userAgent: 'findlinks/2.2 (+http://wortschatz.uni-leipzig.de/findlinks/)',
              +			metadata: {
              +				uaFamily: 'findlinks',
              +				uaName: 'findlinks/2.2',
              +				uaUrl: 'http://wortschatz.uni-leipzig.de/findlinks/',
              +				uaCompany: 'Universit\xe4t Leipzig',
              +				uaCompanyUrl: 'http://www.uni-leipzig.de/',
              +				uaIcon: 'bot_findlinks.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=findlinks'
              +			}
              +		},
              +		'7340': {
              +			userAgent: 'Mozilla/5.0 (compatible; Blekkobot; ScoutJet; +http://blekko.com/about/blekkobot)',
              +			metadata: {
              +				uaFamily: 'Blekkobot',
              +				uaName: 'Blekkobot',
              +				uaUrl: 'http://blekko.com/about/blekkobot',
              +				uaCompany: 'Blekko Inc.',
              +				uaCompanyUrl: 'http://blekko.com/',
              +				uaIcon: 'bot_blekkobot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Blekkobot'
              +			}
              +		},
              +		'7343': {
              +			userAgent: 'Mozilla/5.0 (compatible; Mail.RU/2.0)',
              +			metadata: {
              +				uaFamily: 'Mail.Ru bot',
              +				uaName: 'Mail.RU/2.0',
              +				uaUrl: 'http://go.mail.ru/help/robots',
              +				uaCompany: 'Mail.Ru Group',
              +				uaCompanyUrl: 'http://corp.mail.ru/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Mail.Ru bot'
              +			}
              +		},
              +		'7347': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Linux 2.6.32-40-server; java 1.6.0_20; Europe/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'7348': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Linux 3.1.10-1-desktop; java 1.6.0_22; Europe/de) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'7349': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Linux 2.6.38-14-generic; java 1.6.0_22; Europe/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'7362': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Linux 3.2.0-23-generic; java 1.6.0_24; Europe/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'7363': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Windows 7 6.1; java 1.6.0_31; Europe/de) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'7364': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Linux 3.2.0-21-generic; java 1.7.0_03-icedtea; America/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'7365': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Linux 3.2.0-2-amd64; java 1.6.0_24; Europe/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'7366': {
              +			userAgent: 'Mozilla/5.0 (compatible; AcoonBot/4.10.6; +http://www.acoon.de/robot.asp)',
              +			metadata: {
              +				uaFamily: 'AcoonBot',
              +				uaName: 'AcoonBot/4.10.6',
              +				uaUrl: 'http://www.acoon.de/robot.asp',
              +				uaCompany: 'Acoon GmbH',
              +				uaCompanyUrl: 'http://www.acoon.de/',
              +				uaIcon: 'bot_Acoon.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=AcoonBot'
              +			}
              +		},
              +		'7369': {
              +			userAgent: 'Mozilla/5.0 (compatible; CareerBot/1.1; +http://www.career-x.de/bot.html)',
              +			metadata: {
              +				uaFamily: 'CareerBot',
              +				uaName: 'CareerBot/1.1',
              +				uaUrl: 'http://www.career-x.de/bot.html',
              +				uaCompany: 'career-x GmbH',
              +				uaCompanyUrl: 'http://www.career-x.de/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=CareerBot'
              +			}
              +		},
              +		'7373': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Linux 2.6.32-40-generic; java 1.6.0_20; Europe/de) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'7374': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Windows Server 2008 R2 6.1; java 1.6.0_31; America/pt) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'7375': {
              +			userAgent: 'Mozilla/5.0 (compatible; MJ12bot/v1.4.3; http://www.majestic12.co.uk/bot.php?+)',
              +			metadata: {
              +				uaFamily: 'MJ12bot',
              +				uaName: 'MJ12bot/v1.4.3',
              +				uaUrl: 'http://majestic12.co.uk/bot.php',
              +				uaCompany: 'Majestic-12',
              +				uaCompanyUrl: 'http://www.majestic12.co.uk/',
              +				uaIcon: 'bot_mj12bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MJ12bot'
              +			}
              +		},
              +		'7380': {
              +			userAgent: 'Mozilla/5.0 (compatible; HomeTags/1.0; +http://www.hometags.nl/bot)',
              +			metadata: {
              +				uaFamily: 'HomeTags',
              +				uaName: 'HomeTags/1.0',
              +				uaUrl: 'http://www.hometags.nl/bot',
              +				uaCompany: 'HomeTags.nl',
              +				uaCompanyUrl: 'http://www.hometags.nl/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=HomeTags'
              +			}
              +		},
              +		'7381': {
              +			userAgent: 'Y!J-BRJ/YATS crawler (http://listing.yahoo.co.jp/support/faq/int/other/other_001.html)',
              +			metadata: {
              +				uaFamily: 'Yahoo! JAPAN',
              +				uaName: 'Y!J-BRJ/YATS',
              +				uaUrl: 'http://help.yahoo.co.jp/help/jp/search/indexing/indexing-15.html',
              +				uaCompany: 'Yahoo! Inc',
              +				uaCompanyUrl: 'http://www.yahoo.com/',
              +				uaIcon: 'bot_yahoo!slurp.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Yahoo! JAPAN'
              +			}
              +		},
              +		'7384': {
              +			userAgent: 'Mozilla/5.0 (compatible; UnisterBot; crawler@unister.de)',
              +			metadata: {
              +				uaFamily: 'UnisterBot',
              +				uaName: 'UnisterBot',
              +				uaUrl: '',
              +				uaCompany: 'Unister Holding GmbH',
              +				uaCompanyUrl: 'http://www.unister.de/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=UnisterBot'
              +			}
              +		},
              +		'7387': {
              +			userAgent: 'findlinks/2.0.5 (+http://wortschatz.uni-leipzig.de/findlinks/)',
              +			metadata: {
              +				uaFamily: 'findlinks',
              +				uaName: 'findlinks/2.0.5',
              +				uaUrl: 'http://wortschatz.uni-leipzig.de/findlinks/',
              +				uaCompany: 'Universit\xe4t Leipzig',
              +				uaCompanyUrl: 'http://www.uni-leipzig.de/',
              +				uaIcon: 'bot_findlinks.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=findlinks'
              +			}
              +		},
              +		'7399': {
              +			userAgent: 'findlinks/2.5 (+http://wortschatz.uni-leipzig.de/findlinks/)',
              +			metadata: {
              +				uaFamily: 'findlinks',
              +				uaName: 'findlinks/2.5',
              +				uaUrl: 'http://wortschatz.uni-leipzig.de/findlinks/',
              +				uaCompany: 'Universit\xe4t Leipzig',
              +				uaCompanyUrl: 'http://www.uni-leipzig.de/',
              +				uaIcon: 'bot_findlinks.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=findlinks'
              +			}
              +		},
              +		'7402': {
              +			userAgent: 'KeywordDensityRobot/0.8 (http://www.seocentro.com/tools/search-engines/keyword-density.html)',
              +			metadata: {
              +				uaFamily: 'KeywordDensityRobot',
              +				uaName: 'KeywordDensityRobot/0.8',
              +				uaUrl: 'http://www.seocentro.com/tools/seo/keyword-density.html',
              +				uaCompany: 'SeoCentro',
              +				uaCompanyUrl: 'http://www.seocentro.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=KeywordDensityRobot'
              +			}
              +		},
              +		'7404': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Linux 2.6.38-8-generic; java 1.6.0_22; Europe/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'7405': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Linux 3.1.10-1.9-default; java 1.6.0_24; Europe/de) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'7406': {
              +			userAgent: 'Mozilla/5.0 (compatible; MSIE or Firefox mutant; not on Windows server; + http://tab.search.daum.net/aboutWebSearch.html) Daumoa/3.0',
              +			metadata: {
              +				uaFamily: 'Daumoa',
              +				uaName: 'Daumoa/3.0',
              +				uaUrl: 'http://tab.search.daum.net/aboutWebSearch_en.html',
              +				uaCompany: 'Daum Communications Corp.',
              +				uaCompanyUrl: 'http://info.daum.net/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Daumoa'
              +			}
              +		},
              +		'7409': {
              +			userAgent: 'Mozilla/5.0 (compatible; AcoonBot/4.10.7; +http://www.acoon.de/robot.asp)',
              +			metadata: {
              +				uaFamily: 'AcoonBot',
              +				uaName: 'AcoonBot/4.10.7',
              +				uaUrl: 'http://www.acoon.de/robot.asp',
              +				uaCompany: 'Acoon GmbH',
              +				uaCompanyUrl: 'http://www.acoon.de/',
              +				uaIcon: 'bot_Acoon.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=AcoonBot'
              +			}
              +		},
              +		'7411': {
              +			userAgent: 'coccoc',
              +			metadata: {
              +				uaFamily: 'coccoc',
              +				uaName: 'coccoc',
              +				uaUrl: 'http://help.coccoc.com/',
              +				uaCompany: 'Coc Coc',
              +				uaCompanyUrl: 'http://coccoc.vn/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=coccoc'
              +			}
              +		},
              +		'7414': {
              +			userAgent: 'Influencebot/0.9; (Automatic classification of websites; http://www.influencebox.com/; info@influencebox.com)',
              +			metadata: {
              +				uaFamily: 'Influencebot',
              +				uaName: 'Influencebot/0.9',
              +				uaUrl: 'http://www.influencebox.com/',
              +				uaCompany: 'Frank',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Influencebot'
              +			}
              +		},
              +		'7420': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Linux 2.6.32-5-amd64; java 1.6.0_18; US/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'7421': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Windows Server 2008 R2 6.1; java 1.6.0_29; Europe/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'7422': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Windows 7 6.1; java 1.6.0_31; America/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'7423': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Linux 3.3.4-1-ARCH; java 1.6.0_24; Europe/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'7424': {
              +			userAgent: 'RyzeCrawler/1.1.1 ( http://www.domain2day.nl/crawler/)',
              +			metadata: {
              +				uaFamily: 'RyzeCrawler',
              +				uaName: 'RyzeCrawler/1.1.1',
              +				uaUrl: 'http://www.domain2day.nl/crawler/',
              +				uaCompany: 'Domain2day',
              +				uaCompanyUrl: 'http://www.domain2day.nl/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=RyzeCrawler'
              +			}
              +		},
              +		'7426': {
              +			userAgent: 'Mozilla/5.0 (compatible; YandexFavicons/1.0; +http://yandex.com/bots)',
              +			metadata: {
              +				uaFamily: 'YandexBot',
              +				uaName: 'YandexFavicons/1.0',
              +				uaUrl: 'http://yandex.com/bots',
              +				uaCompany: 'Yandex LLC',
              +				uaCompanyUrl: 'http://company.yandex.com/',
              +				uaIcon: 'bot_Yandex.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=YandexBot'
              +			}
              +		},
              +		'7427': {
              +			userAgent: 'Mozilla/5.0 (compatible; YandexAntivirus/2.0; +http://yandex.com/bots)',
              +			metadata: {
              +				uaFamily: 'YandexBot',
              +				uaName: 'YandexAntivirus/2.0',
              +				uaUrl: 'http://yandex.com/bots',
              +				uaCompany: 'Yandex LLC',
              +				uaCompanyUrl: 'http://company.yandex.com/',
              +				uaIcon: 'bot_Yandex.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=YandexBot'
              +			}
              +		},
              +		'7428': {
              +			userAgent: 'Mozilla/5.0 (compatible; YandexVideo/3.0; +http://yandex.com/bots)',
              +			metadata: {
              +				uaFamily: 'YandexBot',
              +				uaName: 'YandexVideo/3.0',
              +				uaUrl: 'http://yandex.com/bots',
              +				uaCompany: 'Yandex LLC',
              +				uaCompanyUrl: 'http://company.yandex.com/',
              +				uaIcon: 'bot_Yandex.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=YandexBot'
              +			}
              +		},
              +		'7429': {
              +			userAgent: 'Mozilla/5.0 (compatible; YandexMedia/3.0; +http://yandex.com/bots)',
              +			metadata: {
              +				uaFamily: 'YandexBot',
              +				uaName: 'YandexMedia/3.0',
              +				uaUrl: 'http://yandex.com/bots',
              +				uaCompany: 'Yandex LLC',
              +				uaCompanyUrl: 'http://company.yandex.com/',
              +				uaIcon: 'bot_Yandex.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=YandexBot'
              +			}
              +		},
              +		'7430': {
              +			userAgent: 'Mozilla/5.0 (compatible; YandexBlogs/0.99; robot; +http://yandex.com/bots)',
              +			metadata: {
              +				uaFamily: 'YandexBot',
              +				uaName: 'YandexBlogs/0.99',
              +				uaUrl: 'http://yandex.com/bots',
              +				uaCompany: 'Yandex LLC',
              +				uaCompanyUrl: 'http://company.yandex.com/',
              +				uaIcon: 'bot_Yandex.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=YandexBot'
              +			}
              +		},
              +		'7433': {
              +			userAgent: 'Mozilla/5.0 (compatible; YandexZakladki/3.0; +http://yandex.com/bots)',
              +			metadata: {
              +				uaFamily: 'YandexBot',
              +				uaName: 'YandexZakladki/3.0',
              +				uaUrl: 'http://yandex.com/bots',
              +				uaCompany: 'Yandex LLC',
              +				uaCompanyUrl: 'http://company.yandex.com/',
              +				uaIcon: 'bot_Yandex.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=YandexBot'
              +			}
              +		},
              +		'7437': {
              +			userAgent: 'Mozilla/5.0 (compatible; PaperLiBot/2.1; http://support.paper.li/entries/20023257-what-is-paper-li)',
              +			metadata: {
              +				uaFamily: 'PaperLiBot',
              +				uaName: 'PaperLiBot/2.1',
              +				uaUrl: 'http://support.paper.li/entries/20023257-what-is-paper-li',
              +				uaCompany: 'Paper.li',
              +				uaCompanyUrl: 'http://paper.li/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=PaperLiBot'
              +			}
              +		},
              +		'7438': {
              +			userAgent: 'WeSEE:Search/0.1 (Alpha, http://www.wesee.com/en/support/bot/)',
              +			metadata: {
              +				uaFamily: 'WeSEE:Search',
              +				uaName: 'WeSEE:Search/0.1 (Alpha)',
              +				uaUrl: 'http://www.wesee.com/en/support/bot/',
              +				uaCompany: 'WeSEE Ltd',
              +				uaCompanyUrl: 'http://www.wesee.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=WeSEE:Search'
              +			}
              +		},
              +		'7442': {
              +			userAgent: 'Mozilla/5.0 (compatible; bnf.fr_bot; +http://www.bnf.fr/fr/outils/a.dl_web_capture_robot.html)',
              +			metadata: {
              +				uaFamily: 'bnf.fr_bot',
              +				uaName: 'bnf.fr_bot',
              +				uaUrl: 'http://www.bnf.fr/fr/outils/a.dl_web_capture_robot.html',
              +				uaCompany: 'Bibliothe`que nationale de France',
              +				uaCompanyUrl: 'http://www.bnf.fr/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=bnf.fr_bot'
              +			}
              +		},
              +		'7458': {
              +			userAgent: 'Mozilla/5.0 (compatible; AcoonBot/4.10.8; +http://www.acoon.de/robot.asp)',
              +			metadata: {
              +				uaFamily: 'AcoonBot',
              +				uaName: 'AcoonBot/4.10.8',
              +				uaUrl: 'http://www.acoon.de/robot.asp',
              +				uaCompany: 'Acoon GmbH',
              +				uaCompanyUrl: 'http://www.acoon.de/',
              +				uaIcon: 'bot_Acoon.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=AcoonBot'
              +			}
              +		},
              +		'7462': {
              +			userAgent: 'Mozilla/5.0 (compatible; aiHitBot-BP/1.1; +http://www.aihit.com/)',
              +			metadata: {
              +				uaFamily: 'aiHitBot',
              +				uaName: 'aiHitBot-BP/1.1',
              +				uaUrl: '',
              +				uaCompany: 'aiHit Ltd',
              +				uaCompanyUrl: 'http://aihit.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=aiHitBot'
              +			}
              +		},
              +		'7467': {
              +			userAgent: 'findlinks/2.6 (+http://wortschatz.uni-leipzig.de/findlinks/)',
              +			metadata: {
              +				uaFamily: 'findlinks',
              +				uaName: 'findlinks/2.6',
              +				uaUrl: 'http://wortschatz.uni-leipzig.de/findlinks/',
              +				uaCompany: 'Universit\xe4t Leipzig',
              +				uaCompanyUrl: 'http://www.uni-leipzig.de/',
              +				uaIcon: 'bot_findlinks.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=findlinks'
              +			}
              +		},
              +		'7469': {
              +			userAgent: 'Mozilla/5.0 (compatible; UptimeRobot/1.0; http://www.uptimerobot.com/)',
              +			metadata: {
              +				uaFamily: 'UptimeRobot',
              +				uaName: 'UptimeRobot/1.0',
              +				uaUrl: 'http://www.uptimerobot.com/',
              +				uaCompany: 'Umut Muhaddisoglu, Daniel Rimille',
              +				uaCompanyUrl: 'http://www.webresourcesdepot.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=UptimeRobot'
              +			}
              +		},
              +		'7477': {
              +			userAgent: 'Mozilla/5.0 (compatible; AcoonBot/4.11.0; +http://www.acoon.de/robot.asp)',
              +			metadata: {
              +				uaFamily: 'AcoonBot',
              +				uaName: 'AcoonBot/4.11.0',
              +				uaUrl: 'http://www.acoon.de/robot.asp',
              +				uaCompany: 'Acoon GmbH',
              +				uaCompanyUrl: 'http://www.acoon.de/',
              +				uaIcon: 'bot_Acoon.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=AcoonBot'
              +			}
              +		},
              +		'7494': {
              +			userAgent: 'Mozilla/5.0 (compatible; Finderbots finder bot; +http://wiki.github.com/bixo/bixo/bixocrawler; bixo-dev@yahoogroups.com)',
              +			metadata: {
              +				uaFamily: 'bixocrawler',
              +				uaName: 'bixo',
              +				uaUrl: 'http://wiki.github.com/bixo/bixo/bixocrawler',
              +				uaCompany: 'Bixo Labs',
              +				uaCompanyUrl: 'http://openbixo.org/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=bixocrawler'
              +			}
              +		},
              +		'7510': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Linux 2.6.32-41-server; java 1.6.0_26; Europe/de) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'7511': {
              +			userAgent: 'yacybot (freeworld/global; i386 Linux 3.2.0-23-generic-pae; java 1.7.0_03; Europe/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'7512': {
              +			userAgent: 'yacybot (freeworld/global; x86 Windows 2003 5.2; java 1.6.0_32; Europe/de) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'7513': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Linux 3.2.0-24-generic; java 1.6.0_24; Europe/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'7525': {
              +			userAgent: 'MIA DEV/search:robot/0.0.1 (This is the MIA Bot - crawling for mia research project. If you feel unhappy and do not want to be visited by our crawler send an email to spider@neofonie.de; http://spider.neofonie.de; spider@neofonie.de)',
              +			metadata: {
              +				uaFamily: 'MIA Bot',
              +				uaName: 'MIA Bot',
              +				uaUrl: 'http://spider.neofonie.de',
              +				uaCompany: 'Neofonie GmbH',
              +				uaCompanyUrl: 'http://www.neofonie.de/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MIA Bot'
              +			}
              +		},
              +		'7542': {
              +			userAgent: 'infohelfer/1.1.0 (http://www.infohelfer.de/)',
              +			metadata: {
              +				uaFamily: 'Infohelfer',
              +				uaName: 'Infohelfer/1.0',
              +				uaUrl: 'http://www.infohelfer.de/crawler.php',
              +				uaCompany: 'ITam GmbH',
              +				uaCompanyUrl: 'http://www.itam-gmbh.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Infohelfer'
              +			}
              +		},
              +		'7544': {
              +			userAgent: 'Mozilla/5.0 (compatible; AcoonBot/4.11.1; +http://www.acoon.de/robot.asp)',
              +			metadata: {
              +				uaFamily: 'AcoonBot',
              +				uaName: 'AcoonBot/4.11.1',
              +				uaUrl: 'http://www.acoon.de/robot.asp',
              +				uaCompany: 'Acoon GmbH',
              +				uaCompanyUrl: 'http://www.acoon.de/',
              +				uaIcon: 'bot_Acoon.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=AcoonBot'
              +			}
              +		},
              +		'7548': {
              +			userAgent: 'coccoc/1.0 ()',
              +			metadata: {
              +				uaFamily: 'coccoc',
              +				uaName: 'coccoc/1.0',
              +				uaUrl: 'http://help.coccoc.com/',
              +				uaCompany: 'Coc Coc',
              +				uaCompanyUrl: 'http://coccoc.vn/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=coccoc'
              +			}
              +		},
              +		'7563': {
              +			userAgent: 'Mozilla/5.0 (compatible; OpenindexSpider/Nutch-1.5-dev; +http://www.openindex.io/en/webmasters/spider.html)',
              +			metadata: {
              +				uaFamily: 'OpenindexSpider',
              +				uaName: 'OpenindexSpider',
              +				uaUrl: 'http://www.openindex.io/en/webmasters/spider.html',
              +				uaCompany: 'Openindex B.V.',
              +				uaCompanyUrl: 'http://www.openindex.io/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=OpenindexSpider'
              +			}
              +		},
              +		'7577': {
              +			userAgent: 'wsAnalyzer/1.0; ++http://www.wsanalyzer.com/bot.html',
              +			metadata: {
              +				uaFamily: 'wsAnalyzer',
              +				uaName: 'wsAnalyzer/1.0',
              +				uaUrl: 'http://www.wsanalyzer.com/bot.html',
              +				uaCompany: 'wsAnalyzer.com',
              +				uaCompanyUrl: 'http://www.wsanalyzer.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=wsAnalyzer'
              +			}
              +		},
              +		'7579': {
              +			userAgent: 'Mozilla/5.0 (compatible; AhrefsBot/3.1; +http://ahrefs.com/robot/)',
              +			metadata: {
              +				uaFamily: 'AhrefsBot',
              +				uaName: 'AhrefsBot/3.1',
              +				uaUrl: 'http://ahrefs.com/robot/',
              +				uaCompany: 'Ahrefs.com',
              +				uaCompanyUrl: 'http://ahrefs.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=AhrefsBot'
              +			}
              +		},
              +		'7596': {
              +			userAgent: 'Wotbox/2.01 (+http://www.wotbox.com/bot/)',
              +			metadata: {
              +				uaFamily: 'Wotbox',
              +				uaName: 'Wotbox/2.01',
              +				uaUrl: 'http://www.wotbox.com/bot/',
              +				uaCompany: 'Wotbox Team',
              +				uaCompanyUrl: 'http://www.wotbox.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Wotbox'
              +			}
              +		},
              +		'7605': {
              +			userAgent: 'Mozilla/5.0 (compatible; ProCogBot/1.0; +http://www.procog.com/spider.html)',
              +			metadata: {
              +				uaFamily: 'ProCogBot',
              +				uaName: 'ProCogBot/1.0',
              +				uaUrl: 'http://www.procog.com/spider.html',
              +				uaCompany: 'ProCog.com',
              +				uaCompanyUrl: 'http://www.procog.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ProCogBot'
              +			}
              +		},
              +		'7606': {
              +			userAgent: 'Mozilla/5.0 (compatible; OpenindexSpider; +http://www.openindex.io/en/webmasters/spider.html)',
              +			metadata: {
              +				uaFamily: 'OpenindexSpider',
              +				uaName: 'OpenindexSpider',
              +				uaUrl: 'http://www.openindex.io/en/webmasters/spider.html',
              +				uaCompany: 'Openindex B.V.',
              +				uaCompanyUrl: 'http://www.openindex.io/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=OpenindexSpider'
              +			}
              +		},
              +		'7622': {
              +			userAgent: 'Woko 3.0',
              +			metadata: {
              +				uaFamily: 'Woko',
              +				uaName: 'Woko 3.0',
              +				uaUrl: 'http://www.woko.cz/akce.phtml?ukaz=osluzbe',
              +				uaCompany: 'Internet Info, s.r.o.',
              +				uaCompanyUrl: 'http://www.iinfo.cz/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Woko'
              +			}
              +		},
              +		'7624': {
              +			userAgent: 'EasyBib AutoCite (http://content.easybib.com/autocite/)',
              +			metadata: {
              +				uaFamily: 'EasyBib AutoCite',
              +				uaName: 'EasyBib AutoCite',
              +				uaUrl: 'http://content.easybib.com/autocite/',
              +				uaCompany: 'ImagineEasy Solutions.',
              +				uaCompanyUrl: 'http://www.imagineeasy.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=EasyBib AutoCite'
              +			}
              +		},
              +		'7625': {
              +			userAgent: 'Mozilla/5.0 (compatible;  Page2RSS/0.7; +http://page2rss.com/)',
              +			metadata: {
              +				uaFamily: 'Page2RSS',
              +				uaName: 'Page2RSS/0.7',
              +				uaUrl: '',
              +				uaCompany: 'Page Two Technologies LLC',
              +				uaCompanyUrl: 'http://page2rss.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Page2RSS'
              +			}
              +		},
              +		'7628': {
              +			userAgent: 'Woko robot 3.0',
              +			metadata: {
              +				uaFamily: 'Woko',
              +				uaName: 'Woko robot 3.0',
              +				uaUrl: 'http://www.woko.cz/akce.phtml?ukaz=osluzbe',
              +				uaCompany: 'Internet Info, s.r.o.',
              +				uaCompanyUrl: 'http://www.iinfo.cz/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Woko'
              +			}
              +		},
              +		'7632': {
              +			userAgent: 'Mozilla/5.0 (compatible; Infohelfer/1.2.0; +http://www.infohelfer.de/crawler.php)',
              +			metadata: {
              +				uaFamily: 'Infohelfer',
              +				uaName: 'Infohelfer/1.2.0',
              +				uaUrl: 'http://www.infohelfer.de/crawler.php',
              +				uaCompany: 'ITam GmbH',
              +				uaCompanyUrl: 'http://www.itam-gmbh.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Infohelfer'
              +			}
              +		},
              +		'7634': {
              +			userAgent: 'Mozilla/5.0 (compatible; WebNL; +http://www.web.nl/webmasters/spider.html; helpdesk@web.nl)',
              +			metadata: {
              +				uaFamily: 'WebNL',
              +				uaName: 'WebNL',
              +				uaUrl: 'http://www.web.nl/webmasters/spider.html',
              +				uaCompany: 'CRIO B.V.',
              +				uaCompanyUrl: 'http://www.crio.nl/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=WebNL'
              +			}
              +		},
              +		'7651': {
              +			userAgent: 'Y!J-BSC/1.0 crawler (http://help.yahoo.co.jp/help/jp/blog-search/)',
              +			metadata: {
              +				uaFamily: 'Yahoo! JAPAN',
              +				uaName: 'Y!J-BSC/1.0',
              +				uaUrl: 'http://help.yahoo.co.jp/help/jp/search/indexing/indexing-15.html',
              +				uaCompany: 'Yahoo Japan Corporation',
              +				uaCompanyUrl: 'http://www.yahoo.co.jp/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Yahoo! JAPAN'
              +			}
              +		},
              +		'7655': {
              +			userAgent: 'Mozilla/5.0 (compatible; proximic; +http://www.proximic.com/info/spider.php)',
              +			metadata: {
              +				uaFamily: 'proximic',
              +				uaName: 'proximic',
              +				uaUrl: 'http://www.proximic.com/info/spider.php',
              +				uaCompany: 'Proximic, Inc.',
              +				uaCompanyUrl: 'http://www.proximic.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=proximic'
              +			}
              +		},
              +		'7671': {
              +			userAgent: 'Sogou Web Spider',
              +			metadata: {
              +				uaFamily: 'sogou spider',
              +				uaName: 'Sogou web spider',
              +				uaUrl: 'http://www.sogou.com/docs/help/webmasters.htm#07',
              +				uaCompany: 'SOGOU.COM',
              +				uaCompanyUrl: 'http://www.sogou.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=sogou spider'
              +			}
              +		},
              +		'7675': {
              +			userAgent: 'Mozilla/5.0 (Windows; U; Windows NT 6.0; en-GB; rv:1.0; trendictionbot0.5.0; trendiction search; http://www.trendiction.de/bot; please let us know of any problems; web at trendiction.com) Gecko/20071127 Firefox/3.0.0.11',
              +			metadata: {
              +				uaFamily: 'trendictionbot ',
              +				uaName: 'trendictionbot0.5.0',
              +				uaUrl: 'http://www.trendiction.de/bot',
              +				uaCompany: 'Trendiction S.A.',
              +				uaCompanyUrl: 'http://www.trendiction.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=trendictionbot '
              +			}
              +		},
              +		'7676': {
              +			userAgent: 'ichiro/3.0 (http://search.goo.ne.jp/option/use/sub4/sub4-1/)',
              +			metadata: {
              +				uaFamily: 'ichiro',
              +				uaName: 'ichiro/3.0',
              +				uaUrl: 'http://search.goo.ne.jp/option/use/sub4/sub4-1/',
              +				uaCompany: 'NTT-Resonant Inc.',
              +				uaCompanyUrl: 'http://www.nttr.co.jp/',
              +				uaIcon: 'bot_ichiro.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ichiro'
              +			}
              +		},
              +		'7696': {
              +			userAgent: 'bot-pge.chlooe.com/1.0.0 (+http://www.chlooe.com/)',
              +			metadata: {
              +				uaFamily: 'bot-pge.chlooe.com',
              +				uaName: 'bot-pge.chlooe.com/1.0.0',
              +				uaUrl: 'http://bot-pge.chlooe.com/',
              +				uaCompany: 'Chlooe.com',
              +				uaCompanyUrl: 'http://www.chlooe.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=bot-pge.chlooe.com'
              +			}
              +		},
              +		'7697': {
              +			userAgent: 'Mozilla/5.0(compatible; Sosospider/2.0; +http://help.soso.com/webspider.htm)',
              +			metadata: {
              +				uaFamily: 'Sosospider',
              +				uaName: 'Sosospider/2.0',
              +				uaUrl: 'http://help.soso.com/webspider.htm',
              +				uaCompany: 'Tencent, Inc.',
              +				uaCompanyUrl: 'http://www.tencent.com/',
              +				uaIcon: 'bot_soso.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Sosospider'
              +			}
              +		},
              +		'7717': {
              +			userAgent: 'Mozilla/5.0 (compatible; GrapeshotCrawler/2.0; +http://www.grapeshot.co.uk/crawler.php)',
              +			metadata: {
              +				uaFamily: 'GrapeshotCrawler',
              +				uaName: 'GrapeshotCrawler/2.0',
              +				uaUrl: 'http://www.grapeshot.co.uk/crawler.php',
              +				uaCompany: 'Grapeshot Limited',
              +				uaCompanyUrl: 'http://www.grapeshot.co.uk/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=GrapeshotCrawler'
              +			}
              +		},
              +		'7718': {
              +			userAgent: 'Mozilla/5.0 (compatible; grapeFX/0.9; crawler@grapeshot.co.uk',
              +			metadata: {
              +				uaFamily: 'GrapeshotCrawler',
              +				uaName: 'grapeFX/0.9',
              +				uaUrl: 'http://www.grapeshot.co.uk/crawler.php',
              +				uaCompany: 'Grapeshot Limited',
              +				uaCompanyUrl: 'http://www.grapeshot.co.uk/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=GrapeshotCrawler'
              +			}
              +		},
              +		'7726': {
              +			userAgent: 'Mozilla/5.0 (compatible; Infohelfer/1.3.0; +http://www.infohelfer.de/crawler.php)',
              +			metadata: {
              +				uaFamily: 'Infohelfer',
              +				uaName: 'Infohelfer/1.3.0',
              +				uaUrl: 'http://www.infohelfer.de/crawler.php',
              +				uaCompany: 'ITam GmbH',
              +				uaCompanyUrl: 'http://www.itam-gmbh.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Infohelfer'
              +			}
              +		},
              +		'7727': {
              +			userAgent: 'coccoc/1.0 (http://help.coccoc.vn/)',
              +			metadata: {
              +				uaFamily: 'coccoc',
              +				uaName: 'coccoc/1.0',
              +				uaUrl: 'http://help.coccoc.com/',
              +				uaCompany: 'Coc Coc',
              +				uaCompanyUrl: 'http://coccoc.vn/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=coccoc'
              +			}
              +		},
              +		'7729': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Windows 7 6.1; java 1.6.0_25; Europe/de) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'7732': {
              +			userAgent: 'Bad-Neighborhood Link Analyzer (http://www.bad-neighborhood.com/)',
              +			metadata: {
              +				uaFamily: 'Bad-Neighborhood',
              +				uaName: 'Bad-Neighborhood Link Analyzer',
              +				uaUrl: 'http://www.bad-neighborhood.com/text-link-tool.htm',
              +				uaCompany: 'Michael VanDeMar',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Bad-Neighborhood'
              +			}
              +		},
              +		'7733': {
              +			userAgent: 'Bad Neighborhood Header Detector (http://www.bad-neighborhood.com/header_detector.php)',
              +			metadata: {
              +				uaFamily: 'Bad-Neighborhood',
              +				uaName: 'Bad Neighborhood Header Detector',
              +				uaUrl: 'http://www.bad-neighborhood.com/header_detector.php',
              +				uaCompany: 'Michael VanDeMar',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Bad-Neighborhood'
              +			}
              +		},
              +		'7747': {
              +			userAgent: 'Whoismindbot/1.0 (+http://www.whoismind.com/bot.html)',
              +			metadata: {
              +				uaFamily: 'Whoismindbot',
              +				uaName: 'Whoismindbot/1.0',
              +				uaUrl: 'http://www.whoismind.com/bot.html',
              +				uaCompany: 'WhoisMind',
              +				uaCompanyUrl: 'http://www.whoismind.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Whoismindbot'
              +			}
              +		},
              +		'7748': {
              +			userAgent: 'webinatorbot 1.0; +http://www.webinator.de',
              +			metadata: {
              +				uaFamily: 'webinatorbot',
              +				uaName: 'webinatorbot 1.0',
              +				uaUrl: '',
              +				uaCompany: 'HighSignal UG',
              +				uaCompanyUrl: 'http://www.highsignal.de/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=webinatorbot'
              +			}
              +		},
              +		'7754': {
              +			userAgent: 'Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm',
              +			metadata: {
              +				uaFamily: 'bingbot',
              +				uaName: 'bingbot/2.0',
              +				uaUrl: 'http://www.bing.com/webmaster/help/which-crawlers-does-bing-use-8c184ec0',
              +				uaCompany: 'Microsoft Corporation',
              +				uaCompanyUrl: 'http://www.microsoft.com/',
              +				uaIcon: 'bot_msnbot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=bingbot'
              +			}
              +		},
              +		'7757': {
              +			userAgent: 'search.KumKie.com',
              +			metadata: {
              +				uaFamily: 'search.KumKie.com',
              +				uaName: 'search.KumKie.com',
              +				uaUrl: '',
              +				uaCompany: 'Gifts Next Day',
              +				uaCompanyUrl: 'http://giftsnextday.net/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=search.KumKie.com'
              +			}
              +		},
              +		'7764': {
              +			userAgent: 'Mozilla/5.0 (compatible; DripfeedBot/2.0; +http://dripfeedbookmark.com/bot.html',
              +			metadata: {
              +				uaFamily: 'DripfeedBot',
              +				uaName: 'DripfeedBot/2.0',
              +				uaUrl: 'http://dripfeedbookmark.com/bot.html',
              +				uaCompany: 'dripfeedbookmark.com',
              +				uaCompanyUrl: 'http://dripfeedbookmark.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=DripfeedBot'
              +			}
              +		},
              +		'7776': {
              +			userAgent: 'Mozilla/5.0 (compatible; SemrushBot/0.95; +http://www.semrush.com/bot.html)',
              +			metadata: {
              +				uaFamily: 'SemrushBot',
              +				uaName: 'SemrushBot/0.95',
              +				uaUrl: 'http://www.semrush.com/bot.html',
              +				uaCompany: 'SEOQuake Team',
              +				uaCompanyUrl: 'http://www.seoquaketeam.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SemrushBot'
              +			}
              +		},
              +		'7780': {
              +			userAgent: 'ZumBot/1.0 (ZUM Search; http://help.zum.com/inquiry)',
              +			metadata: {
              +				uaFamily: 'ZumBot',
              +				uaName: 'ZumBot/1.0',
              +				uaUrl: 'http://help.zum.com/inquiry',
              +				uaCompany: 'ZUMinternet Corp',
              +				uaCompanyUrl: 'http://www.zuminternet.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ZumBot'
              +			}
              +		},
              +		'7784': {
              +			userAgent: 'Pixray-Seeker/2.0 (Pixray-Seeker; http://www.pixray.com/pixraybot; crawler@pixray.com)',
              +			metadata: {
              +				uaFamily: 'Pixray-Seeker',
              +				uaName: 'Pixray-Seeker/2.0',
              +				uaUrl: 'http://www.pixray.com/pixraybot',
              +				uaCompany: 'PIXRAY GmbH.',
              +				uaCompanyUrl: 'http://www.pixray.com/',
              +				uaIcon: 'bot_PixraySeeker.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Pixray-Seeker'
              +			}
              +		},
              +		'7790': {
              +			userAgent: 'Mozilla/5.0 (compatible; discoverybot/2.0; +http://discoveryengine.com/discoverybot.html)',
              +			metadata: {
              +				uaFamily: 'discoverybot',
              +				uaName: 'discoverybot/2.0',
              +				uaUrl: 'http://discoveryengine.com/discoverybot.html',
              +				uaCompany: 'discoveryengine.com.',
              +				uaCompanyUrl: 'http://www.discoveryengine.com/',
              +				uaIcon: 'bot_discobot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=discoverybot'
              +			}
              +		},
              +		'7799': {
              +			userAgent: 'rogerbot/1.0 (http://www.seomoz.org/dp/rogerbot, rogerbot-crawler@seomoz.org)',
              +			metadata: {
              +				uaFamily: 'rogerbot',
              +				uaName: 'rogerbot/1.0',
              +				uaUrl: 'http://moz.com/help/pro/what-is-rogerbot-',
              +				uaCompany: 'SEOmoz, Inc.',
              +				uaCompanyUrl: 'http://moz.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=rogerbot'
              +			}
              +		},
              +		'7816': {
              +			userAgent: 'Mozilla/5.0 (compatible; Plukkie/1.5; http://www.botje.com/plukkie.htm)',
              +			metadata: {
              +				uaFamily: 'Plukkie',
              +				uaName: 'Plukkie/1.3',
              +				uaUrl: 'http://www.botje.com/plukkie.htm',
              +				uaCompany: 'botje.com',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Plukkie'
              +			}
              +		},
              +		'7819': {
              +			userAgent: 'www.integromedb.org/Crawler',
              +			metadata: {
              +				uaFamily: 'IntegromeDB',
              +				uaName: 'IntegromeDB',
              +				uaUrl: 'http://www.integromedb.org/Crawler',
              +				uaCompany: 'BiologicalNetworks',
              +				uaCompanyUrl: 'http://www.biologicalnetworks.org/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=IntegromeDB'
              +			}
              +		},
              +		'7832': {
              +			userAgent: 'drupact/0.7; http://www.arocom.de/drupact',
              +			metadata: {
              +				uaFamily: 'drupact',
              +				uaName: 'drupact/0.7',
              +				uaUrl: 'http://www.arocom.de/drupact',
              +				uaCompany: 'arocom GmbH',
              +				uaCompanyUrl: 'http://www.arocom.de/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=drupact'
              +			}
              +		},
              +		'7833': {
              +			userAgent: 'peerindex/0.1 (http://www.peerindex.com/; crawler AT peerindex DOT com)',
              +			metadata: {
              +				uaFamily: 'peerindex',
              +				uaName: 'peerindex/0.1',
              +				uaUrl: '',
              +				uaCompany: 'PeerIndex',
              +				uaCompanyUrl: 'http://www.peerindex.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=peerindex'
              +			}
              +		},
              +		'7841': {
              +			userAgent: 'WillyBot/1.1 (http://www.willyfogg.com/info/willybot)',
              +			metadata: {
              +				uaFamily: 'WillyBot',
              +				uaName: 'WillyBot/1.1',
              +				uaUrl: 'http://willyfogg.com/info/willybot',
              +				uaCompany: 'WillyFogg.com ',
              +				uaCompanyUrl: 'http://willyfogg.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=WillyBot'
              +			}
              +		},
              +		'7843': {
              +			userAgent: 'Mozilla/5.0 (compatible; AhrefsBot/4.0; +http://ahrefs.com/robot/)',
              +			metadata: {
              +				uaFamily: 'AhrefsBot',
              +				uaName: 'AhrefsBot/4.0',
              +				uaUrl: 'http://ahrefs.com/robot/',
              +				uaCompany: 'Ahrefs.com',
              +				uaCompanyUrl: 'http://ahrefs.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=AhrefsBot'
              +			}
              +		},
              +		'7854': {
              +			userAgent: 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.21 (KHTML, like Gecko) Chrome/19.0.1042.0 Safari/535.21 PagePeeker/2.1; +http://pagepeeker.com/robots/',
              +			metadata: {
              +				uaFamily: 'PagePeeker',
              +				uaName: 'PagePeeker/2.1',
              +				uaUrl: 'http://pagepeeker.com/robots',
              +				uaCompany: 'PagePeeker.com',
              +				uaCompanyUrl: 'http://pagepeeker.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=PagePeeker'
              +			}
              +		},
              +		'7856': {
              +			userAgent: 'netEstate NE Crawler (+http://www.website-datenbank.de/)',
              +			metadata: {
              +				uaFamily: 'netEstate Crawler',
              +				uaName: 'netEstate NE Crawler',
              +				uaUrl: '',
              +				uaCompany: 'netEstate GmbH',
              +				uaCompanyUrl: 'http://www.netestate.de/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=netEstate Crawler'
              +			}
              +		},
              +		'7888': {
              +			userAgent: 'MeMoNewsBot/2.0 (http://www.memonews.com/en/crawler)',
              +			metadata: {
              +				uaFamily: 'MeMoNewsBot',
              +				uaName: 'MeMoNewsBot/2.0',
              +				uaUrl: 'http://www.memonews.com/en/crawler',
              +				uaCompany: 'MeMo News AG',
              +				uaCompanyUrl: 'http://www.memonews.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MeMoNewsBot'
              +			}
              +		},
              +		'7889': {
              +			userAgent: 'Mozilla/5.0 (compatible; pmoz.info ODP link checker; +http://pmoz.info/doc/botinfo.htm)',
              +			metadata: {
              +				uaFamily: 'pmoz.info ODP link checker',
              +				uaName: 'pmoz.info ODP link checker',
              +				uaUrl: 'http://pmoz.info/doc/botinfo.htm',
              +				uaCompany: 'PlantRob',
              +				uaCompanyUrl: 'http://www.robsplants.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=pmoz.info ODP link checker'
              +			}
              +		},
              +		'7912': {
              +			userAgent: 'Mozilla/5.0 (compatible; spbot/3.1; +http://www.seoprofiler.com/bot )',
              +			metadata: {
              +				uaFamily: 'spbot',
              +				uaName: 'spbot/3.1',
              +				uaUrl: 'http://www.seoprofiler.com/bot/',
              +				uaCompany: 'Axandra GmbH',
              +				uaCompanyUrl: 'http://www.axandra.com/',
              +				uaIcon: 'bot_spbot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=spbot'
              +			}
              +		},
              +		'7927': {
              +			userAgent: 'Mozilla/5.0 (compatible; CompSpyBot/1.0; +http://www.compspy.com/spider.html)',
              +			metadata: {
              +				uaFamily: 'CompSpyBot',
              +				uaName: 'CompSpyBot/1.0',
              +				uaUrl: 'http://www.compspy.com/spider.html',
              +				uaCompany: 'compspy.com',
              +				uaCompanyUrl: 'http://www.compspy.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=CompSpyBot'
              +			}
              +		},
              +		'7959': {
              +			userAgent: 'Mozilla/5.0 (compatible; Peepowbot/1.0; +http://www.peepow.com/bot.php)',
              +			metadata: {
              +				uaFamily: 'Peepowbot',
              +				uaName: 'Peepowbot/1.0',
              +				uaUrl: 'http://www.peepow.com/bot.php',
              +				uaCompany: 'peepow.com',
              +				uaCompanyUrl: 'http://peepow.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Peepowbot'
              +			}
              +		},
              +		'7975': {
              +			userAgent: 'HubSpot Connect 1.0 (http://dev.hubspot.com/)',
              +			metadata: {
              +				uaFamily: 'HubSpot Connect',
              +				uaName: 'HubSpot Connect 1.0',
              +				uaUrl: '',
              +				uaCompany: 'HubSpot Inc.',
              +				uaCompanyUrl: 'http://www.hubspot.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=HubSpot Connect'
              +			}
              +		},
              +		'7984': {
              +			userAgent: 'Mozilla/5.0 (compatible; Mail.RU_Bot/2.0)',
              +			metadata: {
              +				uaFamily: 'Mail.Ru bot',
              +				uaName: 'Mail.RU_Bot/2.0',
              +				uaUrl: 'http://go.mail.ru/help/robots',
              +				uaCompany: 'Mail.Ru Group',
              +				uaCompanyUrl: 'http://corp.mail.ru/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Mail.Ru bot'
              +			}
              +		},
              +		'7995': {
              +			userAgent: 'Mozilla/5.0 (compatible; IstellaBot/1.10.2 +http://www.tiscali.it/)',
              +			metadata: {
              +				uaFamily: 'IstellaBot',
              +				uaName: 'IstellaBot/1.10.2',
              +				uaUrl: '',
              +				uaCompany: 'Tiscali Italia S.p.a',
              +				uaCompanyUrl: 'http://www.tiscali.it/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=IstellaBot'
              +			}
              +		},
              +		'8061': {
              +			userAgent: 'Pixray-Seeker/2.0 (http://www.pixray.com/pixraybot; crawler@pixray.com)',
              +			metadata: {
              +				uaFamily: 'Pixray-Seeker',
              +				uaName: 'Pixray-Seeker/2.0',
              +				uaUrl: 'http://www.pixray.com/pixraybot',
              +				uaCompany: 'PIXRAY GmbH.',
              +				uaCompanyUrl: 'http://www.pixray.com/',
              +				uaIcon: 'bot_PixraySeeker.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Pixray-Seeker'
              +			}
              +		},
              +		'8066': {
              +			userAgent: 'Mozilla/5.0 (compatible; SearchmetricsBot; http://www.searchmetrics.com/en/searchmetrics-bot/)',
              +			metadata: {
              +				uaFamily: 'SearchmetricsBot',
              +				uaName: 'SearchmetricsBot',
              +				uaUrl: 'http://www.searchmetrics.com/en/searchmetrics-bot/',
              +				uaCompany: 'Searchmetrics GmbH',
              +				uaCompanyUrl: 'http://www.searchmetrics.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SearchmetricsBot'
              +			}
              +		},
              +		'8083': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Linux 3.2.0-3-amd64; java 1.6.0_24; Europe/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'8096': {
              +			userAgent: 'Mozilla/5.0 (compatible; Genieo/1.0 http://www.genieo.com/webfilter.html)',
              +			metadata: {
              +				uaFamily: 'Genieo Web filter',
              +				uaName: 'Genieo/1.0',
              +				uaUrl: 'http://www.genieo.com/webfilter.html',
              +				uaCompany: 'Genieo',
              +				uaCompanyUrl: 'http://www.genieo.com',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Genieo Web filter'
              +			}
              +		},
              +		'8107': {
              +			userAgent: 'yacybot (freeworld/global; i386 Linux 2.6.32-5-686; java 1.6.0_18; Europe/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'8114': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Windows 7 6.1; java 1.6.0_23; Europe/de) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'8131': {
              +			userAgent: 'facebookplatform/1.0 (+http://developers.facebook.com)',
              +			metadata: {
              +				uaFamily: 'facebookplatform',
              +				uaName: 'facebookplatform/1.0',
              +				uaUrl: 'http://en.wikipedia.org/wiki/Facebook_Platform',
              +				uaCompany: 'Facebook',
              +				uaCompanyUrl: 'http://www.facebook.com/',
              +				uaIcon: 'bot_facebook.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=facebookplatform'
              +			}
              +		},
              +		'8134': {
              +			userAgent: 'Mozilla/5.0 (compatible; Infohelfer/1.3.3; +http://www.infohelfer.de/crawler.php)',
              +			metadata: {
              +				uaFamily: 'Infohelfer',
              +				uaName: 'Infohelfer/1.3.3',
              +				uaUrl: 'http://www.infohelfer.de/crawler.php',
              +				uaCompany: 'ITam GmbH',
              +				uaCompanyUrl: 'http://www.itam-gmbh.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Infohelfer'
              +			}
              +		},
              +		'8138': {
              +			userAgent: 'Mozilla/5.0 (compatible; HomeTags/1.0;  http://www.hometags.nl/bot)',
              +			metadata: {
              +				uaFamily: 'HomeTags',
              +				uaName: 'HomeTags/1.0',
              +				uaUrl: 'http://www.hometags.nl/bot',
              +				uaCompany: 'HomeTags.nl',
              +				uaCompanyUrl: 'http://www.hometags.nl/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=HomeTags'
              +			}
              +		},
              +		'8170': {
              +			userAgent: 'Mozilla/5.0 (compatible; Qseero; +http://www.q0.com)',
              +			metadata: {
              +				uaFamily: 'Qseero',
              +				uaName: 'Qseero',
              +				uaUrl: '',
              +				uaCompany: 'Qseero, Inc.',
              +				uaCompanyUrl: 'http://q0.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Qseero'
              +			}
              +		},
              +		'8179': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Linux 3.2.0-32-generic; java 1.6.0_24; Europe/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'8184': {
              +			userAgent: 'Mozilla/5.0 (compatible; Esribot/1.0; http://www.esrihu.hu/)',
              +			metadata: {
              +				uaFamily: 'Esribot',
              +				uaName: 'Esribot/1.0',
              +				uaUrl: '',
              +				uaCompany: 'ESRI Magyarorsz\xe1g Kft.',
              +				uaCompanyUrl: 'http://www.esrihu.hu/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Esribot'
              +			}
              +		},
              +		'8191': {
              +			userAgent: 'wscheck.com/1.0.0 (+http://wscheck.com/)',
              +			metadata: {
              +				uaFamily: 'wscheck.com',
              +				uaName: 'wscheck.com/1.0.0',
              +				uaUrl: '',
              +				uaCompany: 'AsiaWS',
              +				uaCompanyUrl: 'http://asiaws.net/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=wscheck.com'
              +			}
              +		},
              +		'8192': {
              +			userAgent: 'bot.wsowner.com/1.0.0 (+http://wsowner.com/)',
              +			metadata: {
              +				uaFamily: 'bot.wsowner.com',
              +				uaName: 'bot.wsowner.com/1.0.0',
              +				uaUrl: '',
              +				uaCompany: 'AsiaWS',
              +				uaCompanyUrl: 'http://asiaws.net/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=bot.wsowner.com'
              +			}
              +		},
              +		'8208': {
              +			userAgent: 'Yepi/1.0 (NHN Corp.; http://help.naver.com/robots/)',
              +			metadata: {
              +				uaFamily: 'NaverBot',
              +				uaName: 'Yepi/1.0',
              +				uaUrl: 'http://help.naver.com/robots/',
              +				uaCompany: 'NHN Corporation',
              +				uaCompanyUrl: 'http://www.nhncorp.com/',
              +				uaIcon: 'bot_NaverBot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=NaverBot'
              +			}
              +		},
              +		'8247': {
              +			userAgent: 'Mozilla/5.0 (compatible; Mail.RU_Bot/2.0; +http://go.mail.ru/help/robots)',
              +			metadata: {
              +				uaFamily: 'Mail.Ru bot',
              +				uaName: 'Mail.RU_Bot/2.0',
              +				uaUrl: 'http://go.mail.ru/help/robots',
              +				uaCompany: 'Mail.Ru Group',
              +				uaCompanyUrl: 'http://corp.mail.ru/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Mail.Ru bot'
              +			}
              +		},
              +		'8297': {
              +			userAgent: 'yacybot (freeworld-global; amd64 Linux 3.2.0-4-amd64; java 1.6.0_24; Europe/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'8300': {
              +			userAgent: 'Mozilla/5.0 (compatible; emefgebot/beta; +http://emefge.de/bot.html)',
              +			metadata: {
              +				uaFamily: 'emefgebot',
              +				uaName: 'emefgebot/beta',
              +				uaUrl: 'http://emefge.de/bot.html',
              +				uaCompany: 'Bayern Anzeiger UG',
              +				uaCompanyUrl: 'http://bayernanzeiger.de/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=emefgebot'
              +			}
              +		},
              +		'8318': {
              +			userAgent: 'Mozilla/5.0 (compatible; YioopBot; +http://173.13.143.74/bot.php)',
              +			metadata: {
              +				uaFamily: 'YioopBot',
              +				uaName: 'YioopBot',
              +				uaUrl: 'http://www.yioop.com/bot.php',
              +				uaCompany: 'Chris Pollett',
              +				uaCompanyUrl: 'http://pollett.org/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=YioopBot'
              +			}
              +		},
              +		'8329': {
              +			userAgent: 'Sogou web spider/4.0',
              +			metadata: {
              +				uaFamily: 'sogou spider',
              +				uaName: 'Sogou web spider/4.0',
              +				uaUrl: 'http://www.sogou.com/docs/help/webmasters.htm#07',
              +				uaCompany: 'SOGOU.COM',
              +				uaCompanyUrl: 'http://www.sogou.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=sogou spider'
              +			}
              +		},
              +		'8397': {
              +			userAgent: 'Y!J-BRJ/YATS crawler (http://help.yahoo.co.jp/help/jp/search/indexing/indexing-15.html)',
              +			metadata: {
              +				uaFamily: 'Yahoo! JAPAN',
              +				uaName: 'Y!J-BRJ/YATS',
              +				uaUrl: 'http://help.yahoo.co.jp/help/jp/search/indexing/indexing-15.html',
              +				uaCompany: 'Yahoo Japan Corporation',
              +				uaCompanyUrl: 'http://www.yahoo.co.jp/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Yahoo! JAPAN'
              +			}
              +		},
              +		'8406': {
              +			userAgent: 'yacybot (freeworld-global; amd64 Linux 3.2.0-35-generic; java 1.7.0_09; Europe/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'8429': {
              +			userAgent: 'OpenWebSpider v0.1.4 (http://www.openwebspider.org/)',
              +			metadata: {
              +				uaFamily: 'OpenWebSpider',
              +				uaName: 'OpenWebSpider v0.1.4',
              +				uaUrl: 'http://www.openwebspider.org/',
              +				uaCompany: 'Stefano Alimonti',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=OpenWebSpider'
              +			}
              +		},
              +		'8487': {
              +			userAgent: 'emefgebot/beta (+http://emefge.de/bot.html)',
              +			metadata: {
              +				uaFamily: 'emefgebot',
              +				uaName: 'emefgebot/beta',
              +				uaUrl: 'http://emefge.de/bot.html',
              +				uaCompany: 'Bayern Anzeiger UG',
              +				uaCompanyUrl: 'http://bayernanzeiger.de/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=emefgebot'
              +			}
              +		},
              +		'8574': {
              +			userAgent: 'coccoc/1.0 (http://help.coccoc.com/)',
              +			metadata: {
              +				uaFamily: 'coccoc',
              +				uaName: 'coccoc/1.0',
              +				uaUrl: 'http://help.coccoc.com/',
              +				uaCompany: 'Coc Coc',
              +				uaCompanyUrl: 'http://coccoc.vn/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=coccoc'
              +			}
              +		},
              +		'8586': {
              +			userAgent: 'ExB Language Crawler 2.1.5 (+http://www.exb.de/crawler)',
              +			metadata: {
              +				uaFamily: 'ExB Language Crawler',
              +				uaName: 'ExB Language Crawler 2.1.5',
              +				uaUrl: 'http://www.exb.de/crawler/',
              +				uaCompany: 'ExB Communication Systems GmbH',
              +				uaCompanyUrl: 'http://www.exb.de/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ExB Language Crawler'
              +			}
              +		},
              +		'8590': {
              +			userAgent: 'Mozilla/4.0 (compatible;  Vagabondo/4.0; webcrawler at wise-guys dot nl; http://webagent.wise-guys.nl/; http://www.wise-guys.nl/)',
              +			metadata: {
              +				uaFamily: 'Vagabondo',
              +				uaName: 'Vagabondo/4.0',
              +				uaUrl: 'http://webagent.wise-guys.nl/',
              +				uaCompany: 'WiseGuys Internet BV',
              +				uaCompanyUrl: 'http://www.wise-guys.nl/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Vagabondo'
              +			}
              +		},
              +		'8607': {
              +			userAgent: 'ExB Language Crawler 2.1.2 (+http://www.exb.de/crawler)',
              +			metadata: {
              +				uaFamily: 'ExB Language Crawler',
              +				uaName: 'ExB Language Crawler 2.1.2',
              +				uaUrl: 'http://www.exb.de/crawler/',
              +				uaCompany: 'ExB Communication Systems GmbH',
              +				uaCompanyUrl: 'http://www.exb.de/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ExB Language Crawler'
              +			}
              +		},
              +		'8694': {
              +			userAgent: 'Mozilla/5.0 (compatible; special_archiver/3.1.1 +http://www.archive.org/details/archive.org_bot)',
              +			metadata: {
              +				uaFamily: 'archive.org_bot',
              +				uaName: 'special_archiver/3.1.1',
              +				uaUrl: 'http://www.archive.org/details/archive.org_bot',
              +				uaCompany: 'Internet Archive',
              +				uaCompanyUrl: 'http://www.archive.org/',
              +				uaIcon: 'bot_heritrix.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=archive.org_bot'
              +			}
              +		},
              +		'8743': {
              +			userAgent: 'Mozilla/5.0 (compatible; NLNZ_IAHarvester2013 +http://natlib.govt.nz/about-us/current-initiatives/web-harvest-2013)',
              +			metadata: {
              +				uaFamily: 'NLNZ_IAHarvester2013',
              +				uaName: 'NLNZ_IAHarvester2013',
              +				uaUrl: 'http://natlib.govt.nz/publishers-and-authors/web-harvesting/2013-nz-web-harvest',
              +				uaCompany: 'National Library of New Zealand',
              +				uaCompanyUrl: 'http://natlib.govt.nz/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=NLNZ_IAHarvester2013'
              +			}
              +		},
              +		'8833': {
              +			userAgent: 'Zookabot/2.5;++http://zookabot.com',
              +			metadata: {
              +				uaFamily: 'Zookabot',
              +				uaName: 'Zookabot/2.5',
              +				uaUrl: 'http://zookabot.com/',
              +				uaCompany: 'Hwacha ApS',
              +				uaCompanyUrl: 'http://hwacha.dk/',
              +				uaIcon: 'bot_Zookabot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Zookabot'
              +			}
              +		},
              +		'8866': {
              +			userAgent: 'Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm) SitemapProbe',
              +			metadata: {
              +				uaFamily: 'bingbot',
              +				uaName: 'bingbot SitemapProbe',
              +				uaUrl: 'http://www.bing.com/webmaster/help/which-crawlers-does-bing-use-8c184ec0',
              +				uaCompany: 'Microsoft Corporation',
              +				uaCompanyUrl: 'http://www.microsoft.com/',
              +				uaIcon: 'bot_msnbot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=bingbot'
              +			}
              +		},
              +		'8902': {
              +			userAgent: 'Mozilla/5.0 (compatible; ZumBot/1.0; http://help.zum.com/inquiry)',
              +			metadata: {
              +				uaFamily: 'ZumBot',
              +				uaName: 'ZumBot/1.0',
              +				uaUrl: 'http://help.zum.com/inquiry',
              +				uaCompany: 'ZUMinternet Corp',
              +				uaCompanyUrl: 'http://www.zuminternet.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ZumBot'
              +			}
              +		},
              +		'9010': {
              +			userAgent: 'Mozilla/5.0 (compatible; 4SeoHuntBot; +http://4seohunt.biz/about.html)',
              +			metadata: {
              +				uaFamily: '4seohuntBot',
              +				uaName: '4seohuntBot',
              +				uaUrl: 'http://4seohunt.biz/about.html',
              +				uaCompany: '4seohunt.biz',
              +				uaCompanyUrl: 'http://4seohunt.biz/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=4seohuntBot'
              +			}
              +		},
              +		'9020': {
              +			userAgent: 'fastbot crawler beta 2.0 (+http://www.fastbot.de)',
              +			metadata: {
              +				uaFamily: 'fastbot crawler',
              +				uaName: 'fastbot crawler beta 2.0',
              +				uaUrl: 'http://www.fastbot.de/',
              +				uaCompany: 'http://www.pagedesign.de/',
              +				uaCompanyUrl: 'Pagedesign GmbH',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=fastbot crawler'
              +			}
              +		},
              +		'9065': {
              +			userAgent: 'fastbot.de crawler 2.0 beta (http://www.fastbot.de)',
              +			metadata: {
              +				uaFamily: 'fastbot crawler',
              +				uaName: 'fastbot.de crawler beta 2.0',
              +				uaUrl: 'http://www.fastbot.de/',
              +				uaCompany: 'http://www.pagedesign.de/',
              +				uaCompanyUrl: 'Pagedesign GmbH',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=fastbot crawler'
              +			}
              +		},
              +		'9116': {
              +			userAgent: 'Mozilla/5.0+(compatible;+PiplBot;++http://www.pipl.com/bot/)',
              +			metadata: {
              +				uaFamily: 'PiplBot',
              +				uaName: 'PiplBot',
              +				uaUrl: 'http://pipl.com/bot/',
              +				uaCompany: 'pipl.com',
              +				uaCompanyUrl: 'http://pipl.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=PiplBot'
              +			}
              +		},
              +		'9165': {
              +			userAgent: 'rogerbot/1.0 (http://www.seomoz.org/dp/rogerbot, rogerbot-crawler+shiny@seomoz.org)',
              +			metadata: {
              +				uaFamily: 'rogerbot',
              +				uaName: 'rogerbot/1.0',
              +				uaUrl: 'http://moz.com/help/pro/what-is-rogerbot-',
              +				uaCompany: 'SEOmoz, Inc.',
              +				uaCompanyUrl: 'http://moz.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=rogerbot'
              +			}
              +		},
              +		'9239': {
              +			userAgent: 'Grahambot/0.1 (+http://www.sunaga-lab.com/graham-bot)',
              +			metadata: {
              +				uaFamily: 'Grahambot',
              +				uaName: 'Grahambot/0.1',
              +				uaUrl: 'http://www.sunaga-lab.com/graham-bot',
              +				uaCompany: 'Sunagarabo',
              +				uaCompanyUrl: 'http://sunagae.net/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Grahambot'
              +			}
              +		},
              +		'9240': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Linux 3.5.0-27-generic; java 1.7.0_03; Europe/de) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'9262': {
              +			userAgent: 'SolomonoBot/1.04 (http://www.solomono.ru)',
              +			metadata: {
              +				uaFamily: 'SolomonoBot',
              +				uaName: 'SolomonoBot/1.04',
              +				uaUrl: 'http://solomono.ru/about/',
              +				uaCompany: 'Solomono',
              +				uaCompanyUrl: 'http://solomono.ru/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SolomonoBot'
              +			}
              +		},
              +		'9280': {
              +			userAgent: 'Mozilla/5.0 (compatible; SemrushBot/0.96.2; +http://www.semrush.com/bot.html)',
              +			metadata: {
              +				uaFamily: 'SemrushBot',
              +				uaName: 'SemrushBot/0.96.2',
              +				uaUrl: 'http://www.semrush.com/bot.html',
              +				uaCompany: 'SEOQuake Team',
              +				uaCompanyUrl: 'http://www.seoquaketeam.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SemrushBot'
              +			}
              +		},
              +		'9288': {
              +			userAgent: 'bl.uk_lddc_bot/3.1.1 (+http://www.bl.uk/aboutus/legaldeposit/websites/websites/faqswebmaster/index.html)',
              +			metadata: {
              +				uaFamily: 'bl.uk_lddc_bot',
              +				uaName: 'bl.uk_lddc_bot/3.1.1',
              +				uaUrl: 'http://www.bl.uk/aboutus/legaldeposit/websites/websites/faqswebmaster/index.html',
              +				uaCompany: 'British Library',
              +				uaCompanyUrl: 'http://www.bl.uk/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=bl.uk_lddc_bot'
              +			}
              +		},
              +		'9298': {
              +			userAgent: 'Mozilla/5.0 (Windows NT 6.1; rv:6.0) Gecko/20110814 Firefox/6.0 Google (+https://developers.google.com/+/web/snippet/)',
              +			metadata: {
              +				uaFamily: 'Googlebot',
              +				uaName: 'Googlebot snippet',
              +				uaUrl: 'https://developers.google.com/+/web/snippet/',
              +				uaCompany: 'Google Inc.',
              +				uaCompanyUrl: 'http://www.google.com/',
              +				uaIcon: 'bot_googlebot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Googlebot'
              +			}
              +		},
              +		'9332': {
              +			userAgent: 'BacklinkCrawler V (http://www.backlinktest.com/crawler.html)',
              +			metadata: {
              +				uaFamily: 'BacklinkCrawler',
              +				uaName: 'BacklinkCrawler V',
              +				uaUrl: 'http://www.backlinktest.com/crawler.html',
              +				uaCompany: '2.0Promotion GbR',
              +				uaCompanyUrl: 'http://2.0promotion.de/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=BacklinkCrawler'
              +			}
              +		},
              +		'9346': {
              +			userAgent: 'Automattic Analytics Crawler/0.1; http://wordpress.com/crawler/',
              +			metadata: {
              +				uaFamily: 'Automattic Analytics Crawler',
              +				uaName: 'Automattic Analytics Crawler/0.1',
              +				uaUrl: 'http://wordpress.com/crawler/',
              +				uaCompany: 'Automattic Inc.',
              +				uaCompanyUrl: 'http://automattic.com/',
              +				uaIcon: 'AutomatticCrawler.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Automattic Analytics Crawler'
              +			}
              +		},
              +		'9389': {
              +			userAgent: 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.6 Ara.com.tr AraBot 1.0',
              +			metadata: {
              +				uaFamily: 'AraBot',
              +				uaName: 'AraBot 1.0',
              +				uaUrl: '',
              +				uaCompany: ' ARA ?leti\u015fim Telekom\xfcnikasyon ?nternet Al?\u015fveri\u015f Reklam Tic. Ltd. \u015eti.',
              +				uaCompanyUrl: 'http://www.ara.com.tr/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=AraBot'
              +			}
              +		},
              +		'9410': {
              +			userAgent: 'Aboundex/0.3 (http://www.aboundex.com/crawler/)',
              +			metadata: {
              +				uaFamily: 'Aboundexbot',
              +				uaName: 'Aboundexbot/0.3',
              +				uaUrl: 'http://www.aboundex.com/crawler/',
              +				uaCompany: 'Aboundex.com',
              +				uaCompanyUrl: 'http://www.aboundex.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Aboundexbot'
              +			}
              +		},
              +		'9427': {
              +			userAgent: 'Peeplo Screenshot Bot/0.20 ( abuse at peeplo dot_com )',
              +			metadata: {
              +				uaFamily: 'Peeplo Screenshot Bot',
              +				uaName: 'Peeplo Screenshot Bot/0.20',
              +				uaUrl: '',
              +				uaCompany: 'MOQU ADV Srl',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Peeplo Screenshot Bot'
              +			}
              +		},
              +		'9453': {
              +			userAgent: 'CCBot/2.0',
              +			metadata: {
              +				uaFamily: 'CCBot',
              +				uaName: 'CCBot/2.0',
              +				uaUrl: 'http://commoncrawl.org/research/',
              +				uaCompany: 'CommonCrawl Foundation',
              +				uaCompanyUrl: 'http://www.commoncrawl.org/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=CCBot'
              +			}
              +		},
              +		'9455': {
              +			userAgent: 'Mozilla/5.0 (compatible; ProCogSEOBot/1.0; +http://www.procog.com/ )',
              +			metadata: {
              +				uaFamily: 'ProCogSEOBot',
              +				uaName: 'ProCogSEOBot/1.0',
              +				uaUrl: '',
              +				uaCompany: 'ProCog.com',
              +				uaCompanyUrl: 'http://www.procog.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ProCogSEOBot'
              +			}
              +		},
              +		'9540': {
              +			userAgent: 'MetaURI API/2.0 +metauri.com',
              +			metadata: {
              +				uaFamily: 'MetaURI API',
              +				uaName: 'MetaURI API/2.0',
              +				uaUrl: '',
              +				uaCompany: 'stateless systems',
              +				uaCompanyUrl: 'http://statelesssystems.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MetaURI API'
              +			}
              +		},
              +		'9577': {
              +			userAgent: 'Dlvr.it/1.0 (http://dlvr.it/)',
              +			metadata: {
              +				uaFamily: 'Dlvr.it/1.0',
              +				uaName: 'Dlvr.it/1.0',
              +				uaUrl: 'http://support.dlvr.it/entries/23499527-How-do-I-block-dlvr-it-from-retrieving-the-feeds-on-my-site-',
              +				uaCompany: 'dlvr.it',
              +				uaCompanyUrl: 'http://dlvr.it/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Dlvr.it/1.0'
              +			}
              +		},
              +		'9652': {
              +			userAgent: 'Mozilla/5.0 (compatible; GeliyooBot/1.0; +http://www.geliyoo.com/)',
              +			metadata: {
              +				uaFamily: 'GeliyooBot',
              +				uaName: 'GeliyooBot/1.0',
              +				uaUrl: '',
              +				uaCompany: 'Geliyoo Bili\u015fim Ar-Ge Tic. Ltd. \u015eti.',
              +				uaCompanyUrl: 'http://www.geliyoobilisim.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=GeliyooBot'
              +			}
              +		},
              +		'9653': {
              +			userAgent: 'ExB Language Crawler 2.1.1 (+http://www.exb.de/crawler)',
              +			metadata: {
              +				uaFamily: 'ExB Language Crawler',
              +				uaName: 'ExB Language Crawler 2.1.1',
              +				uaUrl: 'http://www.exb.de/crawler/',
              +				uaCompany: 'ExB Communication Systems GmbH',
              +				uaCompanyUrl: 'http://www.exb.de/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ExB Language Crawler'
              +			}
              +		},
              +		'9655': {
              +			userAgent: 'Mozilla/5.0 (compatible; 200PleaseBot/1.0; +http://www.200please.com/bot)',
              +			metadata: {
              +				uaFamily: '200PleaseBot',
              +				uaName: '200PleaseBot/1.0',
              +				uaUrl: 'http://www.200please.com/bot',
              +				uaCompany: '200please.com',
              +				uaCompanyUrl: 'http://www.200please.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=200PleaseBot'
              +			}
              +		},
              +		'9673': {
              +			userAgent: 'yacybot (webportal-global; amd64 Windows 7 6.1; java 1.7.0_04; America/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'9675': {
              +			userAgent: 'Mozilla/5.0 (compatible; Linux x86_64; Mail.RU_Bot/2.0; +http://go.mail.ru/help/robots)',
              +			metadata: {
              +				uaFamily: 'Mail.Ru bot',
              +				uaName: 'Mail.RU_Bot/2.0',
              +				uaUrl: 'http://go.mail.ru/help/robots',
              +				uaCompany: 'Mail.Ru Group',
              +				uaCompanyUrl: 'http://corp.mail.ru/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Mail.Ru bot'
              +			}
              +		},
              +		'9681': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Linux 3.2.0-4-amd64; java 1.6.0_27; Europe/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'9682': {
              +			userAgent: 'yacybot (freeworld/global; i386 Linux 3.4.2-linode44; java 1.6.0_27; America/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'9691': {
              +			userAgent: 'Mozilla/5.0 (compatible; GeliyooBot/1.0beta; +http://www.geliyoo.com/)',
              +			metadata: {
              +				uaFamily: 'GeliyooBot',
              +				uaName: 'GeliyooBot/1.0beta',
              +				uaUrl: '',
              +				uaCompany: 'Geliyoo Bili\u015fim Ar-Ge Tic. Ltd. \u015eti.',
              +				uaCompanyUrl: 'http://www.geliyoobilisim.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=GeliyooBot'
              +			}
              +		},
              +		'9694': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Linux 3.8.0-21-generic; java 1.6.0_27; Pacific/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'9717': {
              +			userAgent: 'Sogou web spider/4.0l-2m!',
              +			metadata: {
              +				uaFamily: 'sogou spider',
              +				uaName: 'Sogou web spider/4.0l-2m!',
              +				uaUrl: 'http://www.sogou.com/docs/help/webmasters.htm#07',
              +				uaCompany: 'SOGOU.COM',
              +				uaCompanyUrl: 'http://www.sogou.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=sogou spider'
              +			}
              +		},
              +		'9737': {
              +			userAgent: 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.4 (KHTML, like Gecko; Google Web Preview) Chrome/22.0.1229 Safari/537.4',
              +			metadata: {
              +				uaFamily: 'Googlebot',
              +				uaName: 'Google Web Preview',
              +				uaUrl: 'http://support.google.com/webmasters/bin/answer.py?hl=en&answer=1062498',
              +				uaCompany: 'Google Inc.',
              +				uaCompanyUrl: 'http://www.google.com/',
              +				uaIcon: 'bot_googlebot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Googlebot'
              +			}
              +		},
              +		'9781': {
              +			userAgent: 'Mozilla/5.0 (compatible; uMBot-FC/1.0; mailto: crawling@ubermetrics-technologies.com)',
              +			metadata: {
              +				uaFamily: 'uMBot',
              +				uaName: 'uMBot-FC/1.0',
              +				uaUrl: '',
              +				uaCompany: 'uberMetrics Technologies GmbH',
              +				uaCompanyUrl: 'http://www.ubermetrics-technologies.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=uMBot'
              +			}
              +		},
              +		'9784': {
              +			userAgent: 'Mozilla/5.0 (compatible; coccoc/1.0; +http://help.coccoc.com/)',
              +			metadata: {
              +				uaFamily: 'coccoc',
              +				uaName: 'coccoc/1.0',
              +				uaUrl: 'http://help.coccoc.com/',
              +				uaCompany: 'Coc Coc',
              +				uaCompanyUrl: 'http://coccoc.vn/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=coccoc'
              +			}
              +		},
              +		'9832': {
              +			userAgent: 'Mozilla/5.0 (compatible; Mozilla; +http://wiki.github.com/bixo/bixo/bixocrawler; bixo-dev@yahoogroups.com)',
              +			metadata: {
              +				uaFamily: 'bixocrawler',
              +				uaName: 'bixocrawler',
              +				uaUrl: 'http://wiki.github.com/bixo/bixo/bixocrawler',
              +				uaCompany: 'Bixo Labs',
              +				uaCompanyUrl: 'http://openbixo.org/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=bixocrawler'
              +			}
              +		},
              +		'9839': {
              +			userAgent: 'Mozilla/5.0 (compatible; aiHitBot/2.7; +http://www.aihit.com/)',
              +			metadata: {
              +				uaFamily: 'aiHitBot',
              +				uaName: 'aiHitBot/2.7',
              +				uaUrl: '',
              +				uaCompany: 'aiHit Ltd',
              +				uaCompanyUrl: 'http://aihit.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=aiHitBot'
              +			}
              +		},
              +		'9852': {
              +			userAgent: 'Mozilla/5.0 (compatible; GigaBot/1.0; +http://www.gigablast.com/ )',
              +			metadata: {
              +				uaFamily: 'Gigabot',
              +				uaName: 'Gigabot/1.0',
              +				uaUrl: 'http://www.gigablast.com/spider.html',
              +				uaCompany: 'Gigablast Inc',
              +				uaCompanyUrl: 'http://www.gigablast.com/',
              +				uaIcon: 'bot_gigabot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Gigabot'
              +			}
              +		},
              +		'9868': {
              +			userAgent: 'CirrusExplorer/1.1 (http://www.cireu.com/explorer.php)',
              +			metadata: {
              +				uaFamily: 'CirrusExplorer',
              +				uaName: 'CirrusExplorer/1.1',
              +				uaUrl: 'http://www.cireu.com/explorer.php',
              +				uaCompany: 'cireu.com',
              +				uaCompanyUrl: 'http://www.cireu.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=CirrusExplorer'
              +			}
              +		},
              +		'9874': {
              +			userAgent: 'Mozilla/5.0 (compatible; uMBot-LN/1.0; mailto: crawling@ubermetrics-technologies.com)',
              +			metadata: {
              +				uaFamily: 'uMBot',
              +				uaName: 'uMBot-LN/1.0',
              +				uaUrl: '',
              +				uaCompany: 'uberMetrics Technologies GmbH',
              +				uaCompanyUrl: 'http://www.ubermetrics-technologies.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=uMBot'
              +			}
              +		},
              +		'9875': {
              +			userAgent: 'Crowsnest/0.5 (+http://www.crowsnest.tv/)',
              +			metadata: {
              +				uaFamily: 'Crowsnest',
              +				uaName: 'Crowsnest/0.5',
              +				uaUrl: '',
              +				uaCompany: 'Gocro, Inc.',
              +				uaCompanyUrl: 'http://www.gocro.jp/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Crowsnest'
              +			}
              +		},
              +		'9877': {
              +			userAgent: 'QuerySeekerSpider ( http://queryseeker.com/bot.html )',
              +			metadata: {
              +				uaFamily: 'QuerySeekerSpider',
              +				uaName: 'QuerySeekerSpider',
              +				uaUrl: 'http://queryseeker.com/bot.html',
              +				uaCompany: 'QueryEye Inc.',
              +				uaCompanyUrl: 'http://queryeye.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=QuerySeekerSpider'
              +			}
              +		},
              +		'9905': {
              +			userAgent: 'ownCloud Server Crawler',
              +			metadata: {
              +				uaFamily: 'ownCloud Server Crawler',
              +				uaName: 'ownCloud Server Crawler',
              +				uaUrl: '',
              +				uaCompany: 'ownCloud comunity',
              +				uaCompanyUrl: 'http://owncloud.org/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ownCloud Server Crawler'
              +			}
              +		},
              +		'9918': {
              +			userAgent: 'Mozilla/5.0 (compatible; rogerBot/1.0; UrlCrawler; http://www.seomoz.org/dp/rogerbot)',
              +			metadata: {
              +				uaFamily: 'rogerbot',
              +				uaName: 'rogerbot/1.0',
              +				uaUrl: 'http://moz.com/help/pro/what-is-rogerbot-',
              +				uaCompany: 'SEOmoz, Inc.',
              +				uaCompanyUrl: 'http://moz.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=rogerbot'
              +			}
              +		},
              +		'9925': {
              +			userAgent: 'Mozilla/5.0 (compatible; SemrushBot/0.96.3; +http://www.semrush.com/bot.html)',
              +			metadata: {
              +				uaFamily: 'SemrushBot',
              +				uaName: 'SemrushBot/0.96.3',
              +				uaUrl: 'http://www.semrush.com/bot.html',
              +				uaCompany: 'SEOQuake Team',
              +				uaCompanyUrl: 'http://www.seoquaketeam.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SemrushBot'
              +			}
              +		},
              +		'9949': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Linux 3.8.0-23-generic; java 1.6.0_27; Pacific/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'10008': {
              +			userAgent: 'BLEXBot',
              +			metadata: {
              +				uaFamily: 'BLEXBot',
              +				uaName: 'BLEXBot',
              +				uaUrl: 'http://webmeup-crawler.com/',
              +				uaCompany: 'WebMeUp',
              +				uaCompanyUrl: 'http://webmeup.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=BLEXBot'
              +			}
              +		},
              +		'10035': {
              +			userAgent: 'Mozilla/5.0 (compatible; CloudServerMarketSpider/1.0; +http://www.cloudservermarket.com/spider.html)',
              +			metadata: {
              +				uaFamily: 'CloudServerMarketSpider',
              +				uaName: 'CloudServerMarketSpider/1.0',
              +				uaUrl: 'http://www.cloudservermarket.com/spider.html',
              +				uaCompany: 'CloudServerMarket.com',
              +				uaCompanyUrl: 'http://www.cloudservermarket.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=CloudServerMarketSpider'
              +			}
              +		},
              +		'10057': {
              +			userAgent: 'Mozilla/5.0 (compatible; BLEXBot/1.0; +http://webmeup.com/crawler.html)',
              +			metadata: {
              +				uaFamily: 'BLEXBot',
              +				uaName: 'BLEXBot/1.0',
              +				uaUrl: 'http://webmeup-crawler.com/',
              +				uaCompany: 'WebMeUp',
              +				uaCompanyUrl: 'http://webmeup.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=BLEXBot'
              +			}
              +		},
              +		'10073': {
              +			userAgent: 'Mozilla/5.0(compatible;Sosospider/2.0;+http://help.soso.com/webspider.htm)',
              +			metadata: {
              +				uaFamily: 'Sosospider',
              +				uaName: 'Sosospider/2.0',
              +				uaUrl: 'http://help.soso.com/webspider.htm',
              +				uaCompany: 'Tencent, Inc.',
              +				uaCompanyUrl: 'http://www.tencent.com/',
              +				uaIcon: 'bot_soso.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Sosospider'
              +			}
              +		},
              +		'10078': {
              +			userAgent: 'Mozilla/5.0 (compatible; firmilybot/0.3; +http://www.firmily.com/bot.php',
              +			metadata: {
              +				uaFamily: 'firmilybot',
              +				uaName: 'firmilybot/0.3',
              +				uaUrl: 'http://www.firmily.com/bot.php',
              +				uaCompany: 'Firmily',
              +				uaCompanyUrl: 'http://www.firmily.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=firmilybot'
              +			}
              +		},
              +		'10084': {
              +			userAgent: 'MetaHeadersBot (+http://www.metaheaders.com/bot.html)',
              +			metadata: {
              +				uaFamily: 'MetaHeadersBot',
              +				uaName: 'MetaHeadersBot',
              +				uaUrl: 'http://www.metaheaders.net/bot.html',
              +				uaCompany: 'metaheaders.net',
              +				uaCompanyUrl: 'http://www.metaheaders.net/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MetaHeadersBot'
              +			}
              +		},
              +		'10101': {
              +			userAgent: 'Mozilla/5.0 (compatible; meanpathbot/1.0; +http://www.meanpath.com/meanpathbot.html)',
              +			metadata: {
              +				uaFamily: 'meanpathbot',
              +				uaName: 'meanpathbot/1.0',
              +				uaUrl: 'http://www.meanpath.com/meanpathbot.html',
              +				uaCompany: 'meanpath, Inc.',
              +				uaCompanyUrl: 'https://meanpath.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=meanpathbot'
              +			}
              +		},
              +		'10107': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Windows 7 6.1; java 1.7.0_09; Europe/de) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'10108': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Windows XP 5.2; java 1.7.0_04; America/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'10126': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Linux 3.8.13-gentoo; java 1.7.0_21; Europe/de) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'10140': {
              +			userAgent: 'Mozilla/5.0 (compatible; AMZNKAssocBot/4.0 +http://affiliate-program.amazon.com)',
              +			metadata: {
              +				uaFamily: 'AMZNKAssocBot',
              +				uaName: 'AMZNKAssocBot/4.0',
              +				uaUrl: 'https://affiliate-program.amazon.com/gp/associates/help/t21/a14',
              +				uaCompany: 'Amazon.com, Inc.',
              +				uaCompanyUrl: 'http://www.amazon.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=AMZNKAssocBot'
              +			}
              +		},
              +		'10182': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Linux 2.6.32-49-server; java 1.6.0_27; Europe/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'10228': {
              +			userAgent: 'Mozilla/5.0 (compatible; AcoonBot/4.12.1; +http://www.acoon.de/robot.asp)',
              +			metadata: {
              +				uaFamily: 'AcoonBot',
              +				uaName: 'AcoonBot/4.12.1',
              +				uaUrl: 'http://www.acoon.de/robot.asp',
              +				uaCompany: 'Acoon GmbH',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_Acoon.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=AcoonBot'
              +			}
              +		},
              +		'10237': {
              +			userAgent: 'Mozilla/5.0 (compatible; linkdexbot/2.0; +http://www.linkdex.com/about/bots/)',
              +			metadata: {
              +				uaFamily: 'linkdexbot',
              +				uaName: 'linkdexbot/2.0',
              +				uaUrl: 'http://www.linkdex.com/about/bots/',
              +				uaCompany: 'Linkdex Limited.',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=linkdexbot'
              +			}
              +		},
              +		'10241': {
              +			userAgent: 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534+ (KHTML, like Gecko) BingPreview/1.0b',
              +			metadata: {
              +				uaFamily: 'BingPreview',
              +				uaName: 'BingPreview/1.0b',
              +				uaUrl: 'http://www.bing.com/blogs/site_blogs/b/webmaster/archive/2012/10/26/page-snapshots-in-bing-windows-8-app-to-bring-new-crawl-traffic-to-sites.aspx',
              +				uaCompany: 'Microsoft Corporation',
              +				uaCompanyUrl: 'http://www.microsoft.com/',
              +				uaIcon: 'bot_msnbot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=BingPreview'
              +			}
              +		},
              +		'10246': {
              +			userAgent: 'Mozilla/5.0 (compatible; AhrefsBot/5.0; +http://ahrefs.com/robot/)',
              +			metadata: {
              +				uaFamily: 'AhrefsBot',
              +				uaName: 'AhrefsBot/5.0',
              +				uaUrl: 'http://ahrefs.com/robot/',
              +				uaCompany: 'Ahrefs.com',
              +				uaCompanyUrl: 'http://ahrefs.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=AhrefsBot'
              +			}
              +		},
              +		'10293': {
              +			userAgent: 'Mozilla/5.0 (compatible; SeznamBot/3.1-test1; +http://fulltext.sblog.cz/)',
              +			metadata: {
              +				uaFamily: 'SeznamBot',
              +				uaName: 'SeznamBot/3.1-test',
              +				uaUrl: 'http://napoveda.seznam.cz/en/indexing-the-web.html',
              +				uaCompany: 'Seznam.cz, a.s.',
              +				uaCompanyUrl: 'http://www.seznam.cz/',
              +				uaIcon: 'seznam.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SeznamBot'
              +			}
              +		},
              +		'10301': {
              +			userAgent: 'yacybot (webportal-global; x86 Windows Vista 6.0; java 1.7.0_25; Europe/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'10308': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Windows 7 6.1; java 1.7.0_25; Europe/de) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'10342': {
              +			userAgent: 'SeoCheckBot (FischerNetzDesign Seo Checker, info@fischernetzdesign.de)',
              +			metadata: {
              +				uaFamily: 'SeoCheckBot',
              +				uaName: 'SeoCheckBot',
              +				uaUrl: 'http://www.kfsw.de/bot.html',
              +				uaCompany: 'Kristian Fischer',
              +				uaCompanyUrl: 'http://www.kfsw.de/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SeoCheckBot'
              +			}
              +		},
              +		'10349': {
              +			userAgent: 'Mozilla/5.0 (compatible; woriobot support [at] zite [dot] com +http://zite.com)',
              +			metadata: {
              +				uaFamily: 'woriobot',
              +				uaName: 'woriobot',
              +				uaUrl: '',
              +				uaCompany: 'Zite',
              +				uaCompanyUrl: 'http://zite.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=woriobot'
              +			}
              +		},
              +		'10356': {
              +			userAgent: 'SeoCheck (FischerNetzDesign Seo Checker, info@fischernetzdesign.de)',
              +			metadata: {
              +				uaFamily: 'SeoCheckBot',
              +				uaName: 'SeoCheck',
              +				uaUrl: 'http://www.kfsw.de/bot.html',
              +				uaCompany: 'Kristian Fischer',
              +				uaCompanyUrl: 'http://www.kfsw.de/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SeoCheckBot'
              +			}
              +		},
              +		'10374': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Linux 3.2.0-4-amd64; java 1.7.0_03; Etc/de) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'10444': {
              +			userAgent: 'Mozilla/5.0 (compatible; SemrushBot/0.96.4; +http://www.semrush.com/bot.html)',
              +			metadata: {
              +				uaFamily: 'SemrushBot',
              +				uaName: 'SemrushBot/0.96.4',
              +				uaUrl: 'http://www.semrush.com/bot.html',
              +				uaCompany: 'SEOQuake Team',
              +				uaCompanyUrl: 'http://www.seoquaketeam.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SemrushBot'
              +			}
              +		},
              +		'10448': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Windows NT (unknown) 6.2; java 1.7.0_05; Africa/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'10481': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Windows 7 6.1; java 1.7.0_04; Asia/ja) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'10498': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Windows Server 2008 R2 6.1; java 1.7.0_25; Europe/de) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'10503': {
              +			userAgent: 'ScreenerBot Crawler Beta 2.0 (+http://www.ScreenerBot.com)',
              +			metadata: {
              +				uaFamily: 'ScreenerBot Crawler',
              +				uaName: 'ScreenerBot Crawler Beta 2.0',
              +				uaUrl: 'http://www.screenerbot.com/',
              +				uaCompany: '',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=ScreenerBot Crawler'
              +			}
              +		},
              +		'10537': {
              +			userAgent: 'Mozilla/5.0 (compatible; Mozilla/5.0; +http://wiki.github.com/bixo/bixo/bixocrawler; bixo-dev@yahoogroups.com)',
              +			metadata: {
              +				uaFamily: 'bixocrawler',
              +				uaName: 'bixocrawler',
              +				uaUrl: 'http://wiki.github.com/bixo/bixo/bixocrawler',
              +				uaCompany: 'Bixo Labs',
              +				uaCompanyUrl: 'http://openbixo.org/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=bixocrawler'
              +			}
              +		},
              +		'10555': {
              +			userAgent: 'Semantifire1/0.20 ( http://www.setooz.com/oozbot.html ; agentname at setooz dot_com )',
              +			metadata: {
              +				uaFamily: 'Semantifire',
              +				uaName: 'Semantifire1/0.20',
              +				uaUrl: 'http://www.setooz.com/oozbot.html',
              +				uaCompany: 'SETU Software Systems (P) Ltd.',
              +				uaCompanyUrl: 'http://www.setusoftware.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Semantifire'
              +			}
              +		},
              +		'10562': {
              +			userAgent: 'Mozilla/5.0 (compatible; BIXOCRAWLER; +http://wiki.github.com/bixo/bixo/bixocrawler; bixo-dev@yahoogroups.com)',
              +			metadata: {
              +				uaFamily: 'bixocrawler',
              +				uaName: 'bixocrawler',
              +				uaUrl: 'http://wiki.github.com/bixo/bixo/bixocrawler',
              +				uaCompany: 'Bixo Labs',
              +				uaCompanyUrl: 'http://openbixo.org/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=bixocrawler'
              +			}
              +		},
              +		'10576': {
              +			userAgent: 'Mozilla/5.0 (compatible; socialbm_bot/1.0; +http://spider.socialbm.net)',
              +			metadata: {
              +				uaFamily: 'socialbm_bot',
              +				uaName: 'socialbm_bot/1.0',
              +				uaUrl: 'http://spider.socialbm.net/',
              +				uaCompany: 'Martin Junker - social-bookmarking.net',
              +				uaCompanyUrl: 'http://www.social-bookmarking.net/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=socialbm_bot'
              +			}
              +		},
              +		'10604': {
              +			userAgent: 'rogerbot/1.0 (http://moz.com/help/pro/what-is-rogerbot-, rogerbot-crawler+shiny@moz.com)',
              +			metadata: {
              +				uaFamily: 'rogerbot',
              +				uaName: 'rogerbot/1.0',
              +				uaUrl: 'http://moz.com/help/pro/what-is-rogerbot-',
              +				uaCompany: 'SEOmoz, Inc.',
              +				uaCompanyUrl: 'http://moz.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=rogerbot'
              +			}
              +		},
              +		'10615': {
              +			userAgent: 'CCResearchBot/1.0 commoncrawl.org/research//Nutch-1.7-SNAPSHOT',
              +			metadata: {
              +				uaFamily: 'CCResearchBot',
              +				uaName: 'CCResearchBot/1.0',
              +				uaUrl: 'http://commoncrawl.org/research/',
              +				uaCompany: 'CommonCrawl Foundation',
              +				uaCompanyUrl: 'http://www.commoncrawl.org/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=CCResearchBot'
              +			}
              +		},
              +		'10635': {
              +			userAgent: 'Mozilla/5.0 (compatible; MJ12bot/v1.4.4; http://www.majestic12.co.uk/bot.php?+)',
              +			metadata: {
              +				uaFamily: 'MJ12bot',
              +				uaName: 'MJ12bot/v1.4.4',
              +				uaUrl: 'http://majestic12.co.uk/bot.php',
              +				uaCompany: 'Majestic-12',
              +				uaCompanyUrl: 'http://www.majestic12.co.uk/',
              +				uaIcon: 'bot_mj12bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MJ12bot'
              +			}
              +		},
              +		'10658': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Linux 3.5.0-27-generic; java 1.7.0_25; Europe/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'10691': {
              +			userAgent: 'Mozilla/5.0 (compatible; SemrushBot/0.97; +http://www.semrush.com/bot.html)',
              +			metadata: {
              +				uaFamily: 'SemrushBot',
              +				uaName: 'SemrushBot/0.97',
              +				uaUrl: 'http://www.semrush.com/bot.html',
              +				uaCompany: 'SEOQuake Team',
              +				uaCompanyUrl: 'http://www.seoquaketeam.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SemrushBot'
              +			}
              +		},
              +		'10708': {
              +			userAgent: 'Mozilla/5.0 (compatible; spbot/4.0a; +http://www.seoprofiler.com/bot )',
              +			metadata: {
              +				uaFamily: 'spbot',
              +				uaName: 'spbot/4.0a',
              +				uaUrl: 'http://www.seoprofiler.com/bot/',
              +				uaCompany: 'Axandra GmbH',
              +				uaCompanyUrl: 'http://www.axandra.com/',
              +				uaIcon: 'bot_spbot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=spbot'
              +			}
              +		},
              +		'10822': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Windows 8 6.2; java 1.7.0_25; Europe/de) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'10823': {
              +			userAgent: 'Mozilla/5.0 (compatible; BLEXBot/1.0; +http://webmeup-crawler.com/)',
              +			metadata: {
              +				uaFamily: 'BLEXBot',
              +				uaName: 'BLEXBot/1.0',
              +				uaUrl: 'http://webmeup-crawler.com/',
              +				uaCompany: 'WebMeUp',
              +				uaCompanyUrl: 'http://webmeup.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=BLEXBot'
              +			}
              +		},
              +		'10847': {
              +			userAgent: 'Mozilla/5.0 (compatible; MojeekBot/0.5; http://www.mojeek.com/bot.html)',
              +			metadata: {
              +				uaFamily: 'MojeekBot',
              +				uaName: 'MojeekBot/0.5',
              +				uaUrl: 'http://www.mojeek.com/bot.html',
              +				uaCompany: 'Mojeek Ltd.',
              +				uaCompanyUrl: 'http://www.mojeek.com/',
              +				uaIcon: 'bot_MojeekBot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MojeekBot'
              +			}
              +		},
              +		'10913': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Linux 3.8.0-19-generic; java 1.7.0_25; Europe/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'10923': {
              +			userAgent: 'Cliqz Bot (+http://www.cliqz.com)',
              +			metadata: {
              +				uaFamily: 'CliqzBot',
              +				uaName: 'Cliqz Bot',
              +				uaUrl: '',
              +				uaCompany: '10betterpages GmbH',
              +				uaCompanyUrl: 'http://www.10betterpages.com/',
              +				uaIcon: 'bot_cliqzbot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=CliqzBot'
              +			}
              +		},
              +		'10990': {
              +			userAgent: 'KrOWLer/0.0.1, matentzn at cs dot man dot ac dot uk',
              +			metadata: {
              +				uaFamily: 'KrOWLer',
              +				uaName: 'KrOWLer/0.0.1',
              +				uaUrl: '',
              +				uaCompany: 'Nico Matentzoglu',
              +				uaCompanyUrl: 'http://nico.matentzoglu.net/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=KrOWLer'
              +			}
              +		},
              +		'11025': {
              +			userAgent: 'Cliqzbot/0.1 (+http://cliqz.com +cliqzbot@cliqz.com)',
              +			metadata: {
              +				uaFamily: 'Cliqzbot',
              +				uaName: 'Cliqzbot/0.1',
              +				uaUrl: '',
              +				uaCompany: '10betterpages GmbH',
              +				uaCompanyUrl: 'http://www.10betterpages.com/',
              +				uaIcon: 'bot_cliqzbot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Cliqzbot'
              +			}
              +		},
              +		'11039': {
              +			userAgent: 'Mozilla/4.0 (compatible;HostTracker/2.0;+http://www.host-tracker.com/)',
              +			metadata: {
              +				uaFamily: 'HostTracker',
              +				uaName: 'HostTracker/2.0',
              +				uaUrl: '',
              +				uaCompany: 'HostTracker, Ltd.',
              +				uaCompanyUrl: 'http://www.host-tracker.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=HostTracker'
              +			}
              +		},
              +		'11045': {
              +			userAgent: 'Mozilla/5.0 (compatible; linkdexbot/2.1; +http://www.linkdex.com/about/bots/)',
              +			metadata: {
              +				uaFamily: 'linkdexbot',
              +				uaName: 'linkdexbot/2.1',
              +				uaUrl: 'http://www.linkdex.com/about/bots/',
              +				uaCompany: 'Linkdex Limited.',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=linkdexbot'
              +			}
              +		},
              +		'11058': {
              +			userAgent: 'BUbiNG (+http://law.di.unimi.it/BUbiNG.html)',
              +			metadata: {
              +				uaFamily: 'BUbiNG',
              +				uaName: 'BUbiNG',
              +				uaUrl: 'http://law.di.unimi.it/BUbiNG.html',
              +				uaCompany: ' Universit\xe0 degli studi di Milano.',
              +				uaCompanyUrl: 'http://www.unimi.it/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=BUbiNG'
              +			}
              +		},
              +		'11068': {
              +			userAgent: 'Mozilla/5.0 (compatible; parsijoo; +http://www.parsijoo.ir/; ehsan.mousakazemi@gmail.com)',
              +			metadata: {
              +				uaFamily: 'parsijoo',
              +				uaName: 'parsijoo',
              +				uaUrl: '',
              +				uaCompany: ' Community Atmosphere',
              +				uaCompanyUrl: 'http://parsijoo.ir/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=parsijoo'
              +			}
              +		},
              +		'11079': {
              +			userAgent: 'Mozilla/5.0 (compatible; spbot/4.0b; +http://www.seoprofiler.com/bot )',
              +			metadata: {
              +				uaFamily: 'spbot',
              +				uaName: 'spbot/4.0b',
              +				uaUrl: 'http://www.seoprofiler.com/bot/',
              +				uaCompany: 'Axandra GmbH',
              +				uaCompanyUrl: 'http://www.axandra.com/',
              +				uaIcon: 'bot_spbot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=spbot'
              +			}
              +		},
              +		'11139': {
              +			userAgent: 'Speedy Spider (Submit your site at http://www.entireweb.com/free_submission/)',
              +			metadata: {
              +				uaFamily: 'Speedy',
              +				uaName: 'Speedy Spider',
              +				uaUrl: '',
              +				uaCompany: 'Entireweb Sweden AB',
              +				uaCompanyUrl: 'http://www.entireweb.com/',
              +				uaIcon: 'bot_Speedy.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Speedy'
              +			}
              +		},
              +		'11253': {
              +			userAgent: 'Mozilla/5.0 (compatible; alexa site audit/1.0; +http://www.alexa.com/help/webmasters; siteaudit@alexa.com)',
              +			metadata: {
              +				uaFamily: 'alexa site audit',
              +				uaName: 'alexa site audit/1.0',
              +				uaUrl: 'http://www.alexa.com/siteaudit',
              +				uaCompany: 'Alexa Internet, Inc.',
              +				uaCompanyUrl: 'http://www.alexa.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=alexa site audit'
              +			}
              +		},
              +		'11255': {
              +			userAgent: 'A6-Indexer/1.0 (http://www.a6corp.com/a6-web-scraping-policy/)',
              +			metadata: {
              +				uaFamily: 'A6-Indexer',
              +				uaName: 'A6-Indexer/1.0',
              +				uaUrl: 'http://www.a6corp.com/a6-web-scraping-policy/',
              +				uaCompany: 'A6 Corporation',
              +				uaCompanyUrl: 'http://www.a6corp.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=A6-Indexer'
              +			}
              +		},
              +		'11256': {
              +			userAgent: 'yacybot (freeworld/global; amd64 Linux 3.10.15-1-MANJARO; java 1.7.0_40; Asia/en) http://yacy.net/bot.html',
              +			metadata: {
              +				uaFamily: 'yacybot',
              +				uaName: 'yacybot',
              +				uaUrl: 'http://yacy.net/bot.html',
              +				uaCompany: 'Michael Christen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_yacybot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=yacybot'
              +			}
              +		},
              +		'11265': {
              +			userAgent: 'Mozilla/5.0 (Compatible; Vedma/0.91Beta; +http://www.vedma.ru/bot.htm)',
              +			metadata: {
              +				uaFamily: 'Vedma',
              +				uaName: 'Vedma/0.91Beta',
              +				uaUrl: 'http://www.vedma.ru/bot.htm',
              +				uaCompany: 'vedma.ru',
              +				uaCompanyUrl: 'http://www.vedma.ru/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Vedma'
              +			}
              +		},
              +		'11312': {
              +			userAgent: 'Mozilla/5.0 (compatible; WebThumbnail/3.x; Website Thumbnail Generator; +http://webthumbnail.org)',
              +			metadata: {
              +				uaFamily: 'WebThumbnail',
              +				uaName: 'WebThumbnail/3.x',
              +				uaUrl: '',
              +				uaCompany: 'hellworx - Lukasz Cepowski',
              +				uaCompanyUrl: 'http://www.hellworx.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=WebThumbnail'
              +			}
              +		},
              +		'11323': {
              +			userAgent: 'Mozilla/5.0 (compatible; archive.org_bot; Wayback Machine Live Record; +http://archive.org/details/archive.org_bot)',
              +			metadata: {
              +				uaFamily: 'archive.org_bot',
              +				uaName: 'archive.org_bot',
              +				uaUrl: 'http://www.archive.org/details/archive.org_bot',
              +				uaCompany: 'Internet Archive',
              +				uaCompanyUrl: 'http://www.archive.org/',
              +				uaIcon: 'bot_heritrix.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=archive.org_bot'
              +			}
              +		},
              +		'11331': {
              +			userAgent: 'SeoCheckBot (Seo-Check, http://www.kfsw.de/bot.html)',
              +			metadata: {
              +				uaFamily: 'SeoCheckBot',
              +				uaName: 'SeoCheckBot',
              +				uaUrl: 'http://www.kfsw.de/bot.html',
              +				uaCompany: 'Kristian Fischer',
              +				uaCompanyUrl: 'http://www.kfsw.de/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=SeoCheckBot'
              +			}
              +		},
              +		'11343': {
              +			userAgent: 'MiaDev/0.0.1 (MIA Bot for research project MIA (www.MIA-marktplatz.de); http://www.mia-marktplatz.de/spider; spider@mia-marktplatz.de)',
              +			metadata: {
              +				uaFamily: 'MiaDev',
              +				uaName: 'MiaDev/0.0.1',
              +				uaUrl: 'http://www.mia-marktplatz.de/spider',
              +				uaCompany: 'Technische Universit\xe4t Berlin',
              +				uaCompanyUrl: 'http://www.dima.tu-berlin.de/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=MiaDev'
              +			}
              +		},
              +		'11351': {
              +			userAgent: 'Mozilla/5.0 (compatible; aiHitBot/2.8; +http://endb-consolidated.aihit.com/)',
              +			metadata: {
              +				uaFamily: 'aiHitBot',
              +				uaName: 'aiHitBot/2.8',
              +				uaUrl: '',
              +				uaCompany: 'aiHit Ltd',
              +				uaCompanyUrl: 'http://aihit.com/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=aiHitBot'
              +			}
              +		},
              +		'11377': {
              +			userAgent: 'Baiduspider-image+(+http://www.baidu.com/search/spider.htm)',
              +			metadata: {
              +				uaFamily: 'Baiduspider',
              +				uaName: 'Baiduspider-image',
              +				uaUrl: 'http://www.baidu.com/search/spider.htm',
              +				uaCompany: 'Baidu',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bot_baiduspider.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Baiduspider'
              +			}
              +		},
              +		'11378': {
              +			userAgent: 'Fetch/2.0a (CMS Detection/Web/SEO analysis tool, see http://guess.scritch.org)',
              +			metadata: {
              +				uaFamily: 'Fetch-Guess',
              +				uaName: 'Fetch/2.0a',
              +				uaUrl: '',
              +				uaCompany: 'Ivo van der Wijk',
              +				uaCompanyUrl: 'http://www.m3r.nl/',
              +				uaIcon: 'bot.png',
              +				uaInfoUrl: '/list-of-ua/bot-detail?bot=Fetch-Guess'
              +			}
              +		},
              +		order: [
              +			'1490',
              +			'9655',
              +			'9010',
              +			'1773',
              +			'1633',
              +			'1871',
              +			'5311',
              +			'11255',
              +			'3422',
              +			'6592',
              +			'9410',
              +			'1941',
              +			'1735',
              +			'5077',
              +			'6246',
              +			'6247',
              +			'859',
              +			'892',
              +			'7106',
              +			'162',
              +			'512',
              +			'1273',
              +			'1282',
              +			'1287',
              +			'1297',
              +			'1685',
              +			'6905',
              +			'7001',
              +			'7009',
              +			'7112',
              +			'7178',
              +			'7265',
              +			'7285',
              +			'7321',
              +			'7366',
              +			'7409',
              +			'7458',
              +			'7477',
              +			'7544',
              +			'10228',
              +			'829',
              +			'7230',
              +			'1705',
              +			'494',
              +			'676',
              +			'715',
              +			'6404',
              +			'6751',
              +			'7333',
              +			'7579',
              +			'7843',
              +			'10246',
              +			'2102',
              +			'2188',
              +			'2223',
              +			'7320',
              +			'7462',
              +			'9839',
              +			'11351',
              +			'89',
              +			'1555',
              +			'1550',
              +			'11253',
              +			'90',
              +			'148',
              +			'214',
              +			'236',
              +			'278',
              +			'394',
              +			'471',
              +			'671',
              +			'1849',
              +			'128',
              +			'2110',
              +			'10140',
              +			'5623',
              +			'7015',
              +			'3236',
              +			'9389',
              +			'2057',
              +			'6237',
              +			'5272',
              +			'8694',
              +			'11323',
              +			'1042',
              +			'37',
              +			'131',
              +			'411',
              +			'694',
              +			'890',
              +			'9346',
              +			'2050',
              +			'6231',
              +			'9332',
              +			'7732',
              +			'7733',
              +			'14',
              +			'1474',
              +			'6399',
              +			'11377',
              +			'2125',
              +			'1770',
              +			'2162',
              +			'2063',
              +			'285',
              +			'360',
              +			'566',
              +			'712',
              +			'602',
              +			'789',
              +			'5357',
              +			'7754',
              +			'8866',
              +			'10241',
              +			'2022',
              +			'6514',
              +			'2135',
              +			'4733',
              +			'5238',
              +			'7494',
              +			'9832',
              +			'10562',
              +			'10537',
              +			'9288',
              +			'548',
              +			'580',
              +			'665',
              +			'749',
              +			'7340',
              +			'10008',
              +			'10057',
              +			'10823',
              +			'4519',
              +			'1726',
              +			'1637',
              +			'1754',
              +			'7442',
              +			'146',
              +			'328',
              +			'456',
              +			'833',
              +			'1479',
              +			'7696',
              +			'8192',
              +			'1733',
              +			'1753',
              +			'1752',
              +			'237',
              +			'11058',
              +			'1516',
              +			'5100',
              +			'817',
              +			'4939',
              +			'7369',
              +			'7162',
              +			'1481',
              +			'5665',
              +			'4977',
              +			'499',
              +			'588',
              +			'742',
              +			'928',
              +			'969',
              +			'1482',
              +			'1238',
              +			'9453',
              +			'10615',
              +			'184',
              +			'200',
              +			'207',
              +			'263',
              +			'327',
              +			'560',
              +			'594',
              +			'824',
              +			'1023',
              +			'812',
              +			'959',
              +			'1270',
              +			'9868',
              +			'76',
              +			'3409',
              +			'393',
              +			'5909',
              +			'10923',
              +			'11025',
              +			'10035',
              +			'7411',
              +			'7548',
              +			'7727',
              +			'8574',
              +			'9784',
              +			'608',
              +			'7927',
              +			'32',
              +			'80',
              +			'688',
              +			'1495',
              +			'2170',
              +			'2181',
              +			'2194',
              +			'2212',
              +			'2242',
              +			'2235',
              +			'2239',
              +			'2241',
              +			'2952',
              +			'2999',
              +			'3003',
              +			'2773',
              +			'2844',
              +			'2937',
              +			'2948',
              +			'5860',
              +			'6630',
              +			'6280',
              +			'9875',
              +			'317',
              +			'725',
              +			'755',
              +			'422',
              +			'630',
              +			'807',
              +			'967',
              +			'1150',
              +			'1466',
              +			'7406',
              +			'1530',
              +			'6802',
              +			'7164',
              +			'1568',
              +			'731',
              +			'752',
              +			'652',
              +			'811',
              +			'938',
              +			'1137',
              +			'1164',
              +			'1214',
              +			'1771',
              +			'6244',
              +			'6922',
              +			'7790',
              +			'1650',
              +			'9577',
              +			'1731',
              +			'5218',
              +			'6937',
              +			'1459',
              +			'3333',
              +			'7764',
              +			'7832',
              +			'1225',
              +			'7143',
              +			'117',
              +			'7624',
              +			'5187',
              +			'556',
              +			'569',
              +			'600',
              +			'7083',
              +			'488',
              +			'597',
              +			'1115',
              +			'1169',
              +			'1323',
              +			'192',
              +			'564',
              +			'8300',
              +			'8487',
              +			'1198',
              +			'1205',
              +			'1027',
              +			'547',
              +			'8184',
              +			'5806',
              +			'1500',
              +			'4730',
              +			'7243',
              +			'6243',
              +			'679',
              +			'753',
              +			'1994',
              +			'7014',
              +			'425',
              +			'8586',
              +			'8607',
              +			'9653',
              +			'5818',
              +			'1523',
              +			'5611',
              +			'8131',
              +			'1061',
              +			'7084',
              +			'4501',
              +			'1717',
              +			'3703',
              +			'312',
              +			'809',
              +			'1005',
              +			'47',
              +			'9020',
              +			'9065',
              +			'4722',
              +			'808',
              +			'1595',
              +			'3002',
              +			'11378',
              +			'118',
              +			'1856',
              +			'5292',
              +			'5352',
              +			'5646',
              +			'5685',
              +			'5715',
              +			'4853',
              +			'5052',
              +			'5243',
              +			'5277',
              +			'5843',
              +			'6011',
              +			'6177',
              +			'6298',
              +			'6312',
              +			'6326',
              +			'6712',
              +			'7338',
              +			'7387',
              +			'7399',
              +			'7467',
              +			'10078',
              +			'1582',
              +			'844',
              +			'876',
              +			'877',
              +			'925',
              +			'6202',
              +			'6068',
              +			'1536',
              +			'1870',
              +			'1663',
              +			'306',
              +			'804',
              +			'851',
              +			'531',
              +			'1035',
              +			'4946',
              +			'217',
              +			'137',
              +			'303',
              +			'741',
              +			'6226',
              +			'6353',
              +			'9691',
              +			'9652',
              +			'190',
              +			'215',
              +			'8096',
              +			'1133',
              +			'1052',
              +			'920',
              +			'9852',
              +			'1573',
              +			'45',
              +			'656',
              +			'657',
              +			'226',
              +			'2133',
              +			'2132',
              +			'5380',
              +			'7053',
              +			'25',
              +			'31',
              +			'982',
              +			'4726',
              +			'4966',
              +			'6945',
              +			'6948',
              +			'6947',
              +			'7258',
              +			'7259',
              +			'7260',
              +			'9737',
              +			'9298',
              +			'9239',
              +			'7717',
              +			'7718',
              +			'1932',
              +			'5165',
              +			'756',
              +			'1872',
              +			'1546',
              +			'1658',
              +			'1704',
              +			'1887',
              +			'2026',
              +			'2016',
              +			'2021',
              +			'2081',
              +			'2079',
              +			'2947',
              +			'7225',
              +			'623',
              +			'1519',
              +			'1583',
              +			'517',
              +			'554',
              +			'669',
              +			'927',
              +			'3600',
              +			'7380',
              +			'8138',
              +			'281',
              +			'307',
              +			'11039',
              +			'3235',
              +			'805',
              +			'5302',
              +			'7975',
              +			'761',
              +			'155',
              +			'1461',
              +			'1738',
              +			'1765',
              +			'1044',
              +			'124',
              +			'144',
              +			'223',
              +			'540',
              +			'1197',
              +			'3445',
              +			'5902',
              +			'6999',
              +			'7676',
              +			'5862',
              +			'764',
              +			'378',
              +			'81',
              +			'168',
              +			'7119',
              +			'7414',
              +			'85',
              +			'7542',
              +			'7632',
              +			'7726',
              +			'8134',
              +			'7819',
              +			'882',
              +			'167',
              +			'197',
              +			'242',
              +			'267',
              +			'729',
              +			'1220',
              +			'7113',
              +			'7995',
              +			'1540',
              +			'1859',
              +			'797',
              +			'6583',
              +			'6829',
              +			'7072',
              +			'5202',
              +			'5',
              +			'1599',
              +			'391',
              +			'1524',
              +			'1484',
              +			'3292',
              +			'1542',
              +			'7402',
              +			'539',
              +			'479',
              +			'10990',
              +			'396',
              +			'633',
              +			'83',
              +			'266',
              +			'405',
              +			'4264',
              +			'4590',
              +			'4591',
              +			'3398',
              +			'631',
              +			'632',
              +			'6625',
              +			'881',
              +			'778',
              +			'6612',
              +			'6647',
              +			'1780',
              +			'5180',
              +			'1504',
              +			'2155',
              +			'481',
              +			'483',
              +			'1798',
              +			'6044',
              +			'1475',
              +			'10237',
              +			'11045',
              +			'774',
              +			'130',
              +			'678',
              +			'4844',
              +			'20',
              +			'820',
              +			'4996',
              +			'1210',
              +			'1502',
              +			'6134',
              +			'7343',
              +			'7984',
              +			'8247',
              +			'9675',
              +			'10101',
              +			'525',
              +			'609',
              +			'7888',
              +			'5960',
              +			'10084',
              +			'7211',
              +			'5280',
              +			'114',
              +			'295',
              +			'496',
              +			'4589',
              +			'9540',
              +			'7525',
              +			'11343',
              +			'125',
              +			'232',
              +			'326',
              +			'520',
              +			'689',
              +			'1676',
              +			'1517',
              +			'1602',
              +			'1908',
              +			'1909',
              +			'2024',
              +			'2185',
              +			'4846',
              +			'6270',
              +			'6877',
              +			'7005',
              +			'7375',
              +			'10635',
              +			'1213',
              +			'1283',
              +			'994',
              +			'1247',
              +			'1867',
              +			'2195',
              +			'7012',
              +			'1563',
              +			'2196',
              +			'5683',
              +			'6436',
              +			'10847',
              +			'538',
              +			'135',
              +			'350',
              +			'624',
              +			'1533',
              +			'2120',
              +			'416',
              +			'562',
              +			'587',
              +			'865',
              +			'3',
              +			'1497',
              +			'1180',
              +			'1468',
              +			'4095',
              +			'4411',
              +			'6010',
              +			'252',
              +			'546',
              +			'791',
              +			'1024',
              +			'977',
              +			'442',
              +			'528',
              +			'813',
              +			'2028',
              +			'1476',
              +			'1494',
              +			'6921',
              +			'8208',
              +			'814',
              +			'6304',
              +			'832',
              +			'6225',
              +			'5056',
              +			'6735',
              +			'7856',
              +			'873',
              +			'1095',
              +			'5092',
              +			'7238',
              +			'368',
              +			'771',
              +			'1102',
              +			'563',
              +			'38',
              +			'465',
              +			'515',
              +			'5003',
              +			'290',
              +			'201',
              +			'209',
              +			'282',
              +			'294',
              +			'341',
              +			'431',
              +			'1072',
              +			'8743',
              +			'4866',
              +			'349',
              +			'366',
              +			'4336',
              +			'6114',
              +			'335',
              +			'480',
              +			'82',
              +			'84',
              +			'86',
              +			'100',
              +			'120',
              +			'133',
              +			'177',
              +			'321',
              +			'323',
              +			'338',
              +			'343',
              +			'382',
              +			'482',
              +			'484',
              +			'485',
              +			'491',
              +			'493',
              +			'710',
              +			'716',
              +			'917',
              +			'1089',
              +			'2087',
              +			'5939',
              +			'6245',
              +			'164',
              +			'178',
              +			'5987',
              +			'6826',
              +			'5228',
              +			'93',
              +			'116',
              +			'308',
              +			'109',
              +			'219',
              +			'355',
              +			'5859',
              +			'6914',
              +			'7045',
              +			'7055',
              +			'7107',
              +			'7132',
              +			'7563',
              +			'7606',
              +			'6234',
              +			'8429',
              +			'310',
              +			'1681',
              +			'2233',
              +			'1496',
              +			'9905',
              +			'1037',
              +			'1040',
              +			'7625',
              +			'253',
              +			'6739',
              +			'7070',
              +			'7854',
              +			'398',
              +			'886',
              +			'7437',
              +			'1938',
              +			'11068',
              +			'9427',
              +			'7959',
              +			'7833',
              +			'5376',
              +			'7153',
              +			'2197',
              +			'690',
              +			'9116',
              +			'6978',
              +			'7063',
              +			'7784',
              +			'8061',
              +			'1895',
              +			'2073',
              +			'4876',
              +			'6352',
              +			'7816',
              +			'7889',
              +			'141',
              +			'616',
              +			'4940',
              +			'760',
              +			'5360',
              +			'6974',
              +			'7605',
              +			'9455',
              +			'7655',
              +			'56',
              +			'5620',
              +			'1982',
              +			'8170',
              +			'5057',
              +			'914',
              +			'9877',
              +			'6024',
              +			'1815',
              +			'4936',
              +			'7217',
              +			'6252',
              +			'856',
              +			'337',
              +			'5362',
              +			'1711',
              +			'7799',
              +			'9165',
              +			'9918',
              +			'10604',
              +			'2145',
              +			'2078',
              +			'6721',
              +			'7044',
              +			'1601',
              +			'3415',
              +			'7424',
              +			'1816',
              +			'1906',
              +			'88',
              +			'123',
              +			'606',
              +			'2138',
              +			'1950',
              +			'1779',
              +			'462',
              +			'501',
              +			'9',
              +			'1565',
              +			'3203',
              +			'10503',
              +			'301',
              +			'7757',
              +			'4512',
              +			'8066',
              +			'2246',
              +			'6892',
              +			'10555',
              +			'6770',
              +			'7060',
              +			'7096',
              +			'7267',
              +			'7776',
              +			'9280',
              +			'9925',
              +			'10691',
              +			'10444',
              +			'151',
              +			'221',
              +			'10342',
              +			'10356',
              +			'11331',
              +			'6040',
              +			'3142',
              +			'5999',
              +			'6506',
              +			'6708',
              +			'6598',
              +			'1522',
              +			'1469',
              +			'1703',
              +			'4907',
              +			'4888',
              +			'6229',
              +			'6835',
              +			'6837',
              +			'1463',
              +			'1464',
              +			'1992',
              +			'3132',
              +			'4437',
              +			'5857',
              +			'6038',
              +			'6189',
              +			'6192',
              +			'6214',
              +			'7126',
              +			'10293',
              +			'1562',
              +			'262',
              +			'536',
              +			'747',
              +			'7163',
              +			'208',
              +			'227',
              +			'911',
              +			'1480',
              +			'6329',
              +			'6109',
              +			'874',
              +			'1866',
              +			'101',
              +			'408',
              +			'754',
              +			'815',
              +			'825',
              +			'921',
              +			'835',
              +			'1600',
              +			'10576',
              +			'1471',
              +			'1470',
              +			'523',
              +			'768',
              +			'770',
              +			'773',
              +			'1936',
              +			'7671',
              +			'8329',
              +			'9717',
              +			'9262',
              +			'1853',
              +			'7697',
              +			'10073',
              +			'4911',
              +			'4922',
              +			'3379',
              +			'5386',
              +			'5748',
              +			'3561',
              +			'3734',
              +			'3589',
              +			'4097',
              +			'4377',
              +			'7912',
              +			'10708',
              +			'11079',
              +			'999',
              +			'1885',
              +			'4185',
              +			'4337',
              +			'6288',
              +			'11139',
              +			'6816',
              +			'1784',
              +			'5066',
              +			'934',
              +			'1472',
              +			'296',
              +			'435',
              +			'545',
              +			'392',
              +			'410',
              +			'5231',
              +			'132',
              +			'5145',
              +			'567',
              +			'1092',
              +			'2099',
              +			'5188',
              +			'5802',
              +			'2098',
              +			'235',
              +			'7138',
              +			'7155',
              +			'1078',
              +			'204',
              +			'333',
              +			'470',
              +			'565',
              +			'96',
              +			'1772',
              +			'1971',
              +			'1727',
              +			'1728',
              +			'352',
              +			'412',
              +			'445',
              +			'447',
              +			'645',
              +			'646',
              +			'648',
              +			'961',
              +			'962',
              +			'963',
              +			'964',
              +			'965',
              +			'966',
              +			'218',
              +			'2004',
              +			'2175',
              +			'194',
              +			'5828',
              +			'6578',
              +			'2003',
              +			'2183',
              +			'1838',
              +			'4000',
              +			'1293',
              +			'6146',
              +			'7675',
              +			'489',
              +			'703',
              +			'40',
              +			'1763',
              +			'5006',
              +			'5839',
              +			'1462',
              +			'1759',
              +			'7317',
              +			'6962',
              +			'9781',
              +			'9874',
              +			'7384',
              +			'6065',
              +			'345',
              +			'437',
              +			'6840',
              +			'1662',
              +			'7469',
              +			'1505',
              +			'5727',
              +			'439',
              +			'1766',
              +			'5275',
              +			'8590',
              +			'11265',
              +			'658',
              +			'329',
              +			'195',
              +			'5065',
              +			'376',
              +			'629',
              +			'798',
              +			'6961',
              +			'612',
              +			'698',
              +			'888',
              +			'222',
              +			'1567',
              +			'225',
              +			'1586',
              +			'1619',
              +			'929',
              +			'6929',
              +			'5642',
              +			'5639',
              +			'5640',
              +			'5641',
              +			'5643',
              +			'5644',
              +			'5635',
              +			'5636',
              +			'5637',
              +			'5638',
              +			'6776',
              +			'4546',
              +			'902',
              +			'922',
              +			'5701',
              +			'153',
              +			'170',
              +			'765',
              +			'788',
              +			'1751',
              +			'7748',
              +			'1478',
              +			'7634',
              +			'469',
              +			'758',
              +			'11312',
              +			'5361',
              +			'786',
              +			'861',
              +			'7438',
              +			'7747',
              +			'5389',
              +			'5710',
              +			'872',
              +			'7841',
              +			'406',
              +			'1805',
              +			'238',
              +			'415',
              +			'452',
              +			'5183',
              +			'7622',
              +			'7628',
              +			'1501',
              +			'10349',
              +			'6515',
              +			'7596',
              +			'7577',
              +			'8191',
              +			'626',
              +			'364',
              +			'2205',
              +			'340',
              +			'4999',
              +			'4898',
              +			'4914',
              +			'1653',
              +			'1604',
              +			'1645',
              +			'1712',
              +			'1776',
              +			'1894',
              +			'1957',
              +			'2017',
              +			'2071',
              +			'2088',
              +			'2091',
              +			'2279',
              +			'2300',
              +			'3034',
              +			'3238',
              +			'3221',
              +			'5281',
              +			'5322',
              +			'4830',
              +			'4423',
              +			'4747',
              +			'4974',
              +			'4975',
              +			'5216',
              +			'5176',
              +			'5249',
              +			'5276',
              +			'5278',
              +			'6679',
              +			'6680',
              +			'6884',
              +			'6896',
              +			'6968',
              +			'6977',
              +			'7008',
              +			'7039',
              +			'7051',
              +			'7079',
              +			'7092',
              +			'7177',
              +			'7252',
              +			'7253',
              +			'7263',
              +			'7278',
              +			'7303',
              +			'7304',
              +			'7305',
              +			'7306',
              +			'7307',
              +			'7308',
              +			'7309',
              +			'7322',
              +			'7323',
              +			'7324',
              +			'7325',
              +			'7362',
              +			'7363',
              +			'7347',
              +			'7348',
              +			'7349',
              +			'7364',
              +			'7365',
              +			'7373',
              +			'7374',
              +			'7404',
              +			'7405',
              +			'7420',
              +			'7421',
              +			'7422',
              +			'7423',
              +			'7510',
              +			'7511',
              +			'7512',
              +			'7513',
              +			'7729',
              +			'8179',
              +			'8107',
              +			'8114',
              +			'8083',
              +			'9240',
              +			'9682',
              +			'9694',
              +			'8297',
              +			'9681',
              +			'8406',
              +			'10108',
              +			'9673',
              +			'10182',
              +			'9949',
              +			'10126',
              +			'10107',
              +			'10481',
              +			'10913',
              +			'10498',
              +			'10374',
              +			'10658',
              +			'10448',
              +			'10301',
              +			'10308',
              +			'10822',
              +			'11256',
              +			'4',
              +			'193',
              +			'1564',
              +			'1793',
              +			'1548',
              +			'1558',
              +			'5982',
              +			'6603',
              +			'7381',
              +			'7651',
              +			'8397',
              +			'605',
              +			'1458',
              +			'1690',
              +			'1869',
              +			'1943',
              +			'5010',
              +			'5014',
              +			'5016',
              +			'5090',
              +			'5846',
              +			'7013',
              +			'7018',
              +			'7159',
              +			'7160',
              +			'7161',
              +			'7172',
              +			'7173',
              +			'7426',
              +			'7427',
              +			'7428',
              +			'7429',
              +			'7430',
              +			'7433',
              +			'1512',
              +			'7133',
              +			'7300',
              +			'8318',
              +			'653',
              +			'728',
              +			'1818',
              +			'891',
              +			'1507',
              +			'1509',
              +			'5718',
              +			'43',
              +			'581',
              +			'5655',
              +			'5007',
              +			'6001',
              +			'7139',
              +			'8833',
              +			'913',
              +			'7780',
              +			'8902',
              +			'140',
              +			'159',
              +			'401',
              +			'3441'
              +		]
              +	},
              +	os: {
              +		'1': {
              +			osFamily: 'Windows',
              +			osName: 'Windows XP',
              +			osUrl: 'http://en.wikipedia.org/wiki/Windows_XP',
              +			osCompany: 'Microsoft Corporation.',
              +			osCompanyUrl: 'http://www.microsoft.com/',
              +			osIcon: 'windowsxp.png'
              +		},
              +		'2': {
              +			osFamily: 'Windows',
              +			osName: 'Windows 2000',
              +			osUrl: 'http://en.wikipedia.org/wiki/Windows_2000',
              +			osCompany: 'Microsoft Corporation.',
              +			osCompanyUrl: 'http://www.microsoft.com/',
              +			osIcon: 'windows.png'
              +		},
              +		'3': {
              +			osFamily: 'Windows',
              +			osName: 'Windows 2003 Server',
              +			osUrl: 'http://en.wikipedia.org/wiki/Windows_2003',
              +			osCompany: 'Microsoft Corporation.',
              +			osCompanyUrl: 'http://www.microsoft.com/',
              +			osIcon: 'windowsxp.png'
              +		},
              +		'4': {
              +			osFamily: 'Windows',
              +			osName: 'Windows 95',
              +			osUrl: 'http://en.wikipedia.org/wiki/Windows_95',
              +			osCompany: 'Microsoft Corporation.',
              +			osCompanyUrl: 'http://www.microsoft.com/',
              +			osIcon: 'windows.png'
              +		},
              +		'5': {
              +			osFamily: 'Windows',
              +			osName: 'Windows 98',
              +			osUrl: 'http://en.wikipedia.org/wiki/Windows_98',
              +			osCompany: 'Microsoft Corporation.',
              +			osCompanyUrl: 'http://www.microsoft.com/',
              +			osIcon: 'windows.png'
              +		},
              +		'6': {
              +			osFamily: 'Windows',
              +			osName: 'Windows 3.x',
              +			osUrl: 'http://en.wikipedia.org/wiki/Windows_3.x',
              +			osCompany: 'Microsoft Corporation.',
              +			osCompanyUrl: 'http://www.microsoft.com/',
              +			osIcon: 'windows.png'
              +		},
              +		'7': {
              +			osFamily: 'Windows',
              +			osName: 'Windows CE',
              +			osUrl: 'http://en.wikipedia.org/wiki/Windows_CE',
              +			osCompany: 'Microsoft Corporation.',
              +			osCompanyUrl: 'http://www.microsoft.com/',
              +			osIcon: 'windowsce.png'
              +		},
              +		'8': {
              +			osFamily: 'Windows',
              +			osName: 'Windows ME',
              +			osUrl: 'http://en.wikipedia.org/wiki/Windows_me',
              +			osCompany: 'Microsoft Corporation.',
              +			osCompanyUrl: 'http://www.microsoft.com/',
              +			osIcon: 'windows.png'
              +		},
              +		'9': {
              +			osFamily: 'Windows',
              +			osName: 'Windows Vista',
              +			osUrl: 'http://en.wikipedia.org/wiki/Windows_Vista',
              +			osCompany: 'Microsoft Corporation.',
              +			osCompanyUrl: 'http://www.microsoft.com/',
              +			osIcon: 'windowsvista.png'
              +		},
              +		'10': {
              +			osFamily: 'JVM',
              +			osName: 'JVM (Platform Micro Edition)',
              +			osUrl: 'http://en.wikipedia.org/wiki/Java_Platform,_Micro_Edition',
              +			osCompany: 'Sun Microsystems, Inc.',
              +			osCompanyUrl: 'http://en.wikipedia.org/wiki/Sun_Microsystems',
              +			osIcon: 'java.png'
              +		},
              +		'11': {
              +			osFamily: 'Linux',
              +			osName: 'Linux (CentOS)',
              +			osUrl: 'http://www.centos.org/',
              +			osCompany: 'CentOS Project',
              +			osCompanyUrl: 'http://www.centos.org/',
              +			osIcon: 'linux_centos.png'
              +		},
              +		'12': {
              +			osFamily: 'Linux',
              +			osName: 'Linux (Ubuntu)',
              +			osUrl: 'http://www.ubuntu.com/',
              +			osCompany: 'Canonical Ltd.',
              +			osCompanyUrl: 'http://www.canonical.com/',
              +			osIcon: 'linux_ubuntu.png'
              +		},
              +		'13': {
              +			osFamily: 'Linux',
              +			osName: 'Linux (Debian)',
              +			osUrl: 'http://www.debian.org/',
              +			osCompany: 'Software in the Public Interest, Inc.',
              +			osCompanyUrl: 'http://www.spi-inc.org/',
              +			osIcon: 'linux_debian.png'
              +		},
              +		'14': {
              +			osFamily: 'Linux',
              +			osName: 'Linux (Fedora)',
              +			osUrl: 'http://fedoraproject.org/',
              +			osCompany: 'Red Hat, Inc.',
              +			osCompanyUrl: 'http://www.redhat.com/',
              +			osIcon: 'linux_fedora.png'
              +		},
              +		'15': {
              +			osFamily: 'Linux',
              +			osName: 'Linux (Gentoo)',
              +			osUrl: 'http://www.gentoo.org/',
              +			osCompany: 'Gentoo Foundation, Inc.',
              +			osCompanyUrl: 'http://www.gentoo.org/foundation/en/',
              +			osIcon: 'linux_gentoo.png'
              +		},
              +		'16': {
              +			osFamily: 'Linux',
              +			osName: 'Linux (Linspire)',
              +			osUrl: 'http://en.wikipedia.org/wiki/Linspire',
              +			osCompany: 'Linspire, Inc.',
              +			osCompanyUrl: 'http://www.linspire.com/',
              +			osIcon: 'linux_linspire.png'
              +		},
              +		'17': {
              +			osFamily: 'Linux',
              +			osName: 'Linux (Mandriva)',
              +			osUrl: 'http://www.mandriva.com/',
              +			osCompany: '',
              +			osCompanyUrl: '',
              +			osIcon: 'linux_mandriva.png'
              +		},
              +		'18': {
              +			osFamily: 'Linux',
              +			osName: 'Linux (RedHat)',
              +			osUrl: 'http://en.wikipedia.org/wiki/Red_Hat_Enterprise_Linux',
              +			osCompany: 'Red Hat, Inc.',
              +			osCompanyUrl: 'http://www.redhat.com/',
              +			osIcon: 'linux_redhat.png'
              +		},
              +		'19': {
              +			osFamily: 'Linux',
              +			osName: 'Linux',
              +			osUrl: 'http://en.wikipedia.org/wiki/Linux',
              +			osCompany: '',
              +			osCompanyUrl: '',
              +			osIcon: 'linux.png'
              +		},
              +		'20': {
              +			osFamily: 'Linux',
              +			osName: 'Linux (Slackware)',
              +			osUrl: 'http://www.slackware.com/',
              +			osCompany: 'Slackware Linux, Inc.',
              +			osCompanyUrl: '',
              +			osIcon: 'linux_slackware.png'
              +		},
              +		'21': {
              +			osFamily: 'Linux',
              +			osName: 'Linux (Kanotix)',
              +			osUrl: 'http://kanotix.com/',
              +			osCompany: '',
              +			osCompanyUrl: '',
              +			osIcon: 'linux_kanotix.png'
              +		},
              +		'22': {
              +			osFamily: 'Linux',
              +			osName: 'Linux (SUSE)',
              +			osUrl: 'http://www.suse.com/',
              +			osCompany: 'Novell, Inc.',
              +			osCompanyUrl: 'http://www.novell.com/home/',
              +			osIcon: 'linux_suse.png'
              +		},
              +		'23': {
              +			osFamily: 'Linux',
              +			osName: 'Linux (Knoppix)',
              +			osUrl: 'http://knoppix.net/',
              +			osCompany: 'Klaus Knopper',
              +			osCompanyUrl: 'http://www.knopper.net/knopper/',
              +			osIcon: 'linux_knoppix.png'
              +		},
              +		'24': {
              +			osFamily: 'BSD',
              +			osName: 'NetBSD',
              +			osUrl: 'http://www.netbsd.org/',
              +			osCompany: 'NetBSD Foundation, Inc.',
              +			osCompanyUrl: '',
              +			osIcon: 'netbsd.png'
              +		},
              +		'25': {
              +			osFamily: 'BSD',
              +			osName: 'FreeBSD',
              +			osUrl: 'http://www.freebsd.org/',
              +			osCompany: 'FreeBSD Foundation',
              +			osCompanyUrl: 'http://www.freebsdfoundation.org/',
              +			osIcon: 'freebsd.png'
              +		},
              +		'26': {
              +			osFamily: 'BSD',
              +			osName: 'OpenBSD',
              +			osUrl: 'http://www.openbsd.org/',
              +			osCompany: '',
              +			osCompanyUrl: '',
              +			osIcon: 'openbsd.png'
              +		},
              +		'29': {
              +			osFamily: 'Solaris',
              +			osName: 'Solaris',
              +			osUrl: 'http://en.wikipedia.org/wiki/Solaris_%28operating_system%29',
              +			osCompany: 'Sun Microsystems, Inc.',
              +			osCompanyUrl: 'http://en.wikipedia.org/wiki/Sun_Microsystems',
              +			osIcon: 'solaris.png'
              +		},
              +		'30': {
              +			osFamily: 'Amiga OS',
              +			osName: 'Amiga OS',
              +			osUrl: 'http://www.amigaos.net/',
              +			osCompany: 'Commodore International Limited',
              +			osCompanyUrl: 'http://en.wikipedia.org/wiki/Commodore_International',
              +			osIcon: 'amiga.png'
              +		},
              +		'31': {
              +			osFamily: 'IRIX',
              +			osName: 'IRIX',
              +			osUrl: 'http://www.sgi.com/products/software/irix/',
              +			osCompany: 'Silicon Graphics, Inc.',
              +			osCompanyUrl: 'http://www.sgi.com/',
              +			osIcon: 'irix.png'
              +		},
              +		'32': {
              +			osFamily: 'OpenVMS',
              +			osName: 'OpenVMS',
              +			osUrl: 'http://h71000.www7.hp.com/',
              +			osCompany: 'Hewlett-Packard Development Company, L.P.',
              +			osCompanyUrl: 'http://www.hp.com/',
              +			osIcon: 'openvms.png'
              +		},
              +		'33': {
              +			osFamily: 'BeOS',
              +			osName: 'BeOS',
              +			osUrl: '',
              +			osCompany: 'Be, Inc.',
              +			osCompanyUrl: 'http://www.beincorporated.com/',
              +			osIcon: 'beos.png'
              +		},
              +		'34': {
              +			osFamily: 'Symbian OS',
              +			osName: 'Symbian OS',
              +			osUrl: 'http://en.wikipedia.org/wiki/Symbian_OS',
              +			osCompany: 'Symbian Foundation',
              +			osCompanyUrl: 'http://licensing.symbian.org/',
              +			osIcon: 'symbian.png'
              +		},
              +		'35': {
              +			osFamily: 'Palm OS',
              +			osName: 'Palm OS',
              +			osUrl: 'http://en.wikipedia.org/wiki/Palm_OS',
              +			osCompany: 'Palm, Inc.',
              +			osCompanyUrl: 'http://en.wikipedia.org/wiki/Palm,_Inc.',
              +			osIcon: 'palmos.png'
              +		},
              +		'37': {
              +			osFamily: 'Windows',
              +			osName: 'MSN TV (WebTV)',
              +			osUrl: 'http://en.wikipedia.org/wiki/MSN_TV',
              +			osCompany: 'Microsoft Corporation.',
              +			osCompanyUrl: 'http://www.microsoft.com/',
              +			osIcon: 'webtv.png'
              +		},
              +		'39': {
              +			osFamily: 'OS/2',
              +			osName: 'OS/2 Warp',
              +			osUrl: 'http://en.wikipedia.org/wiki/OS/2_Warp#The_.22Warp.22_years',
              +			osCompany: 'IBM Corporation',
              +			osCompanyUrl: 'http://www.ibm.com/',
              +			osIcon: 'os2warp.png'
              +		},
              +		'40': {
              +			osFamily: 'RISK OS',
              +			osName: 'RISK OS',
              +			osUrl: '',
              +			osCompany: 'RISCOS Ltd',
              +			osCompanyUrl: 'http://www.riscos.com/',
              +			osIcon: 'riskos.png'
              +		},
              +		'41': {
              +			osFamily: 'HP-UX',
              +			osName: 'HP-UX',
              +			osUrl: 'http://www.hp.com/products1/unix/',
              +			osCompany: 'Hewlett-Packard Development Company, L.P.',
              +			osCompanyUrl: 'http://www.hp.com/',
              +			osIcon: 'hpux.png'
              +		},
              +		'42': {
              +			osFamily: 'Nintendo',
              +			osName: 'Nintendo Wii',
              +			osUrl: 'http://en.wikipedia.org/wiki/Nintendo_Wii',
              +			osCompany: 'Nintendo of America Inc.',
              +			osCompanyUrl: 'http://www.nintendo.com/',
              +			osIcon: 'wii.png'
              +		},
              +		'43': {
              +			osFamily: 'Windows',
              +			osName: 'Windows',
              +			osUrl: 'http://en.wikipedia.org/wiki/Windows',
              +			osCompany: 'Microsoft Corporation.',
              +			osCompanyUrl: 'http://www.microsoft.com/',
              +			osIcon: 'windows.png'
              +		},
              +		'44': {
              +			osFamily: 'Mac OS',
              +			osName: 'Mac OS',
              +			osUrl: 'http://en.wikipedia.org/wiki/Mac_OS',
              +			osCompany: 'Apple Computer, Inc.',
              +			osCompanyUrl: 'http://www.apple.com/',
              +			osIcon: 'macos.png'
              +		},
              +		'45': {
              +			osFamily: 'AIX',
              +			osName: 'AIX',
              +			osUrl: 'http://en.wikipedia.org/wiki/IBM_AIX',
              +			osCompany: 'IBM Corporation',
              +			osCompanyUrl: 'http://www.ibm.com/',
              +			osIcon: 'aix.png'
              +		},
              +		'46': {
              +			osFamily: 'Windows',
              +			osName: 'Windows NT',
              +			osUrl: 'http://en.wikipedia.org/wiki/Windows_NT',
              +			osCompany: 'Microsoft Corporation.',
              +			osCompanyUrl: 'http://www.microsoft.com/',
              +			osIcon: 'windows.png'
              +		},
              +		'47': {
              +			osFamily: 'JVM',
              +			osName: 'JVM (Java)',
              +			osUrl: 'http://en.wikipedia.org/wiki/Jvm',
              +			osCompany: 'Sun Microsystems, Inc.',
              +			osCompanyUrl: 'http://en.wikipedia.org/wiki/Sun_Microsystems',
              +			osIcon: 'java.png'
              +		},
              +		'49': {
              +			osFamily: 'Plan 9',
              +			osName: 'Plan 9',
              +			osUrl: 'http://plan9.bell-labs.com/plan9/',
              +			osCompany: 'Lucent Technologies',
              +			osCompanyUrl: 'http://www.lucent.com/',
              +			osIcon: 'plan9.png'
              +		},
              +		'50': {
              +			osFamily: 'BlackBerry OS',
              +			osName: 'BlackBerry OS',
              +			osUrl: 'http://en.wikipedia.org/wiki/BlackBerry_OS',
              +			osCompany: 'BlackBerry Ltd',
              +			osCompanyUrl: 'http://www.blackberry.com/',
              +			osIcon: 'rim_os.png'
              +		},
              +		'52': {
              +			osFamily: 'QNX',
              +			osName: 'QNX x86pc',
              +			osUrl: 'http://www.qnx.com/',
              +			osCompany: 'QNX Software Systems',
              +			osCompanyUrl: 'http://www.qnx.com/',
              +			osIcon: 'qnx.png'
              +		},
              +		'53': {
              +			osFamily: 'MorphOS',
              +			osName: 'MorphOS',
              +			osUrl: 'http://www.morphos-team.net/',
              +			osCompany: 'MorphOS development team',
              +			osCompanyUrl: '',
              +			osIcon: 'morphos.png'
              +		},
              +		'55': {
              +			osFamily: 'Linux',
              +			osName: 'Linux (VectorLinux)',
              +			osUrl: 'http://vectorlinux.com/',
              +			osCompany: 'Robert S. Lange',
              +			osCompanyUrl: '',
              +			osIcon: 'linux_vector.png'
              +		},
              +		'56': {
              +			osFamily: 'Linux',
              +			osName: 'Linux (Mint)',
              +			osUrl: 'http://linuxmint.com/',
              +			osCompany: 'clem',
              +			osCompanyUrl: '',
              +			osIcon: 'linuxmint.png'
              +		},
              +		'57': {
              +			osFamily: 'SCO',
              +			osName: 'SCO OpenServer',
              +			osUrl: 'http://www.sco.com/products/openserver/',
              +			osCompany: 'The SCO Group',
              +			osCompanyUrl: 'http://www.sco.com/',
              +			osIcon: 'sco.png'
              +		},
              +		'58': {
              +			osFamily: 'Linux',
              +			osName: 'Linux (Arch Linux)',
              +			osUrl: 'http://www.archlinux.org/',
              +			osCompany: 'Judd Vinet',
              +			osCompanyUrl: 'http://www.zeroflux.org/',
              +			osIcon: 'linux_archlinux.png'
              +		},
              +		'59': {
              +			osFamily: 'SkyOS',
              +			osName: 'SkyOS',
              +			osUrl: 'http://www.skyos.org/',
              +			osCompany: 'SkyOS Team',
              +			osCompanyUrl: 'http://www.skyos.org/',
              +			osIcon: 'skyos.png'
              +		},
              +		'61': {
              +			osFamily: 'BSD',
              +			osName: 'DragonFly BSD',
              +			osUrl: 'http://www.dragonflybsd.org/',
              +			osCompany: 'DragonFly BSD Team',
              +			osCompanyUrl: 'http://www.dragonflybsd.org/team/',
              +			osIcon: 'dragonflybsd.png'
              +		},
              +		'62': {
              +			osFamily: 'Android',
              +			osName: 'Android',
              +			osUrl: 'http://en.wikipedia.org/wiki/Android_%28operating_system%29',
              +			osCompany: 'Google, Inc.',
              +			osCompanyUrl: 'http://www.google.com/',
              +			osIcon: 'android.png'
              +		},
              +		'64': {
              +			osFamily: 'Windows',
              +			osName: 'Windows 7',
              +			osUrl: 'http://en.wikipedia.org/wiki/Windows_7',
              +			osCompany: 'Microsoft Corporation.',
              +			osCompanyUrl: 'http://www.microsoft.com/',
              +			osIcon: 'windows-7.png'
              +		},
              +		'65': {
              +			osFamily: 'iOS',
              +			osName: 'iOS',
              +			osUrl: 'http://en.wikipedia.org/wiki/IOS',
              +			osCompany: 'Apple Inc.',
              +			osCompanyUrl: 'http://www.apple.com/',
              +			osIcon: 'iphone.png'
              +		},
              +		'69': {
              +			osFamily: 'webOS',
              +			osName: 'webOS',
              +			osUrl: 'http://en.wikipedia.org/wiki/WebOS',
              +			osCompany: 'Hewlett-Packard',
              +			osCompanyUrl: 'http://en.wikipedia.org/wiki/Palm,_Inc.',
              +			osIcon: 'webos.png'
              +		},
              +		'70': {
              +			osFamily: 'Haiku OS',
              +			osName: 'Haiku OS',
              +			osUrl: 'http://www.haiku-os.org/',
              +			osCompany: 'Haiku Inc.',
              +			osCompanyUrl: 'http://www.haiku-os.org/about/haiku_inc',
              +			osIcon: 'haiku.png'
              +		},
              +		'72': {
              +			osFamily: 'DangerOS',
              +			osName: 'Danger Hiptop',
              +			osUrl: 'http://en.wikipedia.org/wiki/DangerOS',
              +			osCompany: 'Danger, Inc.',
              +			osCompanyUrl: 'http://en.wikipedia.org/wiki/Danger_%28company%29',
              +			osIcon: 'dangeros.png'
              +		},
              +		'74': {
              +			osFamily: 'Syllable',
              +			osName: 'Syllable',
              +			osUrl: 'http://syllable.org/',
              +			osCompany: 'Kristian Van Der Vliet, Kaj de Vos, Rick Caudill, Arno Klenke, Henrik Isaksson',
              +			osCompanyUrl: '',
              +			osIcon: 'syllable.png'
              +		},
              +		'75': {
              +			osFamily: 'Linux',
              +			osName: 'Linux (Maemo)',
              +			osUrl: 'http://maemo.org/',
              +			osCompany: 'Nokia',
              +			osCompanyUrl: 'http://www.nokia.com/',
              +			osIcon: 'maemo.png'
              +		},
              +		'83': {
              +			osFamily: 'OS X',
              +			osName: 'OS X 10.4 Tiger',
              +			osUrl: 'http://www.apple.com/osx/',
              +			osCompany: 'Apple Computer, Inc.',
              +			osCompanyUrl: 'http://www.apple.com/',
              +			osIcon: 'macosx.png'
              +		},
              +		'84': {
              +			osFamily: 'OS X',
              +			osName: 'OS X 10.5 Leopard',
              +			osUrl: 'http://www.apple.com/osx/',
              +			osCompany: 'Apple Computer, Inc.',
              +			osCompanyUrl: 'http://www.apple.com/',
              +			osIcon: 'macosx.png'
              +		},
              +		'85': {
              +			osFamily: 'OS X',
              +			osName: 'OS X 10.6 Snow Leopard',
              +			osUrl: 'http://www.apple.com/osx/',
              +			osCompany: 'Apple Computer, Inc.',
              +			osCompanyUrl: 'http://www.apple.com/',
              +			osIcon: 'macosx.png'
              +		},
              +		'86': {
              +			osFamily: 'OS X',
              +			osName: 'OS X',
              +			osUrl: 'http://www.apple.com/osx/',
              +			osCompany: 'Apple Computer, Inc.',
              +			osCompanyUrl: 'http://www.apple.com/',
              +			osIcon: 'macosx.png'
              +		},
              +		'87': {
              +			osFamily: 'OS/2',
              +			osName: 'OS/2',
              +			osUrl: 'http://en.wikipedia.org/wiki/OS/2',
              +			osCompany: 'IBM Corporation',
              +			osCompanyUrl: 'http://www.ibm.com/',
              +			osIcon: 'os2.png'
              +		},
              +		'88': {
              +			osFamily: 'Windows',
              +			osName: 'Windows Mobile',
              +			osUrl: 'http://en.wikipedia.org/wiki/Windows_Mobile',
              +			osCompany: 'Microsoft Corporation.',
              +			osCompanyUrl: 'http://www.microsoft.com/',
              +			osIcon: 'windowsMobile.png'
              +		},
              +		'90': {
              +			osFamily: 'OS X',
              +			osName: 'OS X 10.3 Panther',
              +			osUrl: 'http://www.apple.com/osx/',
              +			osCompany: 'Apple Computer, Inc.',
              +			osCompanyUrl: 'http://www.apple.com/',
              +			osIcon: 'macosx.png'
              +		},
              +		'91': {
              +			osFamily: 'MINIX',
              +			osName: 'MINIX 3 ',
              +			osUrl: 'http://www.minix3.org/',
              +			osCompany: 'Andrew S. Tanenbaum',
              +			osCompanyUrl: 'http://www.cs.vu.nl/~ast/',
              +			osIcon: 'minix.png'
              +		},
              +		'92': {
              +			osFamily: 'Linux',
              +			osName: 'PClinuxOS',
              +			osUrl: 'http://www.pclinuxos.com/',
              +			osCompany: 'Bill Reynolds ("Texstar")',
              +			osCompanyUrl: '',
              +			osIcon: 'pclinuxos.png'
              +		},
              +		'93': {
              +			osFamily: 'Linux',
              +			osName: 'Joli OS',
              +			osUrl: 'http://www.jolicloud.com/',
              +			osCompany: 'Tariq Krim and Romain Huet',
              +			osCompanyUrl: '',
              +			osIcon: 'jolicloud.png'
              +		},
              +		'94': {
              +			osFamily: 'XrossMediaBar (XMB)',
              +			osName: 'XrossMediaBar (XMB)',
              +			osUrl: 'http://en.wikipedia.org/wiki/XrossMediaBar',
              +			osCompany: 'Sony Computer Entertainment',
              +			osCompanyUrl: 'http://www.scei.co.jp/',
              +			osIcon: 'XMB.png'
              +		},
              +		'95': {
              +			osFamily: 'AROS',
              +			osName: 'AROS',
              +			osUrl: 'http://en.wikipedia.org/wiki/AROS_Research_Operating_System',
              +			osCompany: 'AROS Development Team',
              +			osCompanyUrl: '',
              +			osIcon: 'aros.png'
              +		},
              +		'96': {
              +			osFamily: 'Windows',
              +			osName: 'Windows Phone 7',
              +			osUrl: 'http://en.wikipedia.org/wiki/Windows_Phone_7',
              +			osCompany: 'Microsoft Corporation.',
              +			osCompanyUrl: 'http://www.microsoft.com/',
              +			osIcon: 'windowsMobile.png'
              +		},
              +		'97': {
              +			osFamily: 'Linux',
              +			osName: 'Chrome OS',
              +			osUrl: 'http://en.wikipedia.org/wiki/Chrome_OS',
              +			osCompany: 'Google Inc.',
              +			osCompanyUrl: 'http://www.google.com/',
              +			osIcon: 'ChromiumOS.png'
              +		},
              +		'98': {
              +			osFamily: 'Nintendo',
              +			osName: 'Nintendo DS',
              +			osUrl: 'http://www.nintendods.com/',
              +			osCompany: 'Nintendo of America Inc.',
              +			osCompanyUrl: 'http://www.nintendo.com/',
              +			osIcon: 'nintendoDS.png'
              +		},
              +		'99': {
              +			osFamily: 'Linux',
              +			osName: 'GNU OS',
              +			osUrl: 'http://www.gnu.org/',
              +			osCompany: 'Free Software Foundation, Inc.',
              +			osCompanyUrl: 'http://www.fsf.org/',
              +			osIcon: 'gnu_os.png'
              +		},
              +		'100': {
              +			osFamily: 'Windows',
              +			osName: 'Windows 8',
              +			osUrl: 'http://en.wikipedia.org/wiki/Windows_8',
              +			osCompany: 'Microsoft Corporation.',
              +			osCompanyUrl: 'http://www.microsoft.com/',
              +			osIcon: 'windows8.png'
              +		},
              +		'101': {
              +			osFamily: 'RIM OS',
              +			osName: 'BlackBerry Tablet OS 1',
              +			osUrl: 'http://en.wikipedia.org/wiki/BlackBerry_Tablet_OS',
              +			osCompany: 'Research In Motion Limited',
              +			osCompanyUrl: 'http://www.rim.com/',
              +			osIcon: 'rim_os.png'
              +		},
              +		'102': {
              +			osFamily: 'Bada',
              +			osName: 'Bada',
              +			osUrl: 'http://www.bada.com/',
              +			osCompany: 'Samsung Electronics',
              +			osCompanyUrl: 'http://www.samsung.com/',
              +			osIcon: 'bada.png'
              +		},
              +		'103': {
              +			osFamily: 'Android',
              +			osName: 'Android 1.5 Cupcake',
              +			osUrl: 'http://en.wikipedia.org/wiki/Android_%28operating_system%29',
              +			osCompany: 'Google, Inc.',
              +			osCompanyUrl: 'http://www.google.com/',
              +			osIcon: 'android.png'
              +		},
              +		'104': {
              +			osFamily: 'Android',
              +			osName: 'Android 1.6 Donut',
              +			osUrl: 'http://en.wikipedia.org/wiki/Android_%28operating_system%29',
              +			osCompany: 'Google, Inc.',
              +			osCompanyUrl: 'http://www.google.com/',
              +			osIcon: 'android.png'
              +		},
              +		'105': {
              +			osFamily: 'Android',
              +			osName: 'Android 2.0/1 Eclair',
              +			osUrl: 'http://en.wikipedia.org/wiki/Android_%28operating_system%29',
              +			osCompany: 'Google, Inc.',
              +			osCompanyUrl: 'http://www.google.com/',
              +			osIcon: 'android.png'
              +		},
              +		'106': {
              +			osFamily: 'Android',
              +			osName: 'Android 2.2.x Froyo',
              +			osUrl: 'http://en.wikipedia.org/wiki/Android_%28operating_system%29',
              +			osCompany: 'Google, Inc.',
              +			osCompanyUrl: 'http://www.google.com/',
              +			osIcon: 'android.png'
              +		},
              +		'107': {
              +			osFamily: 'Android',
              +			osName: 'Android 2.3.x Gingerbread',
              +			osUrl: 'http://en.wikipedia.org/wiki/Android_%28operating_system%29',
              +			osCompany: 'Google, Inc.',
              +			osCompanyUrl: 'http://www.google.com/',
              +			osIcon: 'android.png'
              +		},
              +		'108': {
              +			osFamily: 'Android',
              +			osName: 'Android 3.x Honeycomb',
              +			osUrl: 'http://en.wikipedia.org/wiki/Android_%28operating_system%29',
              +			osCompany: 'Google, Inc.',
              +			osCompanyUrl: 'http://www.google.com/',
              +			osIcon: 'android.png'
              +		},
              +		'110': {
              +			osFamily: 'Android',
              +			osName: 'Android 1.0',
              +			osUrl: 'http://en.wikipedia.org/wiki/Android_%28operating_system%29',
              +			osCompany: 'Google, Inc.',
              +			osCompanyUrl: 'http://www.google.com/',
              +			osIcon: 'android.png'
              +		},
              +		'111': {
              +			osFamily: 'Android',
              +			osName: 'Android 4.0.x Ice Cream Sandwich',
              +			osUrl: 'http://en.wikipedia.org/wiki/Android_%28operating_system%29',
              +			osCompany: 'Google, Inc.',
              +			osCompanyUrl: 'http://www.google.com/',
              +			osIcon: 'android.png'
              +		},
              +		'112': {
              +			osFamily: 'OS X',
              +			osName: 'OS X 10.7 Lion',
              +			osUrl: 'http://www.apple.com/osx/',
              +			osCompany: 'Apple Computer, Inc.',
              +			osCompanyUrl: 'http://www.apple.com/',
              +			osIcon: 'macosx.png'
              +		},
              +		'113': {
              +			osFamily: 'Tizen',
              +			osName: 'Tizen 1',
              +			osUrl: 'https://www.tizen.org/',
              +			osCompany: 'Tizen Project',
              +			osCompanyUrl: 'https://www.tizen.org/',
              +			osIcon: 'tizen.png'
              +		},
              +		'114': {
              +			osFamily: 'unknown',
              +			osName: 'unknown',
              +			osUrl: '',
              +			osCompany: '',
              +			osCompanyUrl: '',
              +			osIcon: 'unknown.png'
              +		},
              +		'115': {
              +			osFamily: 'Inferno OS',
              +			osName: 'Inferno OS',
              +			osUrl: 'http://en.wikipedia.org/wiki/Inferno_%28operating_system%29',
              +			osCompany: 'Vita Nuova Holdings Ltd',
              +			osCompanyUrl: 'http://www.vitanuova.com/',
              +			osIcon: 'inferno.png'
              +		},
              +		'116': {
              +			osFamily: 'OS X',
              +			osName: 'OS X 10.8 Mountain Lion',
              +			osUrl: 'http://www.apple.com/osx/',
              +			osCompany: 'Apple Computer, Inc.',
              +			osCompanyUrl: 'http://www.apple.com/',
              +			osIcon: 'macosx.png'
              +		},
              +		'117': {
              +			osFamily: 'iOS',
              +			osName: 'iOS 4',
              +			osUrl: 'http://en.wikipedia.org/wiki/IOS',
              +			osCompany: 'Apple Inc.',
              +			osCompanyUrl: 'http://www.apple.com/',
              +			osIcon: 'iphone.png'
              +		},
              +		'118': {
              +			osFamily: 'iOS',
              +			osName: 'iOS 5',
              +			osUrl: 'http://en.wikipedia.org/wiki/IOS_5',
              +			osCompany: 'Apple Inc.',
              +			osCompanyUrl: 'http://www.apple.com/',
              +			osIcon: 'iphone.png'
              +		},
              +		'119': {
              +			osFamily: 'RIM OS',
              +			osName: 'BlackBerry Tablet OS 2',
              +			osUrl: 'http://en.wikipedia.org/wiki/BlackBerry_Tablet_OS',
              +			osCompany: 'Research In Motion Limited',
              +			osCompanyUrl: 'http://www.rim.com/',
              +			osIcon: 'rim_os.png'
              +		},
              +		'120': {
              +			osFamily: 'Android',
              +			osName: 'Android 4.1.x Jelly Bean',
              +			osUrl: 'http://en.wikipedia.org/wiki/Android_%28operating_system%29',
              +			osCompany: 'Google, Inc.',
              +			osCompanyUrl: 'http://www.google.com/',
              +			osIcon: 'android.png'
              +		},
              +		'121': {
              +			osFamily: 'iOS',
              +			osName: 'iOS 6',
              +			osUrl: 'http://en.wikipedia.org/wiki/IOS_6',
              +			osCompany: 'Apple Inc.',
              +			osCompanyUrl: 'http://www.apple.com/',
              +			osIcon: 'iphone.png'
              +		},
              +		'122': {
              +			osFamily: 'LiveArea',
              +			osName: 'LiveArea',
              +			osUrl: 'http://en.wikipedia.org/wiki/LiveArea',
              +			osCompany: 'Sony Computer Entertainment',
              +			osCompanyUrl: 'http://www.scei.co.jp/',
              +			osIcon: 'ps-vitaLiveArea.png'
              +		},
              +		'123': {
              +			osFamily: 'Windows',
              +			osName: 'Xbox patform',
              +			osUrl: 'http://en.wikipedia.org/wiki/Xbox#Operating_system',
              +			osCompany: 'Microsoft Corporation.',
              +			osCompanyUrl: 'http://www.microsoft.com/',
              +			osIcon: 'Xbox.png'
              +		},
              +		'124': {
              +			osFamily: 'Android',
              +			osName: 'Android 4.2 Jelly Bean',
              +			osUrl: 'http://en.wikipedia.org/wiki/Android_%28operating_system%29',
              +			osCompany: 'Google, Inc.',
              +			osCompanyUrl: 'http://www.google.com/',
              +			osIcon: 'android.png'
              +		},
              +		'125': {
              +			osFamily: 'Firefox OS',
              +			osName: 'Firefox OS',
              +			osUrl: 'http://www.mozilla.org/firefoxos/',
              +			osCompany: 'Mozilla Foundation',
              +			osCompanyUrl: 'http://www.mozilla.org/',
              +			osIcon: 'firefoxos.png'
              +		},
              +		'126': {
              +			osFamily: 'Windows',
              +			osName: 'Windows RT',
              +			osUrl: 'http://en.wikipedia.org/wiki/Windows_RT',
              +			osCompany: 'Microsoft Corporation.',
              +			osCompanyUrl: 'http://www.microsoft.com/',
              +			osIcon: 'windows8.png'
              +		},
              +		'127': {
              +			osFamily: 'Windows',
              +			osName: 'Windows Phone 8',
              +			osUrl: 'http://en.wikipedia.org/wiki/Windows_Phone_8',
              +			osCompany: 'Microsoft Corporation.',
              +			osCompanyUrl: 'http://www.microsoft.com/',
              +			osIcon: 'windowsPhone8.png'
              +		},
              +		'128': {
              +			osFamily: 'Linux',
              +			osName: 'Linux (Mageia)',
              +			osUrl: 'http://www.mageia.org/',
              +			osCompany: 'Mageia.Org',
              +			osCompanyUrl: 'http://www.mageia.org/',
              +			osIcon: 'linux_mageia.png'
              +		},
              +		'129': {
              +			osFamily: 'iOS',
              +			osName: 'iOS 7',
              +			osUrl: 'http://en.wikipedia.org/wiki/IOS_7',
              +			osCompany: 'Apple Inc.',
              +			osCompanyUrl: 'http://www.apple.com/',
              +			osIcon: 'iphone.png'
              +		},
              +		'130': {
              +			osFamily: 'Windows',
              +			osName: 'Windows 8.1',
              +			osUrl: 'http://en.wikipedia.org/wiki/Windows_8#Windows_8.1',
              +			osCompany: 'Microsoft Corporation.',
              +			osCompanyUrl: 'http://www.microsoft.com/',
              +			osIcon: 'win81.png'
              +		},
              +		'131': {
              +			osFamily: 'Android',
              +			osName: 'Android 4.3 Jelly Bean',
              +			osUrl: 'http://en.wikipedia.org/wiki/Android_%28operating_system%29',
              +			osCompany: 'Google, Inc.',
              +			osCompanyUrl: 'http://www.google.com/',
              +			osIcon: 'android.png'
              +		},
              +		'132': {
              +			osFamily: 'OS X',
              +			osName: 'OS X 10.9 Mavericks',
              +			osUrl: 'http://www.apple.com/osx/',
              +			osCompany: 'Apple Computer, Inc.',
              +			osCompanyUrl: 'http://www.apple.com/',
              +			osIcon: 'macosx.png'
              +		},
              +		'133': {
              +			osFamily: 'Nintendo',
              +			osName: 'Nintendo 3DS',
              +			osUrl: 'http://www.nintendo.com/3ds',
              +			osCompany: 'Nintendo of America Inc.',
              +			osCompanyUrl: 'http://www.nintendo.com/',
              +			osIcon: 'nintendoDS.png'
              +		},
              +		'134': {
              +			osFamily: 'Tizen',
              +			osName: 'Tizen 2',
              +			osUrl: 'https://www.tizen.org/',
              +			osCompany: 'Tizen Project',
              +			osCompanyUrl: 'https://www.tizen.org/',
              +			osIcon: 'tizen.png'
              +		},
              +		order: [
              +			'1',
              +			'2',
              +			'3',
              +			'4',
              +			'5',
              +			'6',
              +			'7',
              +			'8',
              +			'9',
              +			'10',
              +			'11',
              +			'12',
              +			'13',
              +			'14',
              +			'15',
              +			'16',
              +			'17',
              +			'18',
              +			'19',
              +			'20',
              +			'21',
              +			'22',
              +			'23',
              +			'24',
              +			'25',
              +			'26',
              +			'29',
              +			'30',
              +			'31',
              +			'32',
              +			'33',
              +			'34',
              +			'35',
              +			'37',
              +			'39',
              +			'40',
              +			'41',
              +			'42',
              +			'43',
              +			'44',
              +			'45',
              +			'46',
              +			'47',
              +			'49',
              +			'50',
              +			'52',
              +			'53',
              +			'55',
              +			'56',
              +			'57',
              +			'58',
              +			'59',
              +			'61',
              +			'62',
              +			'64',
              +			'65',
              +			'69',
              +			'70',
              +			'72',
              +			'74',
              +			'75',
              +			'83',
              +			'84',
              +			'85',
              +			'86',
              +			'87',
              +			'88',
              +			'90',
              +			'91',
              +			'92',
              +			'93',
              +			'94',
              +			'95',
              +			'96',
              +			'97',
              +			'98',
              +			'99',
              +			'100',
              +			'101',
              +			'102',
              +			'103',
              +			'104',
              +			'105',
              +			'106',
              +			'107',
              +			'108',
              +			'110',
              +			'111',
              +			'112',
              +			'113',
              +			'114',
              +			'115',
              +			'116',
              +			'117',
              +			'118',
              +			'119',
              +			'120',
              +			'121',
              +			'122',
              +			'123',
              +			'124',
              +			'125',
              +			'126',
              +			'127',
              +			'128',
              +			'129',
              +			'130',
              +			'131',
              +			'132',
              +			'133',
              +			'134'
              +		]
              +	},
              +	browser: {
              +		'1': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Camino',
              +				uaUrl: 'http://caminobrowser.org/',
              +				uaCompany: 'Mozilla Foundation',
              +				uaCompanyUrl: 'http://www.mozilla.org/',
              +				uaIcon: 'camino.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Camino'
              +			}
              +		},
              +		'2': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'SeaMonkey',
              +				uaUrl: 'http://www.seamonkey-project.org/',
              +				uaCompany: 'Mozilla Foundation',
              +				uaCompanyUrl: 'http://www.mozilla.org/',
              +				uaIcon: 'seamonkey.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=SeaMonkey'
              +			}
              +		},
              +		'3': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Firefox',
              +				uaUrl: 'http://www.firefox.com/',
              +				uaCompany: 'Mozilla Foundation',
              +				uaCompanyUrl: 'http://www.mozilla.org/',
              +				uaIcon: 'firefox.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Firefox'
              +			}
              +		},
              +		'4': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Netscape Navigator',
              +				uaUrl: 'http://en.wikipedia.org/wiki/Netscape_Navigator',
              +				uaCompany: 'Netscape Communications Corp.',
              +				uaCompanyUrl: 'http://en.wikipedia.org/wiki/Netscape_Communications_Corporation',
              +				uaIcon: 'netscape.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Netscape Navigator'
              +			}
              +		},
              +		'5': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Epiphany',
              +				uaUrl: 'http://projects.gnome.org/epiphany/',
              +				uaCompany: 'GNOME Foundation',
              +				uaCompanyUrl: 'http://www.gnome.org/',
              +				uaIcon: 'epiphany.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Epiphany'
              +			}
              +		},
              +		'6': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Galeon',
              +				uaUrl: 'http://galeon.sourceforge.net/',
              +				uaCompany: 'GNOME Foundation',
              +				uaCompanyUrl: 'http://www.gnome.org/',
              +				uaIcon: 'galeon.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Galeon'
              +			}
              +		},
              +		'7': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Flock',
              +				uaUrl: 'http://en.wikipedia.org/wiki/Flock_%28web_browser%29',
              +				uaCompany: 'Flock, Inc.',
              +				uaCompanyUrl: '',
              +				uaIcon: 'flock.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Flock'
              +			}
              +		},
              +		'8': {
              +			typeId: '3',
              +			metadata: {
              +				uaFamily: 'Minimo',
              +				uaUrl: 'http://www.mozilla.org/projects/minimo/',
              +				uaCompany: 'Mozilla Foundation',
              +				uaCompanyUrl: 'http://www.mozilla.org/',
              +				uaIcon: 'minimo.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Minimo'
              +			}
              +		},
              +		'9': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'K-Meleon',
              +				uaUrl: 'http://kmeleon.sourceforge.net/',
              +				uaCompany: 'Christophe Thibault, Dorian ...',
              +				uaCompanyUrl: '',
              +				uaIcon: 'k-meleon.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=K-Meleon'
              +			}
              +		},
              +		'10': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'K-Ninja',
              +				uaUrl: 'http://www.geocities.com/grenleef/',
              +				uaCompany: '',
              +				uaCompanyUrl: '',
              +				uaIcon: 'k-ninja.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=K-Ninja'
              +			}
              +		},
              +		'11': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Kazehakase',
              +				uaUrl: 'http://kazehakase.sourceforge.jp/',
              +				uaCompany: '',
              +				uaCompanyUrl: '',
              +				uaIcon: 'kazehakase.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Kazehakase'
              +			}
              +		},
              +		'14': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Firebird (old name for Firefox)',
              +				uaUrl: 'http://www.firefox.com/',
              +				uaCompany: 'Mozilla Foundation',
              +				uaCompanyUrl: 'http://www.mozilla.org/',
              +				uaIcon: 'phoenix.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Firebird (old name for Firefox)'
              +			}
              +		},
              +		'15': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Phoenix (old name for Firefox)',
              +				uaUrl: 'http://en.wikipedia.org/wiki/Mozilla_Phoenix',
              +				uaCompany: 'Mozilla Foundation',
              +				uaCompanyUrl: 'http://www.mozilla.org/',
              +				uaIcon: 'phoenix.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Phoenix (old name for Firefox)'
              +			}
              +		},
              +		'16': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Konqueror',
              +				uaUrl: 'http://www.konqueror.org/',
              +				uaCompany: 'KDE e.V.',
              +				uaCompanyUrl: 'http://ev.kde.org/',
              +				uaIcon: 'konqueror2.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Konqueror'
              +			}
              +		},
              +		'17': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Opera',
              +				uaUrl: 'http://www.opera.com/',
              +				uaCompany: 'Opera Software ASA.',
              +				uaCompanyUrl: 'http://www.opera.com/',
              +				uaIcon: 'opera.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Opera'
              +			}
              +		},
              +		'18': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'OmniWeb',
              +				uaUrl: 'http://www.omnigroup.com/applications/omniweb/',
              +				uaCompany: 'Omni Development, Inc.',
              +				uaCompanyUrl: 'http://www.omnigroup.com/',
              +				uaIcon: 'omniweb.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=OmniWeb'
              +			}
              +		},
              +		'19': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Sunrise',
              +				uaUrl: 'http://www.sunrisebrowser.com/',
              +				uaCompany: '',
              +				uaCompanyUrl: '',
              +				uaIcon: 'sunrise.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Sunrise'
              +			}
              +		},
              +		'21': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Shiira',
              +				uaUrl: 'http://en.wikipedia.org/wiki/Shiira',
              +				uaCompany: 'Shiira Project',
              +				uaCompanyUrl: '',
              +				uaIcon: 'shiira.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Shiira'
              +			}
              +		},
              +		'22': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Safari',
              +				uaUrl: 'http://en.wikipedia.org/wiki/Safari_%28web_browser%29',
              +				uaCompany: 'Apple Inc.',
              +				uaCompanyUrl: 'http://www.apple.com/',
              +				uaIcon: 'safari.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Safari'
              +			}
              +		},
              +		'23': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Dillo',
              +				uaUrl: 'http://www.dillo.org/',
              +				uaCompany: '',
              +				uaCompanyUrl: '',
              +				uaIcon: 'dillo.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Dillo'
              +			}
              +		},
              +		'24': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'iCab',
              +				uaUrl: 'http://www.icab.de/',
              +				uaCompany: 'Alexander Clauss',
              +				uaCompanyUrl: '',
              +				uaIcon: 'icab.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=iCab'
              +			}
              +		},
              +		'25': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Lynx',
              +				uaUrl: 'http://lynx.isc.org/',
              +				uaCompany: '',
              +				uaCompanyUrl: '',
              +				uaIcon: 'lynx.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Lynx'
              +			}
              +		},
              +		'27': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Elinks',
              +				uaUrl: 'http://elinks.or.cz/',
              +				uaCompany: 'Mikulas Patocka',
              +				uaCompanyUrl: '',
              +				uaIcon: 'elinks.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Elinks'
              +			}
              +		},
              +		'28': {
              +			typeId: '1',
              +			metadata: {
              +				uaFamily: 'Wget',
              +				uaUrl: 'http://www.gnu.org/software/wget/',
              +				uaCompany: 'Free Software Foundation, Inc.',
              +				uaCompanyUrl: 'http://www.gnu.org/',
              +				uaIcon: 'wget.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Wget'
              +			}
              +		},
              +		'29': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Amiga Aweb',
              +				uaUrl: 'http://www.amitrix.com/aweb.html',
              +				uaCompany: 'AmiTrix Development Inc.',
              +				uaCompanyUrl: 'http://www.amitrix.com/',
              +				uaIcon: 'aweb.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Amiga Aweb'
              +			}
              +		},
              +		'30': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Amiga Voyager',
              +				uaUrl: 'http://v3.vapor.com/',
              +				uaCompany: 'VaporWare',
              +				uaCompanyUrl: 'http://www.vapor.com/',
              +				uaIcon: 'voyager.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Amiga Voyager'
              +			}
              +		},
              +		'31': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'IBrowse',
              +				uaUrl: 'http://www.ibrowse-dev.net/',
              +				uaCompany: 'Stefan Burstr\xf6m',
              +				uaCompanyUrl: '',
              +				uaIcon: 'ibrowse.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=IBrowse'
              +			}
              +		},
              +		'32': {
              +			typeId: '3',
              +			metadata: {
              +				uaFamily: 'Openwave Mobile Browser',
              +				uaUrl: 'http://www.openwave.com/',
              +				uaCompany: 'Openwave Systems Inc.',
              +				uaCompanyUrl: 'http://www.openwave.com/',
              +				uaIcon: 'openwave.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Openwave Mobile Browser'
              +			}
              +		},
              +		'33': {
              +			typeId: '3',
              +			metadata: {
              +				uaFamily: 'NetFront',
              +				uaUrl: 'http://www.access-company.com/',
              +				uaCompany: 'ACCESS CO.,LTD',
              +				uaCompanyUrl: 'http://www.access-company.com/',
              +				uaIcon: 'netfront.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=NetFront'
              +			}
              +		},
              +		'35': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'IE',
              +				uaUrl: 'http://en.wikipedia.org/wiki/Internet_Explorer',
              +				uaCompany: 'Microsoft Corporation.',
              +				uaCompanyUrl: 'http://www.microsoft.com/',
              +				uaIcon: 'msie.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=IE'
              +			}
              +		},
              +		'39': {
              +			typeId: '1',
              +			metadata: {
              +				uaFamily: 'Offline Explorer',
              +				uaUrl: 'http://www.metaproducts.com/',
              +				uaCompany: 'MetaProducts Corporation.',
              +				uaCompanyUrl: '',
              +				uaIcon: 'offline_explorer.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Offline Explorer'
              +			}
              +		},
              +		'40': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'AOL Explorer',
              +				uaUrl: 'http://daol.aol.com/software/',
              +				uaCompany: 'America Online, Inc.',
              +				uaCompanyUrl: 'http://www.aol.com/',
              +				uaIcon: 'aol.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=AOL Explorer'
              +			}
              +		},
              +		'41': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Avant Browser',
              +				uaUrl: 'http://avantbrowser.com/',
              +				uaCompany: 'Avant Force',
              +				uaCompanyUrl: 'http://avantbrowser.com/',
              +				uaIcon: 'avantbrowser.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Avant Browser'
              +			}
              +		},
              +		'42': {
              +			typeId: '1',
              +			metadata: {
              +				uaFamily: 'AvantGo',
              +				uaUrl: 'http://en.wikipedia.org/wiki/AvantGo',
              +				uaCompany: 'Sybase Inc.',
              +				uaCompanyUrl: 'http://www.sybase.com/',
              +				uaIcon: 'avantgo.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=AvantGo'
              +			}
              +		},
              +		'43': {
              +			typeId: '3',
              +			metadata: {
              +				uaFamily: 'Blazer',
              +				uaUrl: 'http://en.wikipedia.org/wiki/Blazer_(web_browser)',
              +				uaCompany: 'Bluelark Systems',
              +				uaCompanyUrl: '',
              +				uaIcon: 'blazer.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Blazer'
              +			}
              +		},
              +		'44': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Crazy Browser',
              +				uaUrl: 'http://www.crazybrowser.com/',
              +				uaCompany: 'CrazyBrowser.com',
              +				uaCompanyUrl: 'http://www.crazybrowser.com/',
              +				uaIcon: 'crazybrowser.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Crazy Browser'
              +			}
              +		},
              +		'45': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Deepnet Explorer',
              +				uaUrl: 'http://www.deepnetexplorer.com/',
              +				uaCompany: 'Deepnet Technologies Ltd',
              +				uaCompanyUrl: 'http://www.deepnetexplorer.com/',
              +				uaIcon: 'deepnet.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Deepnet Explorer'
              +			}
              +		},
              +		'46': {
              +			typeId: '1',
              +			metadata: {
              +				uaFamily: 'HTTrack',
              +				uaUrl: 'http://www.httrack.com/',
              +				uaCompany: 'Xavier Roche',
              +				uaCompanyUrl: 'http://www.httrack.com/',
              +				uaIcon: 'httrack.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=HTTrack'
              +			}
              +		},
              +		'47': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'IceWeasel',
              +				uaUrl: 'http://www.gnu.org/software/gnuzilla/',
              +				uaCompany: 'Software in the Public Interest, Inc.',
              +				uaCompanyUrl: 'http://www.spi-inc.org/',
              +				uaIcon: 'iceweasel.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=IceWeasel'
              +			}
              +		},
              +		'48': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'iRider',
              +				uaUrl: 'http://www.irider.com/irider/index.htm',
              +				uaCompany: 'Wymea Bay',
              +				uaCompanyUrl: 'http://www.irider.com/company/index.htm',
              +				uaIcon: 'irider.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=iRider'
              +			}
              +		},
              +		'49': {
              +			typeId: '1',
              +			metadata: {
              +				uaFamily: 'iSiloX',
              +				uaUrl: 'http://www.isilox.com/',
              +				uaCompany: 'DC & Co.',
              +				uaCompanyUrl: 'http://www.isilox.com/',
              +				uaIcon: 'isilox.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=iSiloX'
              +			}
              +		},
              +		'50': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'KKman',
              +				uaUrl: 'http://www.kkbox.com.tw/kkman/index.html',
              +				uaCompany: 'KKBOX Inc. ',
              +				uaCompanyUrl: 'http://www.kkbox-inc.com/',
              +				uaIcon: 'kkman.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=KKman'
              +			}
              +		},
              +		'51': {
              +			typeId: '5',
              +			metadata: {
              +				uaFamily: 'libwww-perl',
              +				uaUrl: 'http://search.cpan.org/dist/libwww-perl/',
              +				uaCompany: 'Gisle Aas',
              +				uaCompanyUrl: '',
              +				uaIcon: 'libwwwperl.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=libwww-perl'
              +			}
              +		},
              +		'52': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Lunascape',
              +				uaUrl: 'http://www.lunascape.tv/',
              +				uaCompany: 'Lunascape & Co., Ltd.',
              +				uaCompanyUrl: 'http://www.lunascape.co.jp/',
              +				uaIcon: 'lunascape.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Lunascape'
              +			}
              +		},
              +		'53': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Maxthon',
              +				uaUrl: 'http://www.maxthon.com/',
              +				uaCompany: 'Maxthon International Limited.',
              +				uaCompanyUrl: 'http://www.maxthon.com/',
              +				uaIcon: 'maxthon.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Maxthon'
              +			}
              +		},
              +		'54': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Mozilla',
              +				uaUrl: 'http://en.wikipedia.org/wiki/Mozilla',
              +				uaCompany: 'Mozilla Foundation',
              +				uaCompanyUrl: 'http://www.mozilla.com/',
              +				uaIcon: 'mozilla.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Mozilla'
              +			}
              +		},
              +		'55': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'MultiZilla',
              +				uaUrl: 'http://multizilla.mozdev.org/',
              +				uaCompany: 'HJ van Rantwijk',
              +				uaCompanyUrl: 'http://multizilla.mozdev.org/',
              +				uaIcon: 'multizilla.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=MultiZilla'
              +			}
              +		},
              +		'56': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'NetCaptor',
              +				uaUrl: 'http://en.wikipedia.org/wiki/NetCaptor',
              +				uaCompany: 'Stilesoft Inc.',
              +				uaCompanyUrl: '',
              +				uaIcon: 'netcaptor.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=NetCaptor'
              +			}
              +		},
              +		'57': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'NetBox',
              +				uaUrl: 'http://www.netgem.com/',
              +				uaCompany: 'Netgem',
              +				uaCompanyUrl: 'http://www.netgem.com/',
              +				uaIcon: 'netgem.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=NetBox'
              +			}
              +		},
              +		'58': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'NetSurf',
              +				uaUrl: 'http://www.netsurf-browser.org/',
              +				uaCompany: "NetSurf's Development Team",
              +				uaCompanyUrl: 'http://www.netsurf-browser.org/about/team',
              +				uaIcon: 'netsurf.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=NetSurf'
              +			}
              +		},
              +		'59': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Sleipnir',
              +				uaUrl: 'http://en.wikipedia.org/wiki/Sleipnir_%28browser%29',
              +				uaCompany: 'Fenrir Inc.',
              +				uaCompanyUrl: 'http://www.fenrir-inc.com/',
              +				uaIcon: 'sleipnir.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Sleipnir'
              +			}
              +		},
              +		'61': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Swiftfox',
              +				uaUrl: 'http://www.getswiftfox.com/',
              +				uaCompany: 'Jason Halme',
              +				uaCompanyUrl: '',
              +				uaIcon: 'swiftfox.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Swiftfox'
              +			}
              +		},
              +		'62': {
              +			typeId: '1',
              +			metadata: {
              +				uaFamily: 'Teleport Pro',
              +				uaUrl: 'http://www.tenmax.com/teleport/pro/home.htm',
              +				uaCompany: 'Tennyson Maxwell Information Systems, Inc.',
              +				uaCompanyUrl: 'http://www.tenmax.com/',
              +				uaIcon: 'teleportpro.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Teleport Pro'
              +			}
              +		},
              +		'71': {
              +			typeId: '1',
              +			metadata: {
              +				uaFamily: 'WebCopier',
              +				uaUrl: 'http://www.maximumsoft.com/products/wc_index.html',
              +				uaCompany: 'MaximumSoft Corp.',
              +				uaCompanyUrl: 'http://www.maximumsoft.com/',
              +				uaIcon: 'webcopier.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=WebCopier'
              +			}
              +		},
              +		'74': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Phaseout',
              +				uaUrl: 'http://www.phaseout.net/',
              +				uaCompany: 'PhaseOut.net',
              +				uaCompanyUrl: 'http://www.phaseout.net/',
              +				uaIcon: 'phaseout.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Phaseout'
              +			}
              +		},
              +		'79': {
              +			typeId: '4',
              +			metadata: {
              +				uaFamily: 'Thunderbird',
              +				uaUrl: 'http://www.mozilla.com/en-US/thunderbird/',
              +				uaCompany: 'Mozilla Foundation',
              +				uaCompanyUrl: 'http://www.mozilla.org/',
              +				uaIcon: 'thunderbird.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Thunderbird'
              +			}
              +		},
              +		'81': {
              +			typeId: '3',
              +			metadata: {
              +				uaFamily: 'Doris',
              +				uaUrl: 'http://www.anygraaf.fi/browser/indexe.htm',
              +				uaCompany: 'Anygraaf',
              +				uaCompanyUrl: 'http://www.anygraaf.fi/',
              +				uaIcon: 'doris.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Doris'
              +			}
              +		},
              +		'82': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Enigma browser',
              +				uaUrl: 'http://www.suttondesigns.com/',
              +				uaCompany: 'Advanced Search Technologies, Inc.',
              +				uaCompanyUrl: 'http://www.advancedsearchcorp.com/',
              +				uaIcon: 'enigmabrowser.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Enigma browser'
              +			}
              +		},
              +		'85': {
              +			typeId: '5',
              +			metadata: {
              +				uaFamily: 'Jakarta Commons-HttpClient',
              +				uaUrl: 'http://jakarta.apache.org/commons/httpclient/',
              +				uaCompany: 'Apache Software Foundation',
              +				uaCompanyUrl: 'http://www.apache.org/',
              +				uaIcon: 'jakarta.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Jakarta Commons-HttpClient'
              +			}
              +		},
              +		'86': {
              +			typeId: '5',
              +			metadata: {
              +				uaFamily: 'cURL',
              +				uaUrl: 'http://curl.haxx.se/',
              +				uaCompany: 'team Haxx',
              +				uaCompanyUrl: 'http://www.haxx.se/',
              +				uaIcon: 'curl.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=cURL'
              +			}
              +		},
              +		'87': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Amaya',
              +				uaUrl: 'http://www.w3.org/Amaya/',
              +				uaCompany: 'World Wide Web Consortium',
              +				uaCompanyUrl: 'http://www.w3.org/',
              +				uaIcon: 'amaya.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Amaya'
              +			}
              +		},
              +		'88': {
              +			typeId: '1',
              +			metadata: {
              +				uaFamily: 'GetRight',
              +				uaUrl: 'http://www.getright.com/',
              +				uaCompany: 'Headlight Software, Inc.',
              +				uaCompanyUrl: 'http://www.headlightinc.com/',
              +				uaIcon: 'getright.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=GetRight'
              +			}
              +		},
              +		'89': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Off By One',
              +				uaUrl: 'http://offbyone.com/',
              +				uaCompany: 'Home Page Software Inc.',
              +				uaCompanyUrl: 'http://homepagesw.com/',
              +				uaIcon: 'offbyone.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Off By One'
              +			}
              +		},
              +		'90': {
              +			typeId: '5',
              +			metadata: {
              +				uaFamily: 'Python-urllib',
              +				uaUrl: 'http://www.python.org/doc/current/lib/module-urllib.html',
              +				uaCompany: 'Python Software Foundation',
              +				uaCompanyUrl: 'http://www.python.org/psf/',
              +				uaIcon: 'pythonurllib.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Python-urllib'
              +			}
              +		},
              +		'91': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'w3m',
              +				uaUrl: 'http://w3m.sourceforge.net/',
              +				uaCompany: 'Sakamoto Hironori',
              +				uaCompanyUrl: 'http://www2u.biglobe.ne.jp/%7Ehsaka/',
              +				uaIcon: 'w3m.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=w3m'
              +			}
              +		},
              +		'93': {
              +			typeId: '1',
              +			metadata: {
              +				uaFamily: 'WebZIP',
              +				uaUrl: 'http://www.spidersoft.com/webzip/',
              +				uaCompany: 'Spidersoft',
              +				uaCompanyUrl: 'http://www.spidersoft.com/',
              +				uaIcon: 'webzip.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=WebZIP'
              +			}
              +		},
              +		'94': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'ICE browser',
              +				uaUrl: 'http://www.icesoft.com/products/icebrowser.html',
              +				uaCompany: 'ICEsoft Technologies Inc.',
              +				uaCompanyUrl: 'http://www.icesoft.com/',
              +				uaIcon: 'icebrowser.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=ICE browser'
              +			}
              +		},
              +		'96': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'IceApe',
              +				uaUrl: 'http://www.debian.org/',
              +				uaCompany: 'Software in the Public Interest, Inc.',
              +				uaCompanyUrl: 'http://www.spi-inc.org/',
              +				uaIcon: 'seamonkey.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=IceApe'
              +			}
              +		},
              +		'99': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'HotJava',
              +				uaUrl: 'http://java.sun.com/products/archive/hotjava/index.html',
              +				uaCompany: 'Sun Microsystems, Inc.',
              +				uaCompanyUrl: 'http://www.sun.com/',
              +				uaIcon: 'hotjava.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=HotJava'
              +			}
              +		},
              +		'100': {
              +			typeId: '1',
              +			metadata: {
              +				uaFamily: 'JoBo',
              +				uaUrl: 'http://www.matuschek.net/jobo/',
              +				uaCompany: 'Daniel Matuschek',
              +				uaCompanyUrl: 'http://www.matuschek.net/',
              +				uaIcon: 'jobo.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=JoBo'
              +			}
              +		},
              +		'105': {
              +			typeId: '5',
              +			metadata: {
              +				uaFamily: 'POE-Component-Client-HTTP',
              +				uaUrl: 'http://search.cpan.org/dist/POE-Component-Client-HTTP/',
              +				uaCompany: '',
              +				uaCompanyUrl: '',
              +				uaIcon: 'perl.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=POE-Component-Client-HTTP'
              +			}
              +		},
              +		'111': {
              +			typeId: '5',
              +			metadata: {
              +				uaFamily: 'Snoopy',
              +				uaUrl: 'http://sourceforge.net/projects/snoopy',
              +				uaCompany: 'Andrei Zmievski',
              +				uaCompanyUrl: '',
              +				uaIcon: 'unknown.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Snoopy'
              +			}
              +		},
              +		'117': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'NCSA Mosaic',
              +				uaUrl: 'http://www.ncsa.uiuc.edu/Projects/mosaic.html',
              +				uaCompany: 'NCSA',
              +				uaCompanyUrl: 'http://www.ncsa.uiuc.edu/',
              +				uaIcon: 'ncsa.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=NCSA Mosaic'
              +			}
              +		},
              +		'119': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Kapiko',
              +				uaUrl: 'http://ufoxlab.googlepages.com/',
              +				uaCompany: 'Ufox lab.',
              +				uaCompanyUrl: '',
              +				uaIcon: 'kapiko.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Kapiko'
              +			}
              +		},
              +		'120': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Chrome',
              +				uaUrl: 'http://www.google.com/chrome',
              +				uaCompany: 'Google Inc.',
              +				uaCompanyUrl: 'http://www.google.com/',
              +				uaIcon: 'chrome.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Chrome'
              +			}
              +		},
              +		'121': {
              +			typeId: '5',
              +			metadata: {
              +				uaFamily: 'Adobe AIR runtime',
              +				uaUrl: 'http://www.adobe.com/products/air/',
              +				uaCompany: 'Adobe Systems',
              +				uaCompanyUrl: 'http://www.adobe.com/',
              +				uaIcon: 'adobeair.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Adobe AIR runtime'
              +			}
              +		},
              +		'122': {
              +			typeId: '5',
              +			metadata: {
              +				uaFamily: 'LWP::Simple',
              +				uaUrl: 'http://search.cpan.org/perldoc?LWP::Simple',
              +				uaCompany: 'CPAN',
              +				uaCompanyUrl: 'http://cpan.org/',
              +				uaIcon: 'lwp.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=LWP::Simple'
              +			}
              +		},
              +		'123': {
              +			typeId: '5',
              +			metadata: {
              +				uaFamily: 'WWW::Mechanize',
              +				uaUrl: 'http://search.cpan.org/dist/WWW-Mechanize/',
              +				uaCompany: 'CPAN',
              +				uaCompanyUrl: 'http://cpan.org/',
              +				uaIcon: 'lwp.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=WWW::Mechanize'
              +			}
              +		},
              +		'124': {
              +			typeId: '10',
              +			metadata: {
              +				uaFamily: 'Xenu',
              +				uaUrl: 'http://home.snafu.de/tilman/xenulink.html',
              +				uaCompany: 'Tilman Hausherr',
              +				uaCompanyUrl: 'http://home.snafu.de/tilman/index.html',
              +				uaIcon: 'xenu.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Xenu'
              +			}
              +		},
              +		'125': {
              +			typeId: '1',
              +			metadata: {
              +				uaFamily: 'SiteSucker',
              +				uaUrl: 'http://www.sitesucker.us/',
              +				uaCompany: 'Rick Cranisky',
              +				uaCompanyUrl: '',
              +				uaIcon: 'sitesucker.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=SiteSucker'
              +			}
              +		},
              +		'126': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Arora',
              +				uaUrl: 'http://arora.googlecode.com/',
              +				uaCompany: 'Benjamin Meyer',
              +				uaCompanyUrl: 'http://www.blogger.com/profile/00185079236289035707',
              +				uaIcon: 'arora.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Arora'
              +			}
              +		},
              +		'128': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Firefox (Shiretoko)',
              +				uaUrl: 'http://www.mozilla.org/projects/firefox/3.1a1/releasenotes/',
              +				uaCompany: 'Mozilla Foundation',
              +				uaCompanyUrl: 'http://www.mozilla.org/',
              +				uaIcon: 'firefox.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Firefox (Shiretoko)'
              +			}
              +		},
              +		'129': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Firefox (Minefield)',
              +				uaUrl: 'http://www.mozilla.org/projects/minefield/',
              +				uaCompany: 'Mozilla Foundation',
              +				uaCompanyUrl: 'http://www.mozilla.org/',
              +				uaIcon: 'firefox.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Firefox (Minefield)'
              +			}
              +		},
              +		'130': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Iron',
              +				uaUrl: 'http://www.srware.net/en/software_srware_iron.php',
              +				uaCompany: '',
              +				uaCompanyUrl: '',
              +				uaIcon: 'iron.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Iron'
              +			}
              +		},
              +		'131': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Lobo',
              +				uaUrl: 'http://lobobrowser.org/java-browser.jsp',
              +				uaCompany: '',
              +				uaCompanyUrl: '',
              +				uaIcon: 'lobo.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Lobo'
              +			}
              +		},
              +		'132': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Links',
              +				uaUrl: 'http://links.twibright.com/',
              +				uaCompany: 'Twibright Labs',
              +				uaCompanyUrl: 'http://twibright.com/',
              +				uaIcon: 'links2.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Links'
              +			}
              +		},
              +		'133': {
              +			typeId: '3',
              +			metadata: {
              +				uaFamily: 'Mobile Firefox',
              +				uaUrl: 'http://www.mozilla.com/mobile/',
              +				uaCompany: 'Mozilla Foundation',
              +				uaCompanyUrl: 'http://www.mozilla.org/',
              +				uaIcon: 'firefox.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Mobile Firefox'
              +			}
              +		},
              +		'134': {
              +			typeId: '4',
              +			metadata: {
              +				uaFamily: 'Lotus Notes',
              +				uaUrl: 'http://www.ibm.com/software/lotus/products/notes/',
              +				uaCompany: 'IBM',
              +				uaCompanyUrl: 'http://www.ibm.com/',
              +				uaIcon: 'lotusnotes.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Lotus Notes'
              +			}
              +		},
              +		'135': {
              +			typeId: '6',
              +			metadata: {
              +				uaFamily: 'Klondike',
              +				uaUrl: 'http://web.archive.org/web/20071012053920/www.apachesoftware.com/products.html',
              +				uaCompany: 'Apache Software Consulting Inc.',
              +				uaCompanyUrl: 'http://web.archive.org/web/*/www.apachesoftware.com',
              +				uaIcon: 'klondike.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Klondike'
              +			}
              +		},
              +		'136': {
              +			typeId: '6',
              +			metadata: {
              +				uaFamily: 'WapTiger',
              +				uaUrl: 'http://www.waptiger.com/waptiger/',
              +				uaCompany: 'infotiger',
              +				uaCompanyUrl: 'http://www.infotiger.com/',
              +				uaIcon: 'wap.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=WapTiger'
              +			}
              +		},
              +		'137': {
              +			typeId: '10',
              +			metadata: {
              +				uaFamily: 'W3C Validator',
              +				uaUrl: 'http://validator.w3.org/',
              +				uaCompany: 'World Wide Web Consortium',
              +				uaCompanyUrl: 'http://www.w3.org/',
              +				uaIcon: 'w3.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=W3C Validator'
              +			}
              +		},
              +		'138': {
              +			typeId: '10',
              +			metadata: {
              +				uaFamily: 'W3C Checklink',
              +				uaUrl: 'http://validator.w3.org/checklink',
              +				uaCompany: 'World Wide Web Consortium',
              +				uaCompanyUrl: 'http://www.w3.org/',
              +				uaIcon: 'w3.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=W3C Checklink'
              +			}
              +		},
              +		'139': {
              +			typeId: '10',
              +			metadata: {
              +				uaFamily: 'HTMLParser',
              +				uaUrl: 'http://htmlparser.sourceforge.net/',
              +				uaCompany: '',
              +				uaCompanyUrl: '',
              +				uaIcon: 'htmlparser.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=HTMLParser'
              +			}
              +		},
              +		'140': {
              +			typeId: '5',
              +			metadata: {
              +				uaFamily: 'Java',
              +				uaUrl: 'http://www.sun.com/java/',
              +				uaCompany: 'Sun Microsystems, Inc.',
              +				uaCompanyUrl: 'http://www.sun.com/',
              +				uaIcon: 'java.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Java'
              +			}
              +		},
              +		'141': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Bolt',
              +				uaUrl: 'http://boltbrowser.com/',
              +				uaCompany: 'Bitstream',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bolt.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Bolt'
              +			}
              +		},
              +		'142': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Demeter',
              +				uaUrl: 'http://www.hurrikenux.com/Demeter/',
              +				uaCompany: 'hurrikenux Creative',
              +				uaCompanyUrl: 'http://www.hurrikenux.com/',
              +				uaIcon: 'demeter.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Demeter'
              +			}
              +		},
              +		'143': {
              +			typeId: '5',
              +			metadata: {
              +				uaFamily: 'FeedParser',
              +				uaUrl: 'http://feedparser.org/',
              +				uaCompany: 'Mark Pilgrim',
              +				uaCompanyUrl: 'http://diveintomark.org/',
              +				uaIcon: 'lib.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=FeedParser'
              +			}
              +		},
              +		'144': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Orca',
              +				uaUrl: 'http://www.orcabrowser.com/',
              +				uaCompany: 'Avant Force team',
              +				uaCompanyUrl: 'http://www.avantforce.com/',
              +				uaIcon: 'orca.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Orca'
              +			}
              +		},
              +		'145': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Fluid',
              +				uaUrl: 'http://fluidapp.com/',
              +				uaCompany: 'Todd Ditchendorf',
              +				uaCompanyUrl: 'http://www.ditchnet.org/wp/',
              +				uaIcon: 'fluid.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Fluid'
              +			}
              +		},
              +		'146': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'Bookdog',
              +				uaUrl: 'http://sheepsystems.com/products/bookdog/',
              +				uaCompany: 'Sheep Systems',
              +				uaCompanyUrl: 'http://sheepsystems.com/',
              +				uaIcon: 'bookdog.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Bookdog'
              +			}
              +		},
              +		'147': {
              +			typeId: '50',
              +			metadata: {
              +				uaFamily: 'Anonymouse.org',
              +				uaUrl: 'http://anonymouse.org/',
              +				uaCompany: 'Anonymous S.A.',
              +				uaCompanyUrl: 'http://anonymouse.org/',
              +				uaIcon: 'anonymouse_org.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Anonymouse.org'
              +			}
              +		},
              +		'148': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Midori',
              +				uaUrl: 'http://twotoasts.de/index.php/midori/',
              +				uaCompany: 'Christian Dywan',
              +				uaCompanyUrl: 'http://www.twotoasts.de/',
              +				uaIcon: 'midori.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Midori'
              +			}
              +		},
              +		'149': {
              +			typeId: '18',
              +			metadata: {
              +				uaFamily: 'Boxxe',
              +				uaUrl: '',
              +				uaCompany: 'Team boxee',
              +				uaCompanyUrl: 'http://www.boxee.tv/',
              +				uaIcon: 'boxee.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Boxxe'
              +			}
              +		},
              +		'150': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'gPodder',
              +				uaUrl: 'http://gpodder.org/',
              +				uaCompany: 'Thomas Perl and the gPodder Team',
              +				uaCompanyUrl: '',
              +				uaIcon: 'gpodder.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=gPodder'
              +			}
              +		},
              +		'151': {
              +			typeId: '3',
              +			metadata: {
              +				uaFamily: 'Obigo',
              +				uaUrl: 'http://en.wikipedia.org/wiki/Obigo_Browser',
              +				uaCompany: 'Obigo Ltd',
              +				uaCompanyUrl: 'http://www.obigo.com/',
              +				uaIcon: 'obigo.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Obigo'
              +			}
              +		},
              +		'152': {
              +			typeId: '3',
              +			metadata: {
              +				uaFamily: 'SEMC Browser',
              +				uaUrl: '',
              +				uaCompany: 'Sony Ericsson Mobile Communications AB',
              +				uaCompanyUrl: 'http://www.sonyericsson.com/',
              +				uaIcon: 'semc.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=SEMC Browser'
              +			}
              +		},
              +		'153': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Firefox (GranParadiso)',
              +				uaUrl: 'https://wiki.mozilla.org/Firefox3',
              +				uaCompany: 'Mozilla Foundation',
              +				uaCompanyUrl: 'http://www.mozilla.org/',
              +				uaIcon: 'firefox.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Firefox (GranParadiso)'
              +			}
              +		},
              +		'154': {
              +			typeId: '10',
              +			metadata: {
              +				uaFamily: 'WDG Validator',
              +				uaUrl: 'http://www.htmlhelp.com/tools/validator/',
              +				uaCompany: 'Web Design Group',
              +				uaCompanyUrl: 'http://www.htmlhelp.com/',
              +				uaIcon: 'wdg.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=WDG Validator'
              +			}
              +		},
              +		'155': {
              +			typeId: '10',
              +			metadata: {
              +				uaFamily: 'WDG CSSCheck',
              +				uaUrl: 'http://www.htmlhelp.com/tools/csscheck/',
              +				uaCompany: 'Web Design Group',
              +				uaCompanyUrl: 'http://www.htmlhelp.com/',
              +				uaIcon: 'wdg.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=WDG CSSCheck'
              +			}
              +		},
              +		'156': {
              +			typeId: '10',
              +			metadata: {
              +				uaFamily: 'WDG Page Valet',
              +				uaUrl: 'http://valet.htmlhelp.com/page/',
              +				uaCompany: 'Web Design Group',
              +				uaCompanyUrl: 'http://www.htmlhelp.com/',
              +				uaIcon: 'wdg.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=WDG Page Valet'
              +			}
              +		},
              +		'157': {
              +			typeId: '3',
              +			metadata: {
              +				uaFamily: 'IE Mobile',
              +				uaUrl: 'http://www.microsoft.com/windowsmobile/en-us/downloads/microsoft/internet-explorer-mobile.mspx',
              +				uaCompany: 'Microsoft Corporation.',
              +				uaCompanyUrl: 'http://www.microsoft.com/',
              +				uaIcon: 'iemobile.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=IE Mobile'
              +			}
              +		},
              +		'158': {
              +			typeId: '3',
              +			metadata: {
              +				uaFamily: 'BlackBerry Browser',
              +				uaUrl: 'http://www.blackberry.com/',
              +				uaCompany: 'Research In Motion Limited',
              +				uaCompanyUrl: 'http://www.rim.com/',
              +				uaIcon: 'blackberry.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=BlackBerry Browser'
              +			}
              +		},
              +		'159': {
              +			typeId: '3',
              +			metadata: {
              +				uaFamily: 'Polaris',
              +				uaUrl: 'http://www.infraware.co.kr/eng/01_product/product02.asp',
              +				uaCompany: 'Infraware',
              +				uaCompanyUrl: 'http://www.infraware.co.kr/',
              +				uaIcon: 'polaris.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Polaris'
              +			}
              +		},
              +		'160': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Hv3',
              +				uaUrl: 'http://tkhtml.tcl.tk/hv3.html',
              +				uaCompany: 'tkhtml.tcl.tk',
              +				uaCompanyUrl: 'http://tkhtml.tcl.tk/',
              +				uaIcon: 'hv3.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Hv3'
              +			}
              +		},
              +		'161': {
              +			typeId: '6',
              +			metadata: {
              +				uaFamily: 'WinWap',
              +				uaUrl: 'http://www.winwap.com/mobile_applications/winwap_browser',
              +				uaCompany: 'Winwap Technologies',
              +				uaCompanyUrl: 'http://www.winwap.com/',
              +				uaIcon: 'winwap.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=WinWap'
              +			}
              +		},
              +		'162': {
              +			typeId: '18',
              +			metadata: {
              +				uaFamily: 'XBMC',
              +				uaUrl: 'http://xbmc.org/',
              +				uaCompany: 'Team-XBMC',
              +				uaCompanyUrl: 'http://xbmc.org/about/team/',
              +				uaIcon: 'xbmc.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=XBMC'
              +			}
              +		},
              +		'163': {
              +			typeId: '5',
              +			metadata: {
              +				uaFamily: 'XML-RPC for PHP',
              +				uaUrl: 'http://phpxmlrpc.sourceforge.net/',
              +				uaCompany: '',
              +				uaCompanyUrl: '',
              +				uaIcon: 'php-xmlrpc.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=XML-RPC for PHP'
              +			}
              +		},
              +		'165': {
              +			typeId: '18',
              +			metadata: {
              +				uaFamily: 'FlyCast',
              +				uaUrl: 'http://www.flycast.fm/',
              +				uaCompany: 'FlyCast Inc.',
              +				uaCompanyUrl: '',
              +				uaIcon: 'flycast.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=FlyCast'
              +			}
              +		},
              +		'166': {
              +			typeId: '15',
              +			metadata: {
              +				uaFamily: 'Bloglines',
              +				uaUrl: 'http://www.bloglines.com/',
              +				uaCompany: 'IAS Search & Media',
              +				uaCompanyUrl: 'http://www.iac.com/',
              +				uaIcon: 'bloglines.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Bloglines'
              +			}
              +		},
              +		'167': {
              +			typeId: '15',
              +			metadata: {
              +				uaFamily: 'Gregarius',
              +				uaUrl: 'http://devlog.gregarius.net/',
              +				uaCompany: 'Marco Bonetti',
              +				uaCompanyUrl: 'http://www.linkedin.com/in/mbonetti',
              +				uaIcon: 'gregarius.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Gregarius'
              +			}
              +		},
              +		'168': {
              +			typeId: '5',
              +			metadata: {
              +				uaFamily: 'SimplePie',
              +				uaUrl: 'http://simplepie.org/',
              +				uaCompany: 'Ryan Parman and Geoffrey Sneddon',
              +				uaCompanyUrl: '',
              +				uaIcon: 'simplepie.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=SimplePie'
              +			}
              +		},
              +		'169': {
              +			typeId: '5',
              +			metadata: {
              +				uaFamily: 'PycURL',
              +				uaUrl: 'http://pycurl.sourceforge.net/',
              +				uaCompany: '',
              +				uaCompanyUrl: '',
              +				uaIcon: 'curl.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=PycURL'
              +			}
              +		},
              +		'170': {
              +			typeId: '15',
              +			metadata: {
              +				uaFamily: 'Apple-PubSub',
              +				uaUrl: 'http://developer.apple.com/documentation/Darwin/Reference/ManPages/man1/pubsub.1.html',
              +				uaCompany: 'Apple Inc.',
              +				uaCompanyUrl: 'http://www.apple.com/',
              +				uaIcon: 'apple.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Apple-PubSub'
              +			}
              +		},
              +		'171': {
              +			typeId: '15',
              +			metadata: {
              +				uaFamily: 'Feedfetcher-Google',
              +				uaUrl: 'http://www.google.com/feedfetcher.html',
              +				uaCompany: 'Google',
              +				uaCompanyUrl: 'http://www.google.com/',
              +				uaIcon: 'feedfetcher-google.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Feedfetcher-Google'
              +			}
              +		},
              +		'172': {
              +			typeId: '10',
              +			metadata: {
              +				uaFamily: 'FeedValidator',
              +				uaUrl: 'http://feedvalidator.org/',
              +				uaCompany: 'Mark Pilgrim',
              +				uaCompanyUrl: 'http://diveintomark.org/',
              +				uaIcon: 'feedvalidator.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=FeedValidator'
              +			}
              +		},
              +		'173': {
              +			typeId: '5',
              +			metadata: {
              +				uaFamily: 'MagpieRSS',
              +				uaUrl: 'http://magpierss.sourceforge.net/',
              +				uaCompany: 'kellan',
              +				uaCompanyUrl: '',
              +				uaIcon: 'magpierss.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=MagpieRSS'
              +			}
              +		},
              +		'174': {
              +			typeId: '15',
              +			metadata: {
              +				uaFamily: 'BlogBridge',
              +				uaUrl: 'http://www.blogbridge.com/',
              +				uaCompany: 'Salas Associates, Inc.',
              +				uaCompanyUrl: '',
              +				uaIcon: 'blogbridge.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=BlogBridge'
              +			}
              +		},
              +		'175': {
              +			typeId: '18',
              +			metadata: {
              +				uaFamily: 'Miro',
              +				uaUrl: 'http://www.getmiro.com/',
              +				uaCompany: 'Participatory Culture Foundation',
              +				uaCompanyUrl: 'http://www.participatoryculture.org/',
              +				uaIcon: 'miro.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Miro'
              +			}
              +		},
              +		'176': {
              +			typeId: '15',
              +			metadata: {
              +				uaFamily: 'Liferea',
              +				uaUrl: 'http://liferea.sourceforge.net/',
              +				uaCompany: '',
              +				uaCompanyUrl: '',
              +				uaIcon: 'liferea.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Liferea'
              +			}
              +		},
              +		'177': {
              +			typeId: '15',
              +			metadata: {
              +				uaFamily: 'Seznam RSS reader',
              +				uaUrl: '',
              +				uaCompany: 'Seznam.cz, a.s.',
              +				uaCompanyUrl: 'http://www.seznam.cz/',
              +				uaIcon: 'seznamrssreader.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Seznam RSS reader'
              +			}
              +		},
              +		'178': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'PHP',
              +				uaUrl: 'http://php.net/',
              +				uaCompany: 'The PHP Group',
              +				uaCompanyUrl: '',
              +				uaIcon: 'php.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=PHP'
              +			}
              +		},
              +		'179': {
              +			typeId: '10',
              +			metadata: {
              +				uaFamily: 'REL Link Checker Lite',
              +				uaUrl: 'http://www.relsoftware.com/rlc/',
              +				uaCompany: 'REL Software, Inc.',
              +				uaCompanyUrl: 'http://www.relsoftware.com/company/',
              +				uaIcon: 'RELlinkchecker.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=REL Link Checker Lite'
              +			}
              +		},
              +		'180': {
              +			typeId: '15',
              +			metadata: {
              +				uaFamily: 'CPG Dragonfly RSS Module',
              +				uaUrl: 'http://dragonflycms.org/',
              +				uaCompany: '',
              +				uaCompanyUrl: '',
              +				uaIcon: 'dragonflycms.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=CPG Dragonfly RSS Module'
              +			}
              +		},
              +		'181': {
              +			typeId: '15',
              +			metadata: {
              +				uaFamily: 'Newsbeuter',
              +				uaUrl: 'http://www.newsbeuter.org/',
              +				uaCompany: 'Andreas Krennmair',
              +				uaCompanyUrl: 'http://synflood.at/',
              +				uaIcon: 'newsbeuter.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Newsbeuter'
              +			}
              +		},
              +		'182': {
              +			typeId: '10',
              +			metadata: {
              +				uaFamily: 'W3C CSS Validator',
              +				uaUrl: 'http://jigsaw.w3.org/css-validator/',
              +				uaCompany: 'World Wide Web Consortium',
              +				uaCompanyUrl: 'http://www.w3.org/',
              +				uaIcon: 'w3.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=W3C CSS Validator'
              +			}
              +		},
              +		'183': {
              +			typeId: '10',
              +			metadata: {
              +				uaFamily: 'PHP link checker',
              +				uaUrl: 'http://www.hotscripts.com/listing/php-link-checker/',
              +				uaCompany: '',
              +				uaCompanyUrl: '',
              +				uaIcon: 'php.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=PHP link checker'
              +			}
              +		},
              +		'184': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'GoldenPod',
              +				uaUrl: 'http://random.zerodogg.org/goldenpod',
              +				uaCompany: 'Eskild Hustvedt',
              +				uaCompanyUrl: 'http://random.zerodogg.org/',
              +				uaIcon: 'perl.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=GoldenPod'
              +			}
              +		},
              +		'185': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Cheshire',
              +				uaUrl: 'http://greenhouse.aol.com/prod.jsp?prod_id=32',
              +				uaCompany: 'America Online, Inc.',
              +				uaCompanyUrl: 'http://www.aol.com/',
              +				uaIcon: 'aol.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Cheshire'
              +			}
              +		},
              +		'187': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'CometBird',
              +				uaUrl: 'http://www.cometbird.com/',
              +				uaCompany: 'cometbird.com',
              +				uaCompanyUrl: '',
              +				uaIcon: 'cometbird.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=CometBird'
              +			}
              +		},
              +		'188': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'IceCat',
              +				uaUrl: 'http://www.gnu.org/software/gnuzilla/',
              +				uaCompany: 'Free Software Foundation, Inc.',
              +				uaCompanyUrl: 'http://www.fsf.org/',
              +				uaIcon: 'icecat.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=IceCat'
              +			}
              +		},
              +		'189': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Stainless',
              +				uaUrl: 'http://www.stainlessapp.com/',
              +				uaCompany: 'Mesa Dynamics, LLC',
              +				uaCompanyUrl: 'http://www.mesadynamics.com/',
              +				uaIcon: 'stainless.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Stainless'
              +			}
              +		},
              +		'190': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'Prism',
              +				uaUrl: 'http://prism.mozilla.com/',
              +				uaCompany: 'Mozilla Labs',
              +				uaCompanyUrl: 'http://labs.mozilla.com/',
              +				uaIcon: 'prism.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Prism'
              +			}
              +		},
              +		'191': {
              +			typeId: '18',
              +			metadata: {
              +				uaFamily: 'MPlayer',
              +				uaUrl: 'http://www.mplayerhq.hu/',
              +				uaCompany: 'The MPlayer Project',
              +				uaCompanyUrl: '',
              +				uaIcon: 'mplayer.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=MPlayer'
              +			}
              +		},
              +		'192': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'ActiveXperts Network Monitor',
              +				uaUrl: 'http://www.activexperts.com/activmonitor/',
              +				uaCompany: 'ActiveXperts Software B.V.',
              +				uaCompanyUrl: 'http://www.activexperts.com/',
              +				uaIcon: 'activexperts-network-monitor.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=ActiveXperts Network Monitor'
              +			}
              +		},
              +		'193': {
              +			typeId: '3',
              +			metadata: {
              +				uaFamily: 'Motorola Internet Browser',
              +				uaUrl: 'http://www.motorola.com/content.jsp?globalObjectId=1827-4343',
              +				uaCompany: 'Motorola, Inc.',
              +				uaCompanyUrl: 'http://www.motorola.com/',
              +				uaIcon: 'mib.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Motorola Internet Browser'
              +			}
              +		},
              +		'194': {
              +			typeId: '15',
              +			metadata: {
              +				uaFamily: 'Abilon',
              +				uaUrl: '',
              +				uaCompany: 'SisyphSoft',
              +				uaCompanyUrl: 'http://web.archive.org/web/20050721080030/http://www.abilon.org/',
              +				uaIcon: 'abilon.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Abilon'
              +			}
              +		},
              +		'195': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'HTTP nagios plugin',
              +				uaUrl: '',
              +				uaCompany: 'Nagios Enterprises, LLC.',
              +				uaCompanyUrl: 'http://www.nagios.org/',
              +				uaIcon: 'nagios.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=HTTP nagios plugin'
              +			}
              +		},
              +		'196': {
              +			typeId: '18',
              +			metadata: {
              +				uaFamily: 'Windows Media Player',
              +				uaUrl: 'http://www.microsoft.com/windows/windowsmedia/',
              +				uaCompany: 'Microsoft Corporation.',
              +				uaCompanyUrl: 'http://www.microsoft.com/',
              +				uaIcon: 'wmp.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Windows Media Player'
              +			}
              +		},
              +		'197': {
              +			typeId: '18',
              +			metadata: {
              +				uaFamily: 'VLC media player',
              +				uaUrl: 'http://www.videolan.org/vlc/',
              +				uaCompany: 'VideoLAN team',
              +				uaCompanyUrl: 'http://www.videolan.org/',
              +				uaIcon: 'vlc.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=VLC media player'
              +			}
              +		},
              +		'198': {
              +			typeId: '10',
              +			metadata: {
              +				uaFamily: 'P3P Validator',
              +				uaUrl: 'http://www.w3.org/P3P/validator.html',
              +				uaCompany: 'World Wide Web Consortium',
              +				uaCompanyUrl: 'http://www.w3.org/',
              +				uaIcon: 'w3.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=P3P Validator'
              +			}
              +		},
              +		'199': {
              +			typeId: '10',
              +			metadata: {
              +				uaFamily: 'CSE HTML Validator',
              +				uaUrl: 'http://online.htmlvalidator.com/php/onlinevallite.php',
              +				uaCompany: 'AI Internet Solutions',
              +				uaCompanyUrl: 'http://www.htmlvalidator.com/',
              +				uaIcon: 'csehtmlvalidator.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=CSE HTML Validator'
              +			}
              +		},
              +		'200': {
              +			typeId: '15',
              +			metadata: {
              +				uaFamily: 'Omea Reader',
              +				uaUrl: 'http://www.jetbrains.com/omea/reader/',
              +				uaCompany: 'JetBrains',
              +				uaCompanyUrl: 'http://www.jetbrains.com/',
              +				uaIcon: 'omeareader.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Omea Reader'
              +			}
              +		},
              +		'201': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'GSiteCrawler',
              +				uaUrl: 'http://gsitecrawler.com/',
              +				uaCompany: 'SOFTplus Entwicklungen GmbH',
              +				uaCompanyUrl: 'http://www.softplus.net/',
              +				uaIcon: 'gsitecrawler.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=GSiteCrawler'
              +			}
              +		},
              +		'202': {
              +			typeId: '15',
              +			metadata: {
              +				uaFamily: 'YahooFeedSeeker',
              +				uaUrl: 'http://publisher.yahoo.com/rssguide',
              +				uaCompany: 'Yahoo! Inc',
              +				uaCompanyUrl: 'http://www.yahoo.com/',
              +				uaIcon: 'YahooFeedSeeker.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=YahooFeedSeeker'
              +			}
              +		},
              +		'204': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'TheWorld Browser',
              +				uaUrl: 'http://www.theworld.cn/twen/',
              +				uaCompany: 'Phoenix Studio',
              +				uaCompanyUrl: 'http://www.phoenixstudio.org/',
              +				uaIcon: 'the_world.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=TheWorld Browser'
              +			}
              +		},
              +		'205': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'WebCollage',
              +				uaUrl: 'http://www.jwz.org/webcollage/',
              +				uaCompany: 'Jamie Zawinski',
              +				uaCompanyUrl: 'http://www.jwz.org/',
              +				uaIcon: 'webcollage.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=WebCollage'
              +			}
              +		},
              +		'206': {
              +			typeId: '15',
              +			metadata: {
              +				uaFamily: 'NewsGatorOnline',
              +				uaUrl: 'http://www.newsgator.com/',
              +				uaCompany: 'NewsGator Technologies, Inc.',
              +				uaCompanyUrl: 'http://www.newsgator.com/companyinfo/default.aspx',
              +				uaIcon: 'newsgator-online.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=NewsGatorOnline'
              +			}
              +		},
              +		'207': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'PRTG Network Monitor',
              +				uaUrl: 'http://www.paessler.com/prtg',
              +				uaCompany: 'Paessler AG',
              +				uaCompanyUrl: 'http://www.paessler.com/',
              +				uaIcon: 'PRTG_Network_Monitor.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=PRTG Network Monitor'
              +			}
              +		},
              +		'208': {
              +			typeId: '18',
              +			metadata: {
              +				uaFamily: 'Songbird',
              +				uaUrl: 'http://getsongbird.com/',
              +				uaCompany: 'Pioneers of the Inevitable',
              +				uaCompanyUrl: 'http://getsongbird.com/about/',
              +				uaIcon: 'songbird.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Songbird'
              +			}
              +		},
              +		'209': {
              +			typeId: '18',
              +			metadata: {
              +				uaFamily: 'RSS Radio',
              +				uaUrl: 'http://www.dorada.co.uk/',
              +				uaCompany: 'Dorada Software',
              +				uaCompanyUrl: '',
              +				uaIcon: 'rssradio.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=RSS Radio'
              +			}
              +		},
              +		'210': {
              +			typeId: '5',
              +			metadata: {
              +				uaFamily: 'Feed::Find',
              +				uaUrl: 'http://search.cpan.org/dist/Feed-Find/',
              +				uaCompany: 'Benjamin Trott',
              +				uaCompanyUrl: '',
              +				uaIcon: 'perl.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Feed::Find'
              +			}
              +		},
              +		'211': {
              +			typeId: '3',
              +			metadata: {
              +				uaFamily: 'Palm Pre web browser',
              +				uaUrl: 'http://www.palm.com/us/products/phones/pre/index.html',
              +				uaCompany: 'Palm Inc.',
              +				uaCompanyUrl: 'http://www.palm.com/',
              +				uaIcon: 'palmpre.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Palm Pre web browser'
              +			}
              +		},
              +		'212': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Firefox (BonEcho)',
              +				uaUrl: 'http://www.mozilla.org/projects/bonecho/releases/2.0a1.html',
              +				uaCompany: 'Mozilla Foundation',
              +				uaCompanyUrl: 'http://www.mozilla.org/',
              +				uaIcon: 'firefox.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Firefox (BonEcho)'
              +			}
              +		},
              +		'213': {
              +			typeId: '18',
              +			metadata: {
              +				uaFamily: 'QuickTime',
              +				uaUrl: 'http://www.apple.com/quicktime/',
              +				uaCompany: 'Apple Inc.',
              +				uaCompanyUrl: 'http://www.apple.com/',
              +				uaIcon: 'quicktime.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=QuickTime'
              +			}
              +		},
              +		'214': {
              +			typeId: '5',
              +			metadata: {
              +				uaFamily: 'PHPcrawl',
              +				uaUrl: 'http://phpcrawl.cuab.de/',
              +				uaCompany: 'Uwe Hunfeld',
              +				uaCompanyUrl: '',
              +				uaIcon: 'php.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=PHPcrawl'
              +			}
              +		},
              +		'216': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'GreenBrowser',
              +				uaUrl: 'http://www.morequick.com/indexen.htm',
              +				uaCompany: 'More Quick Tools',
              +				uaCompanyUrl: 'http://www.morequick.com/',
              +				uaIcon: 'green_browser.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=GreenBrowser'
              +			}
              +		},
              +		'217': {
              +			typeId: '15',
              +			metadata: {
              +				uaFamily: 'Awasu',
              +				uaUrl: 'http://www.awasu.com/',
              +				uaCompany: 'Awasu Pty. Ltd.',
              +				uaCompanyUrl: '',
              +				uaIcon: 'awasu.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Awasu'
              +			}
              +		},
              +		'218': {
              +			typeId: '18',
              +			metadata: {
              +				uaFamily: 'CorePlayer',
              +				uaUrl: 'http://www.coreplayer.com/',
              +				uaCompany: 'CoreCodec, inc.',
              +				uaCompanyUrl: '',
              +				uaIcon: 'CorePlayer.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=CorePlayer'
              +			}
              +		},
              +		'219': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'QtWeb',
              +				uaUrl: 'http://www.qtweb.net/',
              +				uaCompany: 'QtWeb.NET',
              +				uaCompanyUrl: '',
              +				uaIcon: 'qt_web.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=QtWeb'
              +			}
              +		},
              +		'220': {
              +			typeId: '3',
              +			metadata: {
              +				uaFamily: 'TeaShark',
              +				uaUrl: 'http://www.teashark.com/',
              +				uaCompany: 'TeaShark',
              +				uaCompanyUrl: '',
              +				uaIcon: 'teashark.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=TeaShark'
              +			}
              +		},
              +		'221': {
              +			typeId: '5',
              +			metadata: {
              +				uaFamily: 'LibSoup',
              +				uaUrl: 'http://live.gnome.org/LibSoup',
              +				uaCompany: 'The GNOME Project',
              +				uaCompanyUrl: 'http://www.gnome.org/',
              +				uaIcon: 'libsoup.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=LibSoup'
              +			}
              +		},
              +		'222': {
              +			typeId: '15',
              +			metadata: {
              +				uaFamily: 'NetNewsWire',
              +				uaUrl: 'http://www.newsgator.com/Individuals/NetNewsWire/',
              +				uaCompany: 'NewsGator Technologies, Inc.',
              +				uaCompanyUrl: 'http://www.newsgator.com/',
              +				uaIcon: 'netnewswire.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=NetNewsWire'
              +			}
              +		},
              +		'223': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'Google App Engine',
              +				uaUrl: 'http://code.google.com/appengine/',
              +				uaCompany: 'Google',
              +				uaCompanyUrl: 'http://www.google.com/',
              +				uaIcon: 'google_appengine.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Google App Engine'
              +			}
              +		},
              +		'225': {
              +			typeId: '3',
              +			metadata: {
              +				uaFamily: 'UC Browser',
              +				uaUrl: 'http://www.ucweb.com/English/UCbrowser/index.html',
              +				uaCompany: 'UCWEB Technology Ltd.',
              +				uaCompanyUrl: 'http://www.ucweb.com/',
              +				uaIcon: 'ucweb.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=UC Browser'
              +			}
              +		},
              +		'226': {
              +			typeId: '3',
              +			metadata: {
              +				uaFamily: 'Nokia Web Browser',
              +				uaUrl: 'http://nokia.com/browser',
              +				uaCompany: 'Nokia',
              +				uaCompanyUrl: 'http://www.nokia.com/',
              +				uaIcon: 'nokia.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Nokia Web Browser'
              +			}
              +		},
              +		'227': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'LFTP',
              +				uaUrl: 'http://lftp.yar.ru/',
              +				uaCompany: 'Alexander V. Lukyanov',
              +				uaCompanyUrl: '',
              +				uaIcon: 'lftp.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=LFTP'
              +			}
              +		},
              +		'228': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Oregano',
              +				uaUrl: 'http://www.oreganouk.net/oregano2.html',
              +				uaCompany: 'Genesys Developments Ltd',
              +				uaCompanyUrl: 'http://www.oreganouk.net/',
              +				uaIcon: 'oregano.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Oregano'
              +			}
              +		},
              +		'229': {
              +			typeId: '5',
              +			metadata: {
              +				uaFamily: 'Summer',
              +				uaUrl: 'http://wrya.net/services/trac/summer',
              +				uaCompany: 'Robin Sonefors',
              +				uaCompanyUrl: 'http://flukkost.nu/',
              +				uaIcon: 'libsummer.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Summer'
              +			}
              +		},
              +		'230': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Acoo Browser',
              +				uaUrl: 'http://www.acoobrowser.com/',
              +				uaCompany: '',
              +				uaCompanyUrl: '',
              +				uaIcon: 'acco.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Acoo Browser'
              +			}
              +		},
              +		'231': {
              +			typeId: '15',
              +			metadata: {
              +				uaFamily: 'NewsFox',
              +				uaUrl: 'http://newsfox.mozdev.org/',
              +				uaCompany: 'NewsFox team',
              +				uaCompanyUrl: 'http://newsfox.mozdev.org/team.html',
              +				uaIcon: 'newsfox.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=NewsFox'
              +			}
              +		},
              +		'232': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Hydra Browser',
              +				uaUrl: 'http://hydrabrowser.com/',
              +				uaCompany: 'Quantum',
              +				uaCompanyUrl: '',
              +				uaIcon: 'hydrabrowser.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Hydra Browser'
              +			}
              +		},
              +		'233': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'wKiosk',
              +				uaUrl: 'http://www.app4mac.com/store/index.php?target=products&product_id=9',
              +				uaCompany: 'app4mac Inc.',
              +				uaCompanyUrl: 'http://www.app4mac.com/',
              +				uaIcon: 'wkiosk.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=wKiosk'
              +			}
              +		},
              +		'234': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'Paparazzi!',
              +				uaUrl: 'http://derailer.org/paparazzi/',
              +				uaCompany: 'Nate Weaver (Wevah)',
              +				uaCompanyUrl: 'http://derailer.org/',
              +				uaIcon: 'paparazzi.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Paparazzi!'
              +			}
              +		},
              +		'235': {
              +			typeId: '5',
              +			metadata: {
              +				uaFamily: 'xine',
              +				uaUrl: 'http://www.xine-project.org/',
              +				uaCompany: 'xine team',
              +				uaCompanyUrl: 'http://www.xine-project.org/authors',
              +				uaIcon: 'xine.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=xine'
              +			}
              +		},
              +		'236': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'webfs',
              +				uaUrl: 'http://plan9.bell-labs.com/magic/man2html/4/webfs',
              +				uaCompany: 'Lucent Technologies',
              +				uaCompanyUrl: 'http://plan9.bell-labs.com/plan9/',
              +				uaIcon: 'plan9.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=webfs'
              +			}
              +		},
              +		'237': {
              +			typeId: '15',
              +			metadata: {
              +				uaFamily: 'NewsBreak',
              +				uaUrl: 'http://www.iliumsoft.com/site/nw/newsbreak.php',
              +				uaCompany: 'Ilium Software, Inc.',
              +				uaCompanyUrl: 'http://www.iliumsoft.com/',
              +				uaIcon: 'newsbreak.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=NewsBreak'
              +			}
              +		},
              +		'238': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'LinkbackPlugin for Laconica',
              +				uaUrl: 'http://laconi.ca/',
              +				uaCompany: 'Laconica Developer Community',
              +				uaCompanyUrl: 'http://laconi.ca/trac/wiki/DeveloperCommunity',
              +				uaIcon: 'laconica.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=LinkbackPlugin for Laconica'
              +			}
              +		},
              +		'239': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'Microsoft WebDAV client',
              +				uaUrl: '',
              +				uaCompany: 'Microsoft Corporation.',
              +				uaCompanyUrl: 'http://www.microsoft.com/',
              +				uaIcon: 'webdav.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Microsoft WebDAV client'
              +			}
              +		},
              +		'240': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'GnomeVFS',
              +				uaUrl: 'http://developer.gnome.org/doc/API/2.0/gnome-vfs-2',
              +				uaCompany: 'The GNOME Project',
              +				uaCompanyUrl: 'http://www.gnome.org/',
              +				uaIcon: 'webdav.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=GnomeVFS'
              +			}
              +		},
              +		'241': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Uzbl',
              +				uaUrl: 'http://www.uzbl.org/',
              +				uaCompany: '',
              +				uaCompanyUrl: '',
              +				uaIcon: 'uzbl.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Uzbl'
              +			}
              +		},
              +		'242': {
              +			typeId: '10',
              +			metadata: {
              +				uaFamily: 'Cynthia',
              +				uaUrl: 'http://www.contentquality.com/',
              +				uaCompany: 'HiSoftware Inc.',
              +				uaCompanyUrl: 'http://www.hisoftware.com/',
              +				uaIcon: 'cynthia.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Cynthia'
              +			}
              +		},
              +		'243': {
              +			typeId: '15',
              +			metadata: {
              +				uaFamily: 'Sage',
              +				uaUrl: 'http://sage.mozdev.org',
              +				uaCompany: 'Peter Andrews',
              +				uaCompanyUrl: 'http://petea.org/',
              +				uaIcon: 'sage.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Sage'
              +			}
              +		},
              +		'244': {
              +			typeId: '18',
              +			metadata: {
              +				uaFamily: 'Banshee',
              +				uaUrl: 'http://banshee-project.org/',
              +				uaCompany: 'Novell, Inc.',
              +				uaCompanyUrl: 'http://www.novell.com/',
              +				uaIcon: 'banshee.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Banshee'
              +			}
              +		},
              +		'245': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Wyzo',
              +				uaUrl: 'http://www.wyzo.com/',
              +				uaCompany: 'Radical Software Ltd.',
              +				uaCompanyUrl: 'http://www.radicalsoft.com/',
              +				uaIcon: 'wyzo.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Wyzo'
              +			}
              +		},
              +		'246': {
              +			typeId: '15',
              +			metadata: {
              +				uaFamily: 'RSSOwl',
              +				uaUrl: 'http://www.rssowl.org/',
              +				uaCompany: 'Benjamin Pasero',
              +				uaCompanyUrl: '',
              +				uaIcon: 'rssowl.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=RSSOwl'
              +			}
              +		},
              +		'247': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'ABrowse',
              +				uaUrl: 'http://en.wikipedia.org/wiki/ABrowse',
              +				uaCompany: 'Kurt Skauen',
              +				uaCompanyUrl: 'http://www.syllable.org/',
              +				uaIcon: 'abrowse.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=ABrowse'
              +			}
              +		},
              +		'248': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'Funambol Outlook Sync Client',
              +				uaUrl: 'https://www.forge.funambol.org/download/',
              +				uaCompany: 'Funambol, Inc.',
              +				uaCompanyUrl: 'http://funambol.com/',
              +				uaIcon: 'funambol-outlook.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Funambol Outlook Sync Client'
              +			}
              +		},
              +		'249': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'Funambol Mozilla Sync Client',
              +				uaUrl: 'https://mozilla-plugin.forge.funambol.org/ ',
              +				uaCompany: 'Carlo Codega',
              +				uaCompanyUrl: 'http://sazilla.blogspot.com',
              +				uaIcon: 'funambol-mozilla.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Funambol Mozilla Sync Client'
              +			}
              +		},
              +		'250': {
              +			typeId: '15',
              +			metadata: {
              +				uaFamily: 'RSS Menu',
              +				uaUrl: 'http://www.edot-studios.com/webgroups2/index.php?menu_item=212',
              +				uaCompany: 'e dot studios',
              +				uaCompanyUrl: 'http://www.edot-studios.com/',
              +				uaIcon: 'rss_menu.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=RSS Menu'
              +			}
              +		},
              +		'251': {
              +			typeId: '18',
              +			metadata: {
              +				uaFamily: 'foobar2000',
              +				uaUrl: 'http://www.foobar2000.org/',
              +				uaCompany: 'Peter Pawlowski',
              +				uaCompanyUrl: '',
              +				uaIcon: 'foobar2000.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=foobar2000'
              +			}
              +		},
              +		'252': {
              +			typeId: '5',
              +			metadata: {
              +				uaFamily: 'GStreamer',
              +				uaUrl: 'http://gstreamer.freedesktop.org/',
              +				uaCompany: 'GStreamer community',
              +				uaCompanyUrl: 'http://gstreamer.freedesktop.org/',
              +				uaIcon: 'GStreamer.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=GStreamer'
              +			}
              +		},
              +		'253': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'NetFront Mobile Content Viewer',
              +				uaUrl: 'http://www.access-company.com/products/mobile_solutions/netfrontmobile/contentviewer/index.html',
              +				uaCompany: 'ACCESS CO., LTD.',
              +				uaCompanyUrl: 'http://www.access-company.com/',
              +				uaIcon: 'netfront.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=NetFront Mobile Content Viewer'
              +			}
              +		},
              +		'254': {
              +			typeId: '5',
              +			metadata: {
              +				uaFamily: 'PHP OpenID library',
              +				uaUrl: 'http://openidenabled.com/php-openid/',
              +				uaCompany: 'JanRain, Inc.',
              +				uaCompanyUrl: 'http://www.janrain.com/',
              +				uaIcon: 'PHP_OpenID_lib.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=PHP OpenID library'
              +			}
              +		},
              +		'255': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Blackbird',
              +				uaUrl: 'http://www.blackbirdbrowser.com/',
              +				uaCompany: '40A, Inc.',
              +				uaCompanyUrl: '',
              +				uaIcon: 'blackbird.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Blackbird'
              +			}
              +		},
              +		'256': {
              +			typeId: '15',
              +			metadata: {
              +				uaFamily: 'GreatNews',
              +				uaUrl: 'http://www.curiostudio.com/',
              +				uaCompany: 'Curio Studio',
              +				uaCompanyUrl: '',
              +				uaIcon: 'GreatNews.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=GreatNews'
              +			}
              +		},
              +		'257': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'DeskBrowse',
              +				uaUrl: 'http://www.deskbrowse.org/',
              +				uaCompany: 'Off Leash Developments, Inc',
              +				uaCompanyUrl: 'http://offleashdevelopments.com/',
              +				uaIcon: 'deskbrowse.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=DeskBrowse'
              +			}
              +		},
              +		'258': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'Tulip Chain',
              +				uaUrl: 'http://ostermiller.org/tulipchain/',
              +				uaCompany: 'Stephen "deadsea" Ostermiller',
              +				uaCompanyUrl: 'http://ostermiller.org/',
              +				uaIcon: 'TulipChain.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Tulip Chain'
              +			}
              +		},
              +		'259': {
              +			typeId: '1',
              +			metadata: {
              +				uaFamily: 'Axel',
              +				uaUrl: 'http://axel.alioth.debian.org/',
              +				uaCompany: 'Y Giridhar Appaji Nag',
              +				uaCompanyUrl: 'http://www.appaji.net/',
              +				uaIcon: 'terminal.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Axel'
              +			}
              +		},
              +		'260': {
              +			typeId: '3',
              +			metadata: {
              +				uaFamily: 'MicroB',
              +				uaUrl: 'http://en.wikipedia.org/wiki/MicroB',
              +				uaCompany: 'maemo project',
              +				uaCompanyUrl: 'http://maemo.org/',
              +				uaIcon: 'microb.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=MicroB'
              +			}
              +		},
              +		'261': {
              +			typeId: '3',
              +			metadata: {
              +				uaFamily: 'Tear',
              +				uaUrl: 'http://tear.garage.maemo.org/',
              +				uaCompany: 'Kamen Bundev',
              +				uaCompanyUrl: 'http://bundyo.org/',
              +				uaIcon: 'tear.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Tear'
              +			}
              +		},
              +		'262': {
              +			typeId: '10',
              +			metadata: {
              +				uaFamily: 'LinkExaminer',
              +				uaUrl: 'http://www.analogx.com/contents/download/Network/lnkexam/Freeware.htm',
              +				uaCompany: 'AnalogX, LLC.',
              +				uaCompanyUrl: 'http://www.analogx.com/',
              +				uaIcon: 'LinkExaminer.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=LinkExaminer'
              +			}
              +		},
              +		'263': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Abolimba',
              +				uaUrl: 'http://www.aborange.de/products/freeware/abolimba-multibrowser.php',
              +				uaCompany: 'Mathias Gerlach, Jochen Milchsack',
              +				uaCompanyUrl: 'http://www.aborange.de/',
              +				uaIcon: 'abolimba.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Abolimba'
              +			}
              +		},
              +		'264': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Beonex',
              +				uaUrl: 'http://www.beonex.com/',
              +				uaCompany: 'Ben Bucksch',
              +				uaCompanyUrl: 'http://www.bucksch.org/',
              +				uaIcon: 'beonex.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Beonex'
              +			}
              +		},
              +		'265': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'DocZilla',
              +				uaUrl: 'http://www.doczilla.com/',
              +				uaCompany: 'CITEC',
              +				uaCompanyUrl: 'http://www.citec.com/',
              +				uaIcon: 'doczilla.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=DocZilla'
              +			}
              +		},
              +		'266': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'retawq',
              +				uaUrl: 'http://retawq.sourceforge.net/',
              +				uaCompany: 'Arne Thoma\xdfen',
              +				uaCompanyUrl: '',
              +				uaIcon: 'terminal.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=retawq'
              +			}
              +		},
              +		'267': {
              +			typeId: '3',
              +			metadata: {
              +				uaFamily: 'Jasmine',
              +				uaUrl: '',
              +				uaCompany: 'SAMSUNG',
              +				uaCompanyUrl: 'http://www.samsung.com/',
              +				uaIcon: 'jasmine.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Jasmine'
              +			}
              +		},
              +		'268': {
              +			typeId: '3',
              +			metadata: {
              +				uaFamily: 'Opera Mini',
              +				uaUrl: 'http://www.operamini.com',
              +				uaCompany: 'Opera Software ASA.',
              +				uaCompanyUrl: 'http://www.opera.com/',
              +				uaIcon: 'opera.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Opera Mini'
              +			}
              +		},
              +		'269': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Dooble',
              +				uaUrl: 'http://dooble.sourceforge.net/',
              +				uaCompany: 'Dooble team',
              +				uaCompanyUrl: '',
              +				uaIcon: 'dooble.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Dooble'
              +			}
              +		},
              +		'270': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Madfox',
              +				uaUrl: 'http://en.wikipedia.org/wiki/Madfox',
              +				uaCompany: 'Robin Lu',
              +				uaCompanyUrl: '',
              +				uaIcon: 'madfox.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Madfox'
              +			}
              +		},
              +		'271': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'DownloadStudio',
              +				uaUrl: 'http://www.conceiva.com/products/downloadstudio/default.asp',
              +				uaCompany: 'Conceiva',
              +				uaCompanyUrl: 'http://www.conceiva.com/',
              +				uaIcon: 'downloadstudio.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=DownloadStudio'
              +			}
              +		},
              +		'272': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'WinPodder',
              +				uaUrl: 'http://winpodder.com/',
              +				uaCompany: 'Mike Versteeg',
              +				uaCompanyUrl: 'http://mikeversteeg.com/',
              +				uaIcon: 'winpodder.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=WinPodder'
              +			}
              +		},
              +		'273': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Bunjalloo',
              +				uaUrl: 'http://code.google.com/p/quirkysoft/',
              +				uaCompany: 'quirkysoft',
              +				uaCompanyUrl: '',
              +				uaIcon: 'bunjalloo.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Bunjalloo'
              +			}
              +		},
              +		'274': {
              +			typeId: '10',
              +			metadata: {
              +				uaFamily: 'LinkChecker',
              +				uaUrl: 'http://linkchecker.sourceforge.net/',
              +				uaCompany: 'Bastian Kleineidam',
              +				uaCompanyUrl: '',
              +				uaIcon: 'LinkChecker.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=LinkChecker'
              +			}
              +		},
              +		'276': {
              +			typeId: '5',
              +			metadata: {
              +				uaFamily: 'urlgrabber',
              +				uaUrl: 'http://linux.duke.edu/projects/urlgrabber/',
              +				uaCompany: 'Michael Stenner and Ryan Tomayko',
              +				uaCompanyUrl: '',
              +				uaIcon: 'php.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=urlgrabber'
              +			}
              +		},
              +		'277': {
              +			typeId: '4',
              +			metadata: {
              +				uaFamily: 'Spicebird',
              +				uaUrl: 'http://www.spicebird.com/',
              +				uaCompany: 'Synovel Technologies',
              +				uaCompanyUrl: 'http://www.synovel.com/',
              +				uaIcon: 'spicebird.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Spicebird'
              +			}
              +		},
              +		'278': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Firefox (Namoroka)',
              +				uaUrl: 'https://wiki.mozilla.org/Firefox/Namoroka',
              +				uaCompany: 'Mozilla Foundation',
              +				uaCompanyUrl: 'http://www.mozilla.org/',
              +				uaIcon: 'firefox.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Firefox (Namoroka)'
              +			}
              +		},
              +		'279': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Rekonq',
              +				uaUrl: 'http://rekonq.kde.org/',
              +				uaCompany: 'Andrea Diamantini',
              +				uaCompanyUrl: 'http://www.adjam.org/',
              +				uaIcon: 'rekonq.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Rekonq'
              +			}
              +		},
              +		'280': {
              +			typeId: '10',
              +			metadata: {
              +				uaFamily: 'Multipage Validator',
              +				uaUrl: 'http://www.validator.ca/',
              +				uaCompany: 'R\xe9seau Proze',
              +				uaCompanyUrl: 'http://www.proze.net/',
              +				uaIcon: 'MultipageValidator.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Multipage Validator'
              +			}
              +		},
              +		'281': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'X-Smiles',
              +				uaUrl: 'http://www.xsmiles.org/',
              +				uaCompany: 'X-Smiles.org',
              +				uaCompanyUrl: '',
              +				uaIcon: 'x-smiles.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=X-Smiles'
              +			}
              +		},
              +		'282': {
              +			typeId: '5',
              +			metadata: {
              +				uaFamily: 'WinHTTP',
              +				uaUrl: 'http://msdn.microsoft.com/en-us/library/aa382925(VS.85).aspx',
              +				uaCompany: 'Microsoft Corporation.',
              +				uaCompanyUrl: 'http://www.microsoft.com/',
              +				uaIcon: 'DLLicon.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=WinHTTP'
              +			}
              +		},
              +		'283': {
              +			typeId: '1',
              +			metadata: {
              +				uaFamily: 'Xaldon WebSpider',
              +				uaUrl: 'http://www.xaldon.de/products_webspider.html',
              +				uaCompany: 'xaldon Technologies',
              +				uaCompanyUrl: 'http://www.xaldon.de/',
              +				uaIcon: 'XaldonWebSpider.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Xaldon WebSpider'
              +			}
              +		},
              +		'284': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'Seznam WAP Proxy',
              +				uaUrl: 'http://www.smobil.cz/mobilni-vyhledavani',
              +				uaCompany: 'Seznam.cz, a.s.',
              +				uaCompanyUrl: 'http://www.seznam.cz/',
              +				uaIcon: 'seznam.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Seznam WAP Proxy'
              +			}
              +		},
              +		'285': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'Google Wireless Transcoder',
              +				uaUrl: 'http://google.com/gwt/n',
              +				uaCompany: 'Google',
              +				uaCompanyUrl: 'http://www.google.com/',
              +				uaIcon: 'feedfetcher-google.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Google Wireless Transcoder'
              +			}
              +		},
              +		'286': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'Google Listen',
              +				uaUrl: 'http://listen.googlelabs.com/',
              +				uaCompany: 'Google',
              +				uaCompanyUrl: 'http://www.google.com/',
              +				uaIcon: 'google_listen.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Google Listen'
              +			}
              +		},
              +		'287': {
              +			typeId: '5',
              +			metadata: {
              +				uaFamily: 'Typhoeus',
              +				uaUrl: 'https://github.com/typhoeus/typhoeus',
              +				uaCompany: 'Paul Dix',
              +				uaCompanyUrl: 'http://www.pauldix.net/',
              +				uaIcon: 'typhoeus.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Typhoeus'
              +			}
              +		},
              +		'288': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'OWB',
              +				uaUrl: 'http://www.sand-labs.org/owb',
              +				uaCompany: 'Sand-labs.org',
              +				uaCompanyUrl: 'http://www.sand-labs.org/',
              +				uaIcon: 'owb.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=OWB'
              +			}
              +		},
              +		'289': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Browzar',
              +				uaUrl: 'http://www.browzar.com/',
              +				uaCompany: 'Browzar Ltd',
              +				uaCompanyUrl: '',
              +				uaIcon: 'browzar.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Browzar'
              +			}
              +		},
              +		'290': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'Claws Mail GtkHtml2 plugin',
              +				uaUrl: 'http://www.claws-mail.org/plugin.php?plugin=gtkhtml2',
              +				uaCompany: 'Colin Leroy',
              +				uaCompanyUrl: '',
              +				uaIcon: 'Claws_Mail_GtkHtml_plugin.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Claws Mail GtkHtml2 plugin'
              +			}
              +		},
              +		'291': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'Vuze',
              +				uaUrl: 'http://www.vuze.com/',
              +				uaCompany: 'Vuze, Inc',
              +				uaCompanyUrl: '',
              +				uaIcon: 'vuze.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Vuze'
              +			}
              +		},
              +		'292': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'GlobalMojo',
              +				uaUrl: 'http://globalmojo.com/',
              +				uaCompany: 'KPG VENTURES',
              +				uaCompanyUrl: 'http://www.kpgventures.com/',
              +				uaIcon: 'globalmojo.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=GlobalMojo'
              +			}
              +		},
              +		'293': {
              +			typeId: '18',
              +			metadata: {
              +				uaFamily: 'GOM Player',
              +				uaUrl: 'http://www.gomlab.com/',
              +				uaCompany: 'GRETECH CORP.',
              +				uaCompanyUrl: 'http://www.gretech.com/',
              +				uaIcon: 'GomPlayer.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=GOM Player'
              +			}
              +		},
              +		'294': {
              +			typeId: '5',
              +			metadata: {
              +				uaFamily: 'Python-webchecker',
              +				uaUrl: 'http://www.python.org/doc/essays/ppt/sd99east/sld070.htm',
              +				uaCompany: 'Guido van Rossum/Sam Bayer',
              +				uaCompanyUrl: '',
              +				uaIcon: 'pythonurllib.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Python-webchecker'
              +			}
              +		},
              +		'296': {
              +			typeId: '10',
              +			metadata: {
              +				uaFamily: 'W3C mobileOK Checker',
              +				uaUrl: 'http://validator.w3.org/mobile/',
              +				uaCompany: 'World Wide Web Consortium',
              +				uaCompanyUrl: 'http://www.w3.org/',
              +				uaIcon: 'w3.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=W3C mobileOK Checker'
              +			}
              +		},
              +		'297': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'Siege',
              +				uaUrl: 'http://www.joedog.org/index/siege-home',
              +				uaCompany: 'Joe Dog Software',
              +				uaCompanyUrl: 'http://www.joedog.org/',
              +				uaIcon: 'joedog.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Siege'
              +			}
              +		},
              +		'298': {
              +			typeId: '1',
              +			metadata: {
              +				uaFamily: 'iSiloXC',
              +				uaUrl: 'http://www.isilox.com/',
              +				uaCompany: 'DC & Co.',
              +				uaCompanyUrl: 'http://www.isilox.com/',
              +				uaIcon: 'terminal.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=iSiloXC'
              +			}
              +		},
              +		'299': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'AB (Apache Bench)',
              +				uaUrl: 'http://en.wikipedia.org/wiki/ApacheBench',
              +				uaCompany: 'Apache Software Foundation',
              +				uaCompanyUrl: 'http://www.apache.org/',
              +				uaIcon: 'ab.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=AB (Apache Bench)'
              +			}
              +		},
              +		'300': {
              +			typeId: '10',
              +			metadata: {
              +				uaFamily: 'anw LoadControl',
              +				uaUrl: 'http://webtool.anw.de/analyze/?ladezeit',
              +				uaCompany: 'ANW GmbH & Co. KG',
              +				uaCompanyUrl: 'http://www.anw.de/',
              +				uaIcon: 'anw.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=anw LoadControl'
              +			}
              +		},
              +		'301': {
              +			typeId: '10',
              +			metadata: {
              +				uaFamily: 'anw HTMLChecker',
              +				uaUrl: 'http://webtool.topsubmit.de/analyze/?html',
              +				uaCompany: 'ANW GmbH & Co. KG',
              +				uaCompanyUrl: 'http://www.anw.de/',
              +				uaIcon: 'anw.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=anw HTMLChecker'
              +			}
              +		},
              +		'302': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Edbrowse',
              +				uaUrl: 'http://edbrowse.sourceforge.net/',
              +				uaCompany: 'Karl Dahlke',
              +				uaCompanyUrl: '',
              +				uaIcon: 'Edbrowse.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Edbrowse'
              +			}
              +		},
              +		'303': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'muCommander',
              +				uaUrl: 'http://www.mucommander.com/',
              +				uaCompany: 'Maxence Bernard',
              +				uaCompanyUrl: '',
              +				uaIcon: 'muCommander.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=muCommander'
              +			}
              +		},
              +		'304': {
              +			typeId: '18',
              +			metadata: {
              +				uaFamily: 'XMPlay',
              +				uaUrl: 'http://www.xmplay.com/',
              +				uaCompany: 'un4seen developments',
              +				uaCompanyUrl: 'http://www.un4seen.com/',
              +				uaIcon: 'XMPlay.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=XMPlay'
              +			}
              +		},
              +		'305': {
              +			typeId: '15',
              +			metadata: {
              +				uaFamily: 'NFReader',
              +				uaUrl: 'http://www.gaijin.at/dlnfreader.php',
              +				uaCompany: 'Gaijin.at',
              +				uaCompanyUrl: 'http://www.gaijin.at/',
              +				uaIcon: 'NFReader.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=NFReader'
              +			}
              +		},
              +		'306': {
              +			typeId: '3',
              +			metadata: {
              +				uaFamily: 'uZard Web',
              +				uaUrl: 'http://www.uzard.com/',
              +				uaCompany: 'Logicplant Co.',
              +				uaCompanyUrl: 'http://www.logicplant.com/',
              +				uaIcon: 'uzard.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=uZard Web'
              +			}
              +		},
              +		'307': {
              +			typeId: '5',
              +			metadata: {
              +				uaFamily: 'Indy Library',
              +				uaUrl: 'http://www.indyproject.org/',
              +				uaCompany: 'Chad Z. Hower (Kudzu) and the Indy Pit Crew',
              +				uaCompanyUrl: '',
              +				uaIcon: 'DLLicon.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Indy Library'
              +			}
              +		},
              +		'308': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Multi-Browser XP',
              +				uaUrl: 'http://www.multibrowser.de/',
              +				uaCompany: 'Binh Nguyen-Huu',
              +				uaCompanyUrl: '',
              +				uaIcon: 'Multi-BrowserXP.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Multi-Browser XP'
              +			}
              +		},
              +		'309': {
              +			typeId: '10',
              +			metadata: {
              +				uaFamily: 'LinkWalker',
              +				uaUrl: '',
              +				uaCompany: 'BDProtect Inc',
              +				uaCompanyUrl: 'http://www.brandprotect.com/',
              +				uaIcon: 'LinkWalker.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=LinkWalker'
              +			}
              +		},
              +		'310': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'NetPositive',
              +				uaUrl: 'http://en.wikipedia.org/wiki/NetPositive',
              +				uaCompany: 'Be Inc.',
              +				uaCompanyUrl: 'http://en.wikipedia.org/wiki/Be_Inc.',
              +				uaIcon: 'netpositive.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=NetPositive'
              +			}
              +		},
              +		'311': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'Radio Downloader',
              +				uaUrl: 'http://www.nerdoftheherd.com/tools/radiodld/',
              +				uaCompany: 'Matt Robinson',
              +				uaCompanyUrl: 'http://www.nerdoftheherd.com/',
              +				uaIcon: 'RadioDownloader.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Radio Downloader'
              +			}
              +		},
              +		'312': {
              +			typeId: '1',
              +			metadata: {
              +				uaFamily: 'WebStripper',
              +				uaUrl: 'http://webstripper.net/',
              +				uaCompany: 'Mike Sutton',
              +				uaCompanyUrl: 'http://solentsoftware.com/',
              +				uaIcon: 'webstripper.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=WebStripper'
              +			}
              +		},
              +		'313': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'Cyberduck',
              +				uaUrl: 'http://cyberduck.ch/',
              +				uaCompany: 'David Kocher',
              +				uaCompanyUrl: 'dkocher.name',
              +				uaIcon: 'Cyberduck.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Cyberduck'
              +			}
              +		},
              +		'314': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'WorldWideWeb',
              +				uaUrl: 'http://www.w3.org/People/Berners-Lee/WorldWideWeb',
              +				uaCompany: 'Tim Berners-Lee',
              +				uaCompanyUrl: 'http://www.w3.org/People/Berners-Lee/Overview.html',
              +				uaIcon: '1stBrowser.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=WorldWideWeb'
              +			}
              +		},
              +		'315': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'iVideo',
              +				uaUrl: 'http://tinyurl.com/DownloadiVideo',
              +				uaCompany: 'ZETZ mobile',
              +				uaCompanyUrl: 'http://www.zetzmobile.com/',
              +				uaIcon: 'iVideo.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=iVideo'
              +			}
              +		},
              +		'316': {
              +			typeId: '15',
              +			metadata: {
              +				uaFamily: 'RSS Popper',
              +				uaUrl: 'http://www.rsspopper.com/',
              +				uaCompany: 'Paradisoft',
              +				uaCompanyUrl: 'http://www.paradisoft.com/',
              +				uaIcon: 'rss.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=RSS Popper'
              +			}
              +		},
              +		'317': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'Jamcast',
              +				uaUrl: 'http://www.sdstechnologies.com/',
              +				uaCompany: 'Software Development Solutions, Inc.',
              +				uaCompanyUrl: 'http://www.sdstechnologies.com/',
              +				uaIcon: 'Jamcast.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Jamcast'
              +			}
              +		},
              +		'318': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Comodo Dragon',
              +				uaUrl: 'http://www.comodo.com/home/browsers-toolbars/browser.php',
              +				uaCompany: 'Comodo Group, Inc.',
              +				uaCompanyUrl: 'http://www.comodo.com/',
              +				uaIcon: 'Comodo_Dragon.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Comodo Dragon'
              +			}
              +		},
              +		'319': {
              +			typeId: '1',
              +			metadata: {
              +				uaFamily: 'SuperBot',
              +				uaUrl: 'http://www.sparkleware.com/superbot/index.html',
              +				uaCompany: 'Sparkleware',
              +				uaCompanyUrl: 'http://www.sparkleware.com/',
              +				uaIcon: 'SuperBot.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=SuperBot'
              +			}
              +		},
              +		'320': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'My Internet Browser',
              +				uaUrl: 'http://myinternetbrowser.webove-stranky.org/',
              +				uaCompany: 'Media WebPublishing',
              +				uaCompanyUrl: '',
              +				uaIcon: 'MyInternetBrowser.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=My Internet Browser'
              +			}
              +		},
              +		'321': {
              +			typeId: '3',
              +			metadata: {
              +				uaFamily: 'Opera Mobile',
              +				uaUrl: 'http://www.opera.com/mobile/',
              +				uaCompany: 'Opera Software ASA.',
              +				uaCompanyUrl: 'http://www.opera.com/',
              +				uaIcon: 'opera.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Opera Mobile'
              +			}
              +		},
              +		'322': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Kirix Strata',
              +				uaUrl: 'http://www.kirix.com/',
              +				uaCompany: 'Kirix Corporation',
              +				uaCompanyUrl: 'http://www.kirix.com/about-us.html',
              +				uaIcon: 'kirix-strata.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Kirix Strata'
              +			}
              +		},
              +		'323': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'TT Explorer',
              +				uaUrl: 'http://tt.qq.com/',
              +				uaCompany: 'Tencent',
              +				uaCompanyUrl: 'http://www.tencent.com/',
              +				uaIcon: 'tt_explorer.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=TT Explorer'
              +			}
              +		},
              +		'324': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'LBrowser',
              +				uaUrl: 'http://wiki.freespire.org/index.php/Web_Browser',
              +				uaCompany: 'Xandros Incorporated',
              +				uaCompanyUrl: 'http://www.xandros.com/',
              +				uaIcon: 'LBrowser.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=LBrowser'
              +			}
              +		},
              +		'325': {
              +			typeId: '4',
              +			metadata: {
              +				uaFamily: 'Outlook 2007',
              +				uaUrl: 'http://en.wikipedia.org/wiki/Microsoft_Outlook',
              +				uaCompany: 'Microsoft Corporation.',
              +				uaCompanyUrl: 'http://www.microsoft.com/',
              +				uaIcon: 'outlook-2007.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Outlook 2007'
              +			}
              +		},
              +		'326': {
              +			typeId: '4',
              +			metadata: {
              +				uaFamily: 'Outlook 2010',
              +				uaUrl: 'http://en.wikipedia.org/wiki/Microsoft_Outlook',
              +				uaCompany: 'Microsoft Corporation.',
              +				uaCompanyUrl: 'http://www.microsoft.com/',
              +				uaIcon: 'outlook-2010.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Outlook 2010'
              +			}
              +		},
              +		'327': {
              +			typeId: '4',
              +			metadata: {
              +				uaFamily: 'Windows Live Mail',
              +				uaUrl: 'http://download.live.com/wlmail',
              +				uaCompany: 'Microsoft Corporation.',
              +				uaCompanyUrl: 'http://www.microsoft.com/',
              +				uaIcon: 'Windows_Live_Mail.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Windows Live Mail'
              +			}
              +		},
              +		'328': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Tjusig',
              +				uaUrl: 'http://www.tjusig.cz/',
              +				uaCompany: 'Luk\xe1\u0161 Ingr',
              +				uaCompanyUrl: '',
              +				uaIcon: 'tjusig.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Tjusig'
              +			}
              +		},
              +		'329': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'SiteKiosk',
              +				uaUrl: 'http://www.sitekiosk.com/SiteKiosk/Default.aspx',
              +				uaCompany: 'PROVISIO GmbH / LLC',
              +				uaCompanyUrl: 'http://www.provisio.com/',
              +				uaIcon: 'sitekiosk.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=SiteKiosk'
              +			}
              +		},
              +		'330': {
              +			typeId: '4',
              +			metadata: {
              +				uaFamily: 'The Bat!',
              +				uaUrl: 'http://www.ritlabs.com/en/products/thebat/',
              +				uaCompany: 'RITLabs SRL',
              +				uaCompanyUrl: 'http://www.ritlabs.com/',
              +				uaIcon: 'thebat.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=The Bat!'
              +			}
              +		},
              +		'331': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'Novell BorderManager',
              +				uaUrl: 'http://www.novell.com/products/bordermanager/',
              +				uaCompany: 'Novell, Inc',
              +				uaCompanyUrl: 'http://www.novell.com/',
              +				uaIcon: 'Novell_BorderManager.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Novell BorderManager'
              +			}
              +		},
              +		'332': {
              +			typeId: '4',
              +			metadata: {
              +				uaFamily: 'Shredder',
              +				uaUrl: 'http://www.mozillamessaging.com/en-US/thunderbird/3.0a1/releasenotes/',
              +				uaCompany: 'Mozilla Foundation',
              +				uaCompanyUrl: 'http://www.mozilla.org/',
              +				uaIcon: 'thunderbird.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Shredder'
              +			}
              +		},
              +		'333': {
              +			typeId: '18',
              +			metadata: {
              +				uaFamily: 'Public Radio Player',
              +				uaUrl: 'http://www.publicradioplayer.org/',
              +				uaCompany: 'Public Radio Exchange (PRX)',
              +				uaCompanyUrl: 'http://www.prx.org/',
              +				uaIcon: 'PRP.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Public Radio Player'
              +			}
              +		},
              +		'334': {
              +			typeId: '15',
              +			metadata: {
              +				uaFamily: 'Rss Bandit',
              +				uaUrl: 'http://rssbandit.org/',
              +				uaCompany: 'Infragistics, Inc.',
              +				uaCompanyUrl: 'http://www.infragistics.com/',
              +				uaIcon: 'RssBandit.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Rss Bandit'
              +			}
              +		},
              +		'335': {
              +			typeId: '4',
              +			metadata: {
              +				uaFamily: 'Postbox',
              +				uaUrl: 'http://www.postbox-inc.com/',
              +				uaCompany: 'Postbox, Inc.',
              +				uaCompanyUrl: 'http://www.postbox-inc.com/',
              +				uaIcon: 'postbox.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Postbox'
              +			}
              +		},
              +		'336': {
              +			typeId: '10',
              +			metadata: {
              +				uaFamily: '2Bone LinkChecker',
              +				uaUrl: 'http://www.2bone.com/links/linkchecker.shtml',
              +				uaCompany: '2Bone',
              +				uaCompanyUrl: 'http://www.2bone.com/',
              +				uaIcon: '2bone.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=2Bone LinkChecker'
              +			}
              +		},
              +		'337': {
              +			typeId: '10',
              +			metadata: {
              +				uaFamily: 'Checkbot',
              +				uaUrl: 'http://degraaff.org/checkbot/',
              +				uaCompany: 'Hans de Graaff',
              +				uaCompanyUrl: 'http://degraaff.org/',
              +				uaIcon: 'perl.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Checkbot'
              +			}
              +		},
              +		'338': {
              +			typeId: '4',
              +			metadata: {
              +				uaFamily: 'GcMail',
              +				uaUrl: 'http://www.gcmail.de/',
              +				uaCompany: 'Monika Verse',
              +				uaCompanyUrl: '',
              +				uaIcon: 'gcmail.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=GcMail'
              +			}
              +		},
              +		'339': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Swiftweasel',
              +				uaUrl: 'http://swiftweasel.tuxfamily.org/',
              +				uaCompany: 'SticKK',
              +				uaCompanyUrl: '',
              +				uaIcon: 'swiftweasel.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Swiftweasel'
              +			}
              +		},
              +		'340': {
              +			typeId: '15',
              +			metadata: {
              +				uaFamily: 'Fastladder FeedFetcher',
              +				uaUrl: 'http://fastladder.com/',
              +				uaCompany: 'livedoor Co.,Ltd. ',
              +				uaCompanyUrl: 'http://corp.livedoor.com/',
              +				uaIcon: 'fastladderFeedFetcher.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Fastladder FeedFetcher'
              +			}
              +		},
              +		'341': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Firefox (Lorentz)',
              +				uaUrl: 'http://www.mozilla.com/en-US/firefox/lorentz/',
              +				uaCompany: 'Mozilla Foundation',
              +				uaCompanyUrl: 'http://www.mozilla.org/',
              +				uaIcon: 'firefox.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Firefox (Lorentz)'
              +			}
              +		},
              +		'342': {
              +			typeId: '18',
              +			metadata: {
              +				uaFamily: 'Pocket Tunes',
              +				uaUrl: 'http://www.pocket-tunes.com/',
              +				uaCompany: 'NormSoft, Inc.',
              +				uaCompanyUrl: 'http://www.normsoft.com/',
              +				uaIcon: 'PocketTunes.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Pocket Tunes'
              +			}
              +		},
              +		'343': {
              +			typeId: '15',
              +			metadata: {
              +				uaFamily: 'SharpReader',
              +				uaUrl: 'http://www.sharpreader.net/',
              +				uaCompany: 'Luke Hutteman',
              +				uaCompanyUrl: 'http://www.hutteman.com/',
              +				uaIcon: 'sharpreader.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=SharpReader'
              +			}
              +		},
              +		'344': {
              +			typeId: '15',
              +			metadata: {
              +				uaFamily: 'YeahReader',
              +				uaUrl: 'http://www.yeahreader.com/',
              +				uaCompany: 'ExtraLabs Software',
              +				uaCompanyUrl: 'http://www.extralabs.net/',
              +				uaIcon: 'YeahReader.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=YeahReader'
              +			}
              +		},
              +		'345': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Pale Moon',
              +				uaUrl: 'http://www.palemoon.org/',
              +				uaCompany: 'Moonchild Productions',
              +				uaCompanyUrl: 'http://www.moonchildproductions.net/',
              +				uaIcon: 'pale_moon.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Pale Moon'
              +			}
              +		},
              +		'346': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'Holmes',
              +				uaUrl: 'http://www.ucw.cz/holmes/',
              +				uaCompany: 'Martin Mare\u0161 and Robert \u0160palek',
              +				uaCompanyUrl: '',
              +				uaIcon: 'holmes.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Holmes'
              +			}
              +		},
              +		'347': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'Google Earth',
              +				uaUrl: 'http://earth.google.com/',
              +				uaCompany: 'Google Inc.',
              +				uaCompanyUrl: 'http://google.com/',
              +				uaIcon: 'google_earth.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Google Earth'
              +			}
              +		},
              +		'348': {
              +			typeId: '5',
              +			metadata: {
              +				uaFamily: 'ROME library',
              +				uaUrl: 'https://rome.dev.java.net/',
              +				uaCompany: 'A. Abdelnur, P. Chanezon and E. Chien',
              +				uaCompanyUrl: '',
              +				uaIcon: 'ROME_lib.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=ROME library'
              +			}
              +		},
              +		'349': {
              +			typeId: '15',
              +			metadata: {
              +				uaFamily: 'Akregator',
              +				uaUrl: 'http://akregator.kde.org/',
              +				uaCompany: '',
              +				uaCompanyUrl: 's',
              +				uaIcon: 'akregator.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Akregator'
              +			}
              +		},
              +		'350': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Mini Browser',
              +				uaUrl: 'http://dmkho.tripod.com/',
              +				uaCompany: 'DMKHO',
              +				uaCompanyUrl: '',
              +				uaIcon: 'minibrowser.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Mini Browser'
              +			}
              +		},
              +		'351': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Espial TV Browser',
              +				uaUrl: 'http://www.espial.com/products/evo_browser/',
              +				uaCompany: 'Espial Group',
              +				uaCompanyUrl: 'http://www.espial.com/',
              +				uaIcon: 'EspialTVBrowser.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Espial TV Browser'
              +			}
              +		},
              +		'352': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'UltraBrowser ',
              +				uaUrl: 'http://www.ultrabrowser.com/',
              +				uaCompany: 'UltraBrowser.com, Inc.',
              +				uaCompanyUrl: '',
              +				uaIcon: 'UltraBrowser.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=UltraBrowser '
              +			}
              +		},
              +		'353': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'BrowseX',
              +				uaUrl: 'http://pdqi.com/browsex/',
              +				uaCompany: 'Peter MacDonald',
              +				uaCompanyUrl: 'http://pdqi.com/',
              +				uaIcon: 'browsex.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=BrowseX'
              +			}
              +		},
              +		'354': {
              +			typeId: '3',
              +			metadata: {
              +				uaFamily: 'Android Webkit',
              +				uaUrl: 'http://developer.android.com/reference/android/webkit/package-summary.html',
              +				uaCompany: 'Google Inc.',
              +				uaCompanyUrl: 'http://www.google.com/',
              +				uaIcon: 'androidWebkit.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Android Webkit'
              +			}
              +		},
              +		'355': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Weltweitimnetz Browser',
              +				uaUrl: 'http://weltweitimnetz.de/software/Browser.en.page',
              +				uaCompany: 'Philipp Ruppel',
              +				uaCompanyUrl: 'http://weltweitimnetz.de/',
              +				uaIcon: 'WeltweitimnetzBrowser.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Weltweitimnetz Browser'
              +			}
              +		},
              +		'356': {
              +			typeId: '4',
              +			metadata: {
              +				uaFamily: 'PocoMail',
              +				uaUrl: 'http://www.pocomail.com/',
              +				uaCompany: 'Poco Systems Inc',
              +				uaCompanyUrl: 'http://www.pocosystems.com/',
              +				uaIcon: 'pocomail.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=PocoMail'
              +			}
              +		},
              +		'357': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Element Browser',
              +				uaUrl: 'http://www.elementsoftware.co.uk/software/elementbrowser/',
              +				uaCompany: 'Element Software UK.',
              +				uaCompanyUrl: 'http://www.elementsoftware.co.uk/',
              +				uaIcon: 'elementbrowser.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Element Browser'
              +			}
              +		},
              +		'358': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'SlimBrowser',
              +				uaUrl: 'http://slimbrowser.flashpeak.com/',
              +				uaCompany: 'FlashPeak Inc.',
              +				uaCompanyUrl: 'http://www.flashpeak.com/',
              +				uaIcon: 'slimbrowser.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=SlimBrowser'
              +			}
              +		},
              +		'359': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'LeechCraft',
              +				uaUrl: 'http://leechcraft.org/',
              +				uaCompany: '',
              +				uaCompanyUrl: '',
              +				uaIcon: 'LeechCraft.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=LeechCraft'
              +			}
              +		},
              +		'360': {
              +			typeId: '5',
              +			metadata: {
              +				uaFamily: 'HTTP_Request2',
              +				uaUrl: 'http://pear.php.net/package/http_request2',
              +				uaCompany: '',
              +				uaCompanyUrl: '',
              +				uaIcon: 'php.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=HTTP_Request2'
              +			}
              +		},
              +		'361': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Conkeror',
              +				uaUrl: 'http://conkeror.org/',
              +				uaCompany: 'Mozilla Foundation',
              +				uaCompanyUrl: 'http://www.mozilla.org/',
              +				uaIcon: 'conkeror.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Conkeror'
              +			}
              +		},
              +		'362': {
              +			typeId: '3',
              +			metadata: {
              +				uaFamily: 'Dolphin',
              +				uaUrl: 'http://www.dolphin-browser.com/',
              +				uaCompany: 'Samsung',
              +				uaCompanyUrl: 'http://www.samsung.com/',
              +				uaIcon: 'dolphin.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Dolphin'
              +			}
              +		},
              +		'363': {
              +			typeId: '15',
              +			metadata: {
              +				uaFamily: 'Netvibes feed reader',
              +				uaUrl: '',
              +				uaCompany: 'Netvibes team',
              +				uaCompanyUrl: 'http://about.netvibes.com/',
              +				uaIcon: 'netvibes.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Netvibes feed reader'
              +			}
              +		},
              +		'364': {
              +			typeId: '5',
              +			metadata: {
              +				uaFamily: 'Chilkat HTTP .NET',
              +				uaUrl: 'http://www.chilkatsoft.com/HttpDotNet.asp',
              +				uaCompany: 'Chilkat Software, Inc.',
              +				uaCompanyUrl: 'http://www.chilkatsoft.com/',
              +				uaIcon: 'chilkat.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Chilkat HTTP .NET'
              +			}
              +		},
              +		'365': {
              +			typeId: '5',
              +			metadata: {
              +				uaFamily: 'IXR lib',
              +				uaUrl: 'http://scripts.incutio.com/xmlrpc/',
              +				uaCompany: 'Incutio Ltd.',
              +				uaCompanyUrl: 'http://www.incutio.com/',
              +				uaIcon: 'Incutio.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=IXR lib'
              +			}
              +		},
              +		'366': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'Web-sniffer',
              +				uaUrl: 'http://web-sniffer.net/',
              +				uaCompany: 'Lingo4you GbR',
              +				uaCompanyUrl: 'http://www.lingo4u.de/',
              +				uaIcon: 'Web-sniffer.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Web-sniffer'
              +			}
              +		},
              +		'367': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'Atomic Email Hunter',
              +				uaUrl: 'http://www.massmailsoftware.com/extractweb/',
              +				uaCompany: 'AtomPark Software Inc.',
              +				uaCompanyUrl: 'http://www.atompark.com/',
              +				uaIcon: 'Atomic_Email_Hunter.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Atomic Email Hunter'
              +			}
              +		},
              +		'368': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'iGetter',
              +				uaUrl: 'http://www.igetter.net/',
              +				uaCompany: 'Presenta Ltd.',
              +				uaCompanyUrl: '',
              +				uaIcon: 'iGetter.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=iGetter'
              +			}
              +		},
              +		'369': {
              +			typeId: '1',
              +			metadata: {
              +				uaFamily: 'webfetch',
              +				uaUrl: 'http://tony.aiu.to/sa/webfetch/',
              +				uaCompany: 'Tony Aiuto',
              +				uaCompanyUrl: 'http://tony.aiu.to/',
              +				uaIcon: 'terminal.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=webfetch'
              +			}
              +		},
              +		'370': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'Apache Synapse',
              +				uaUrl: 'http://synapse.apache.org/',
              +				uaCompany: 'Apache Software Foundation',
              +				uaCompanyUrl: 'http://www.apache.org/',
              +				uaIcon: 'ab.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Apache Synapse'
              +			}
              +		},
              +		'371': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'lolifox',
              +				uaUrl: 'http://lolifox.com/',
              +				uaCompany: 'Atachi Hayashime',
              +				uaCompanyUrl: '',
              +				uaIcon: 'lolifox.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=lolifox'
              +			}
              +		},
              +		'372': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'SkipStone',
              +				uaUrl: 'http://www.muhri.net/skipstone/',
              +				uaCompany: 'Maher Awamy',
              +				uaCompanyUrl: 'http://www.muhri.net/',
              +				uaIcon: 'skipStone.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=SkipStone'
              +			}
              +		},
              +		'373': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'Powermarks',
              +				uaUrl: 'http://www.kaylon.com/power.html',
              +				uaCompany: 'Kaylon Technologies Inc.',
              +				uaCompanyUrl: 'http://www.kaylon.com/',
              +				uaIcon: 'powermarks.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Powermarks'
              +			}
              +		},
              +		'374': {
              +			typeId: '15',
              +			metadata: {
              +				uaFamily: 'Safari RSS reader',
              +				uaUrl: 'http://www.apple.com/safari/',
              +				uaCompany: 'Apple Inc.',
              +				uaCompanyUrl: 'http://www.apple.com/',
              +				uaIcon: 'rss.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Safari RSS reader'
              +			}
              +		},
              +		'375': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'Google Friend Connect',
              +				uaUrl: 'http://www.google.com/friendconnect/',
              +				uaCompany: 'Google Inc.',
              +				uaCompanyUrl: 'http://www.google.com/',
              +				uaIcon: 'google_friend_connect.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Google Friend Connect'
              +			}
              +		},
              +		'376': {
              +			typeId: '15',
              +			metadata: {
              +				uaFamily: 'Feed Viewer',
              +				uaUrl: 'http://feedviewer.codeplex.com/',
              +				uaCompany: 'vasek7',
              +				uaCompanyUrl: 'http://www.codeplex.com/site/users/view/vasek7',
              +				uaIcon: 'rss.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Feed Viewer'
              +			}
              +		},
              +		'377': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'RockMelt',
              +				uaUrl: 'http://www.rockmelt.com/',
              +				uaCompany: 'Rockmelt, Inc.',
              +				uaCompanyUrl: 'http://www.rockmelt.com/',
              +				uaIcon: 'rockmelt.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=RockMelt'
              +			}
              +		},
              +		'378': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Epic',
              +				uaUrl: 'http://www.epicbrowser.com/',
              +				uaCompany: 'Hidden Reflex',
              +				uaCompanyUrl: 'http://www.hiddenreflex.com/',
              +				uaIcon: 'epic.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Epic'
              +			}
              +		},
              +		'379': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'InternetSurfboard',
              +				uaUrl: 'http://inetsurfboard.sourceforge.net/',
              +				uaCompany: 'Philipp Ruppel',
              +				uaCompanyUrl: '',
              +				uaIcon: 'internetSurfboard.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=InternetSurfboard'
              +			}
              +		},
              +		'380': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Vonkeror',
              +				uaUrl: 'http://zzo38computer.cjb.net/vonkeror/',
              +				uaCompany: 'zzo38',
              +				uaCompanyUrl: 'http://zzo38computer.cjb.net/',
              +				uaIcon: 'conkeror.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Vonkeror'
              +			}
              +		},
              +		'381': {
              +			typeId: '15',
              +			metadata: {
              +				uaFamily: 'IE RSS reader',
              +				uaUrl: 'http://en.wikipedia.org/wiki/Windows_RSS_Platform',
              +				uaCompany: 'Microsoft',
              +				uaCompanyUrl: 'http://www.microsoft.com/',
              +				uaIcon: 'rss.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=IE RSS reader'
              +			}
              +		},
              +		'382': {
              +			typeId: '15',
              +			metadata: {
              +				uaFamily: 'Trileet NewsRoom',
              +				uaUrl: 'http://feedmonger.blogspot.com/',
              +				uaCompany: 'Trileet Inc.',
              +				uaCompanyUrl: 'http://www.trileet.com/',
              +				uaIcon: 'rss.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Trileet NewsRoom'
              +			}
              +		},
              +		'383': {
              +			typeId: '10',
              +			metadata: {
              +				uaFamily: 'Validator.nu',
              +				uaUrl: 'http://validator.nu/',
              +				uaCompany: 'Henri Sivonen',
              +				uaCompanyUrl: 'http://hsivonen.iki.fi/author/',
              +				uaIcon: 'validator_nu.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Validator.nu'
              +			}
              +		},
              +		'384': {
              +			typeId: '5',
              +			metadata: {
              +				uaFamily: 'Zend_Http_Client',
              +				uaUrl: 'http://framework.zend.com/manual/en/zend.http.html',
              +				uaCompany: 'Zend Technologies Ltd.',
              +				uaCompanyUrl: 'http://www.zend.com/',
              +				uaIcon: 'zend_http_client.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Zend_Http_Client'
              +			}
              +		},
              +		'385': {
              +			typeId: '3',
              +			metadata: {
              +				uaFamily: 'Skyfire',
              +				uaUrl: 'http://www.skyfire.com/',
              +				uaCompany: 'Skyfire Labs, Inc.',
              +				uaCompanyUrl: 'http://www.skyfire.com/about',
              +				uaIcon: 'skyfire.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Skyfire'
              +			}
              +		},
              +		'386': {
              +			typeId: '3',
              +			metadata: {
              +				uaFamily: 'GO Browser',
              +				uaUrl: 'http://www.gobrowser.cn/',
              +				uaCompany: 'GO Dev Team',
              +				uaCompanyUrl: '',
              +				uaIcon: 'go_browser.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=GO Browser'
              +			}
              +		},
              +		'387': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Surf',
              +				uaUrl: 'http://surf.suckless.org/',
              +				uaCompany: 'suckless.org',
              +				uaCompanyUrl: 'http://suckless.org/',
              +				uaIcon: 'surf.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Surf'
              +			}
              +		},
              +		'388': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'iGooMap',
              +				uaUrl: 'http://www.pointworks.de/software/igoomap/index.php',
              +				uaCompany: 'PointWorks.de',
              +				uaCompanyUrl: 'http://www.pointworks.de/',
              +				uaIcon: 'igoomap.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=iGooMap'
              +			}
              +		},
              +		'389': {
              +			typeId: '18',
              +			metadata: {
              +				uaFamily: 'iTunes',
              +				uaUrl: 'http://www.apple.com/itunes/',
              +				uaCompany: 'Apple Inc.',
              +				uaCompanyUrl: 'http://www.apple.com/',
              +				uaIcon: 'itunes.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=iTunes'
              +			}
              +		},
              +		'390': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'BlackHawk',
              +				uaUrl: 'http://www.netgate.sk/blackhawk/help/welcome-to-blackhawk-web-browser.html',
              +				uaCompany: 'NETGATE Technologies s.r.o. ',
              +				uaCompanyUrl: 'http://www.netgate.sk/',
              +				uaIcon: 'blackhawk.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=BlackHawk'
              +			}
              +		},
              +		'392': {
              +			typeId: '3',
              +			metadata: {
              +				uaFamily: 'Kindle Browser',
              +				uaUrl: 'http://en.wikipedia.org/wiki/Amazon_Kindle',
              +				uaCompany: 'Amazon.com',
              +				uaCompanyUrl: 'http://www.amazon.com/',
              +				uaIcon: 'kindle.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Kindle Browser'
              +			}
              +		},
              +		'393': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'Microsoft Office Existence Discovery',
              +				uaUrl: 'http://blogs.msdn.com/b/vsofficedeveloper/archive/2008/03/11/office-existence-discovery-protocol.aspx',
              +				uaCompany: 'Microsoft Corporation.',
              +				uaCompanyUrl: 'http://www.microsoft.com/',
              +				uaIcon: 'webdav.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Microsoft Office Existence Discovery'
              +			}
              +		},
              +		'394': {
              +			typeId: '3',
              +			metadata: {
              +				uaFamily: 'Mobile Safari',
              +				uaUrl: 'http://en.wikipedia.org/wiki/Safari_%28web_browser%29',
              +				uaCompany: 'Apple Inc.',
              +				uaCompanyUrl: 'http://www.apple.com/',
              +				uaIcon: 'safari.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Mobile Safari'
              +			}
              +		},
              +		'395': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'BrownRecluse',
              +				uaUrl: 'http://softbytelabs.com/us/br/index.html',
              +				uaCompany: 'SoftByte Labs, Inc.',
              +				uaCompanyUrl: 'http://softbytelabs.com/',
              +				uaIcon: 'BrownRecluse.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=BrownRecluse'
              +			}
              +		},
              +		'396': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'BookmarkTracker',
              +				uaUrl: 'http://www.bookmarktracker.com/',
              +				uaCompany: 'BookmarkTracker.com, Inc.',
              +				uaCompanyUrl: '',
              +				uaIcon: 'BookmarkTracker.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=BookmarkTracker'
              +			}
              +		},
              +		'397': {
              +			typeId: '5',
              +			metadata: {
              +				uaFamily: 'BinGet',
              +				uaUrl: 'http://www.bin-co.com/php/scripts/load/',
              +				uaCompany: 'Binny VA',
              +				uaCompanyUrl: 'http://binnyva.com/',
              +				uaIcon: 'php.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=BinGet'
              +			}
              +		},
              +		'399': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Webian Shell',
              +				uaUrl: 'http://webian.org/shell/',
              +				uaCompany: 'Ben Francis',
              +				uaCompanyUrl: 'http://tola.me.uk/',
              +				uaIcon: 'webianshell.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Webian Shell'
              +			}
              +		},
              +		'400': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Kylo',
              +				uaUrl: 'http://kylo.tv/',
              +				uaCompany: 'Hillcrest Laboratories',
              +				uaCompanyUrl: 'http://hillcrestlabs.com/',
              +				uaIcon: 'kylo.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Kylo'
              +			}
              +		},
              +		'401': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Fireweb Navigator',
              +				uaUrl: 'http://www.arsslensoft.tk/?q=node/7',
              +				uaCompany: 'Arsslensoft Foundation',
              +				uaCompanyUrl: 'http://www.arsslensoft.fi5.us/',
              +				uaIcon: 'Fireweb.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Fireweb Navigator'
              +			}
              +		},
              +		'402': {
              +			typeId: '5',
              +			metadata: {
              +				uaFamily: 'Evolution/Camel.Stream',
              +				uaUrl: 'http://live.gnome.org/Evolution/Camel.Stream',
              +				uaCompany: 'GNOME Project',
              +				uaCompanyUrl: 'http://www.gnome.org/',
              +				uaIcon: 'DLLicon.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Evolution/Camel.Stream'
              +			}
              +		},
              +		'403': {
              +			typeId: '5',
              +			metadata: {
              +				uaFamily: 'EventMachine',
              +				uaUrl: 'http://rubyeventmachine.com/',
              +				uaCompany: '',
              +				uaCompanyUrl: '',
              +				uaIcon: 'DLLicon.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=EventMachine'
              +			}
              +		},
              +		'404': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Sundance',
              +				uaUrl: 'http://www.digola.com/sundance.html',
              +				uaCompany: 'Digola',
              +				uaCompanyUrl: 'http://www.digola.com/',
              +				uaIcon: 'sundance.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Sundance'
              +			}
              +		},
              +		'405': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Chromium',
              +				uaUrl: 'http://dev.chromium.org/Home',
              +				uaCompany: 'Google Inc. and contributors',
              +				uaCompanyUrl: '',
              +				uaIcon: 'chromium.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Chromium'
              +			}
              +		},
              +		'406': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Columbus',
              +				uaUrl: 'http://www.columbus-browser.com/',
              +				uaCompany: 'Hipgnosis Vision',
              +				uaCompanyUrl: 'http://www.hipgnosis.ro/',
              +				uaIcon: 'columbus.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Columbus'
              +			}
              +		},
              +		'407': {
              +			typeId: '18',
              +			metadata: {
              +				uaFamily: 'Plex Media Center',
              +				uaUrl: 'http://www.plexapp.com/',
              +				uaCompany: 'Plex comunity',
              +				uaCompanyUrl: '',
              +				uaIcon: 'plex.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Plex Media Center'
              +			}
              +		},
              +		'408': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'WebRender',
              +				uaUrl: 'http://webrender.99k.org/',
              +				uaCompany: 'Anand Bose',
              +				uaCompanyUrl: 'http://anandbose.99k.org/',
              +				uaIcon: 'webrender.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=WebRender'
              +			}
              +		},
              +		'409': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'CoolNovo',
              +				uaUrl: 'http://coolnovo.com/',
              +				uaCompany: 'Maple Studio',
              +				uaCompanyUrl: '',
              +				uaIcon: 'coolnovo.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=CoolNovo'
              +			}
              +		},
              +		'410': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Usejump',
              +				uaUrl: 'http://www.usejump.com/',
              +				uaCompany: 'Usejump team',
              +				uaCompanyUrl: '',
              +				uaIcon: 'usejump.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Usejump'
              +			}
              +		},
              +		'411': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Sundial',
              +				uaUrl: 'http://www.sundialbrowser.com/',
              +				uaCompany: 'Unifiedroot',
              +				uaCompanyUrl: 'http://www.unifiedroot.com/',
              +				uaIcon: 'sundial.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Sundial'
              +			}
              +		},
              +		'412': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Alienforce',
              +				uaUrl: 'http://sourceforge.net/projects/alienforce/',
              +				uaCompany: 'KBclub Universal',
              +				uaCompanyUrl: 'http://kbclub.users.sourceforge.net/',
              +				uaIcon: 'alienforce.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Alienforce'
              +			}
              +		},
              +		'413': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'Google Rich Snippets Testing Tool',
              +				uaUrl: 'http://www.google.com/webmasters/tools/richsnippets',
              +				uaCompany: 'Google Inc.',
              +				uaCompanyUrl: 'http://www.google.com/',
              +				uaIcon: 'feedfetcher-google.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Google Rich Snippets Testing Tool'
              +			}
              +		},
              +		'414': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'HTML2JPG',
              +				uaUrl: 'http://www.html2jpg.com/',
              +				uaCompany: 'BVBA Adygo',
              +				uaCompanyUrl: 'http://www.adygo.com/',
              +				uaIcon: 'html2jpg.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=HTML2JPG'
              +			}
              +		},
              +		'415': {
              +			typeId: '15',
              +			metadata: {
              +				uaFamily: 'iCatcher!',
              +				uaUrl: 'http://joeisanerd.com/apps/iCatcher',
              +				uaCompany: 'Joe Isanerd',
              +				uaCompanyUrl: 'http://joeisanerd.com/',
              +				uaIcon: 'iCatcher.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=iCatcher!'
              +			}
              +		},
              +		'416': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Baidu Browser',
              +				uaUrl: 'http://liulanqi.baidu.com/',
              +				uaCompany: 'Baidu, Inc.',
              +				uaCompanyUrl: 'http://www.baidu.com/',
              +				uaIcon: 'baidubrowser.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Baidu Browser'
              +			}
              +		},
              +		'417': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Sogou Explorer',
              +				uaUrl: 'http://ie.sogou.com/',
              +				uaCompany: 'Sohu.com, Inc.',
              +				uaCompanyUrl: 'http://www.sohu.com/',
              +				uaIcon: 'sogouexplorer.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Sogou Explorer'
              +			}
              +		},
              +		'418': {
              +			typeId: '18',
              +			metadata: {
              +				uaFamily: 'MPlayer2',
              +				uaUrl: 'http://www.mplayer2.org/',
              +				uaCompany: 'mplayer2 project',
              +				uaCompanyUrl: '',
              +				uaIcon: 'mplayer.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=MPlayer2'
              +			}
              +		},
              +		'419': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'ZipZap',
              +				uaUrl: 'http://www.zipzaphome.com/',
              +				uaCompany: 'JE Rhoads Company, LLC',
              +				uaCompanyUrl: 'http://www.jerhoads.com/',
              +				uaIcon: 'zipzap.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=ZipZap'
              +			}
              +		},
              +		'420': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'QupZilla',
              +				uaUrl: 'http://www.qupzilla.com/',
              +				uaCompany: 'David Rosca',
              +				uaCompanyUrl: '',
              +				uaIcon: 'qupzilla.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=QupZilla'
              +			}
              +		},
              +		'421': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Patriott',
              +				uaUrl: 'http://madgroup.x10.mx/patriott1.php',
              +				uaCompany: 'MadWorks Group.',
              +				uaCompanyUrl: 'http://madgroup.x10.mx/',
              +				uaIcon: 'patriott.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Patriott'
              +			}
              +		},
              +		'422': {
              +			typeId: '3',
              +			metadata: {
              +				uaFamily: 'Tizen Browser',
              +				uaUrl: 'https://www.tizen.org/',
              +				uaCompany: 'Tizen Project',
              +				uaCompanyUrl: 'https://www.tizen.org/',
              +				uaIcon: 'tizen.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Tizen Browser'
              +			}
              +		},
              +		'423': {
              +			typeId: '3',
              +			metadata: {
              +				uaFamily: 'Chrome Mobile',
              +				uaUrl: 'http://www.google.com/intl/en/chrome/browser/mobile/',
              +				uaCompany: 'Google Inc.',
              +				uaCompanyUrl: 'http://www.google.com/',
              +				uaIcon: 'chrome.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Chrome Mobile'
              +			}
              +		},
              +		'424': {
              +			typeId: '18',
              +			metadata: {
              +				uaFamily: 'Winamp for Android',
              +				uaUrl: 'http://www.winamp.com/android',
              +				uaCompany: 'Nullsoft, Inc.',
              +				uaCompanyUrl: 'http://en.wikipedia.org/wiki/Nullsoft',
              +				uaIcon: 'winamp.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Winamp for Android'
              +			}
              +		},
              +		'425': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'Apache internal dummy connection',
              +				uaUrl: 'http://wiki.apache.org/httpd/InternalDummyConnection',
              +				uaCompany: 'Apache Software Foundation',
              +				uaCompanyUrl: 'http://www.apache.org/',
              +				uaIcon: 'ab.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Apache internal dummy connection'
              +			}
              +		},
              +		'426': {
              +			typeId: '3',
              +			metadata: {
              +				uaFamily: 'NineSky',
              +				uaUrl: 'http://ninesky.com/',
              +				uaCompany: 'ninesky.com',
              +				uaCompanyUrl: '',
              +				uaIcon: 'ninesky.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=NineSky'
              +			}
              +		},
              +		'427': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Maple browser',
              +				uaUrl: 'http://www.freethetvchallenge.com/details/faq',
              +				uaCompany: 'Samsung',
              +				uaCompanyUrl: 'http://www.samsung.com/',
              +				uaIcon: 'maple.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Maple browser'
              +			}
              +		},
              +		'428': {
              +			typeId: '3',
              +			metadata: {
              +				uaFamily: 'wOSBrowser',
              +				uaUrl: '',
              +				uaCompany: 'Hewlett-Packard',
              +				uaCompanyUrl: 'http://www.hp.com/',
              +				uaIcon: 'webos.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=wOSBrowser'
              +			}
              +		},
              +		'429': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'Nokia SyncML Client',
              +				uaUrl: 'http://www.developer.nokia.com/Community/Wiki/SyncML_Client_API',
              +				uaCompany: 'Nokia',
              +				uaCompanyUrl: 'http://www.nokia.com/',
              +				uaIcon: 'nokiaSyncML.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Nokia SyncML Client'
              +			}
              +		},
              +		'430': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Charon',
              +				uaUrl: 'http://en.wikipedia.org/wiki/Charon_%28web_browser%29',
              +				uaCompany: 'Vita Nuova Holdings Ltd',
              +				uaCompanyUrl: 'http://www.vitanuova.com/',
              +				uaIcon: 'charon.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Charon'
              +			}
              +		},
              +		'432': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'JS-Kit/Echo',
              +				uaUrl: 'http://sites.google.com/site/echocomments/home',
              +				uaCompany: 'Echo',
              +				uaCompanyUrl: 'http://aboutecho.com/',
              +				uaIcon: 'JS-Kit.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=JS-Kit/Echo'
              +			}
              +		},
              +		'433': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'Podkicker',
              +				uaUrl: 'http://www.podkicker.com/',
              +				uaCompany: 'skiplist',
              +				uaCompanyUrl: '',
              +				uaIcon: 'podkicker.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Podkicker'
              +			}
              +		},
              +		'434': {
              +			typeId: '5',
              +			metadata: {
              +				uaFamily: 'Python-requests',
              +				uaUrl: 'http://python-requests.org/',
              +				uaCompany: 'Kenneth Reitz',
              +				uaCompanyUrl: 'http://kennethreitz.com/',
              +				uaIcon: 'pythonurllib.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Python-requests'
              +			}
              +		},
              +		'436': {
              +			typeId: '3',
              +			metadata: {
              +				uaFamily: 'Atomic Web Browser',
              +				uaUrl: 'http://atomicwebbrowser.com/',
              +				uaCompany: 'Richard Trautvetter',
              +				uaCompanyUrl: '',
              +				uaIcon: 'AtomicWebBrowser.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Atomic Web Browser'
              +			}
              +		},
              +		'437': {
              +			typeId: '15',
              +			metadata: {
              +				uaFamily: 'Reeder',
              +				uaUrl: 'http://reederapp.com/',
              +				uaCompany: 'Silvio Rizzi',
              +				uaCompanyUrl: 'http://madeatgloria.com/',
              +				uaIcon: 'reader.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Reeder'
              +			}
              +		},
              +		'438': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'WordPress pingback',
              +				uaUrl: 'http://codex.wordpress.org/Introduction_to_Blogging#Pingbacks',
              +				uaCompany: 'wordpress.org',
              +				uaCompanyUrl: 'http://wordpress.org/',
              +				uaIcon: 'wordpress.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=WordPress pingback'
              +			}
              +		},
              +		'439': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'TenFourFox',
              +				uaUrl: 'http://www.floodgap.com/software/tenfourfox/',
              +				uaCompany: 'Cameron Kaiser',
              +				uaCompanyUrl: 'http://www.floodgap.com/',
              +				uaIcon: 'TenFourFox.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=TenFourFox'
              +			}
              +		},
              +		'440': {
              +			typeId: '5',
              +			metadata: {
              +				uaFamily: 'PEAR HTTP_Request',
              +				uaUrl: 'http://pear.php.net/package/HTTP_Request',
              +				uaCompany: 'Richard Heyes',
              +				uaCompanyUrl: '',
              +				uaIcon: 'php.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=PEAR HTTP_Request'
              +			}
              +		},
              +		'441': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'D+',
              +				uaUrl: 'http://dplus-browser.sourceforge.net/',
              +				uaCompany: 'Benjamin Johnson',
              +				uaCompanyUrl: 'http://obeythepenguin.users.sourceforge.net/',
              +				uaIcon: 'dillo.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=D+'
              +			}
              +		},
              +		'442': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'zBrowser',
              +				uaUrl: 'http://sites.google.com/site/zeromusparadoxe01/zbrowser',
              +				uaCompany: 'Bastien Pederencino',
              +				uaCompanyUrl: 'http://sites.google.com/site/zeromusparadoxe01/',
              +				uaIcon: 'zBrowser.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=zBrowser'
              +			}
              +		},
              +		'443': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'SlimBoat',
              +				uaUrl: 'http://slimboat.com/',
              +				uaCompany: 'FlashPeak Inc.',
              +				uaCompanyUrl: 'http://www.flashpeak.com/',
              +				uaIcon: 'slimboat.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=SlimBoat'
              +			}
              +		},
              +		'445': {
              +			typeId: '5',
              +			metadata: {
              +				uaFamily: 'Mechanize',
              +				uaUrl: 'http://mechanize.rubyforge.org/',
              +				uaCompany: 'Aaron Patterson',
              +				uaCompanyUrl: 'http://tenderlovemaking.com/',
              +				uaIcon: 'ruby_on_rails.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Mechanize'
              +			}
              +		},
              +		'446': {
              +			typeId: '5',
              +			metadata: {
              +				uaFamily: 'HTMLayout',
              +				uaUrl: 'http://www.terrainformatica.com/htmlayout/main.whtm',
              +				uaCompany: 'Terra Informatica Software, Inc.',
              +				uaCompanyUrl: 'http://www.terrainformatica.com/',
              +				uaIcon: 'DLLicon.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=HTMLayout'
              +			}
              +		},
              +		'447': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'SaaYaa Explorer',
              +				uaUrl: 'http://www.saayaa.com/',
              +				uaCompany: 'RuanMei.com',
              +				uaCompanyUrl: 'http://www.ruanmei.com/',
              +				uaIcon: 'SaaYaa.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=SaaYaa Explorer'
              +			}
              +		},
              +		'448': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Ryouko',
              +				uaUrl: 'http://sourceforge.net/projects/ryouko/',
              +				uaCompany: 'Daniel Sim',
              +				uaCompanyUrl: 'http://sourceforge.net/users/foxhead128/',
              +				uaIcon: 'ryouko.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Ryouko'
              +			}
              +		},
              +		'449': {
              +			typeId: '5',
              +			metadata: {
              +				uaFamily: 'Anemone',
              +				uaUrl: 'http://anemone.rubyforge.org/',
              +				uaCompany: 'Chris Kite',
              +				uaCompanyUrl: 'http://www.chriskite.com/',
              +				uaIcon: 'DLLicon.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Anemone'
              +			}
              +		},
              +		'450': {
              +			typeId: '4',
              +			metadata: {
              +				uaFamily: 'Sparrow',
              +				uaUrl: 'http://sprw.me/',
              +				uaCompany: 'Google Inc.',
              +				uaCompanyUrl: 'http://www.google.com/',
              +				uaIcon: 'sparrow.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Sparrow'
              +			}
              +		},
              +		'451': {
              +			typeId: '18',
              +			metadata: {
              +				uaFamily: 'SubStream',
              +				uaUrl: 'http://itunes.apple.com/us/app/substream/id389906706?mt=8',
              +				uaCompany: 'Figment, Inc.',
              +				uaCompanyUrl: 'http://www.figmentdevelopment.com/',
              +				uaIcon: 'SubStream.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=SubStream'
              +			}
              +		},
              +		'452': {
              +			typeId: '4',
              +			metadata: {
              +				uaFamily: 'Barca',
              +				uaUrl: 'http://www.pocosystems.com/home/index.php?option=content&task=category&sectionid=2&id=9&Itemid=27',
              +				uaCompany: 'Poco Systems Inc',
              +				uaCompanyUrl: 'http://www.pocosystems.com/',
              +				uaIcon: 'barca.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Barca'
              +			}
              +		},
              +		'453': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'A1 Sitemap Generator',
              +				uaUrl: 'http://www.microsystools.com/products/sitemap-generator/',
              +				uaCompany: 'Microsys',
              +				uaCompanyUrl: 'http://www.microsystools.com/home/microsys.php',
              +				uaIcon: 'A1sitemapGenerator.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=A1 Sitemap Generator'
              +			}
              +		},
              +		'454': {
              +			typeId: '3',
              +			metadata: {
              +				uaFamily: 'PS Vita browser',
              +				uaUrl: '',
              +				uaCompany: 'Sony Computer Entertainment',
              +				uaCompanyUrl: 'http://www.scei.co.jp/',
              +				uaIcon: 'ps-vita-browser.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=PS Vita browser'
              +			}
              +		},
              +		'455': {
              +			typeId: '3',
              +			metadata: {
              +				uaFamily: 'QQbrowser',
              +				uaUrl: 'http://browser.qq.com/',
              +				uaCompany: 'Tencent Ltd.',
              +				uaCompanyUrl: 'http://www.tencent.com/',
              +				uaIcon: 'QQbrowser.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=QQbrowser'
              +			}
              +		},
              +		'456': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Beamrise',
              +				uaUrl: 'http://www.beamrise.com/',
              +				uaCompany: 'SIEN S.A.',
              +				uaCompanyUrl: 'http://www.sien.com/',
              +				uaIcon: 'beamrise.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Beamrise'
              +			}
              +		},
              +		'457': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Yandex.Browser',
              +				uaUrl: 'http://browser.yandex.com/',
              +				uaCompany: 'Yandex ',
              +				uaCompanyUrl: 'http://yandex.com/',
              +				uaIcon: 'Yandex.Browser.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Yandex.Browser'
              +			}
              +		},
              +		'458': {
              +			typeId: '3',
              +			metadata: {
              +				uaFamily: 'Silk',
              +				uaUrl: 'http://amazonsilk.wordpress.com/',
              +				uaCompany: 'Amazon.com, Inc.',
              +				uaCompanyUrl: 'http://www.amazon.com/',
              +				uaIcon: 'amazon_silk.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Silk'
              +			}
              +		},
              +		'459': {
              +			typeId: '5',
              +			metadata: {
              +				uaFamily: 'Apache-HttpClient',
              +				uaUrl: 'http://hc.apache.org/httpcomponents-client-ga/',
              +				uaCompany: 'Apache Software Foundation',
              +				uaCompanyUrl: 'http://www.apache.org/',
              +				uaIcon: 'jakarta.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Apache-HttpClient'
              +			}
              +		},
              +		'460': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Nintendo Browser',
              +				uaUrl: 'http://en.wikipedia.org/wiki/Wii_u',
              +				uaCompany: 'Nintendo of America Inc.',
              +				uaCompanyUrl: 'http://www.nintendo.com/',
              +				uaIcon: 'wii.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Nintendo Browser'
              +			}
              +		},
              +		'461': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'Dell Web Monitor',
              +				uaUrl: '',
              +				uaCompany: 'Quest Software',
              +				uaCompanyUrl: 'http://www.quest.com/',
              +				uaIcon: 'dell.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Dell Web Monitor'
              +			}
              +		},
              +		'462': {
              +			typeId: '15',
              +			metadata: {
              +				uaFamily: 'FeedDemon',
              +				uaUrl: 'http://www.feeddemon.com/',
              +				uaCompany: 'NewsGator Technologies, Inc.',
              +				uaCompanyUrl: 'http://www.newsgator.com/',
              +				uaIcon: 'FeedDemon.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=FeedDemon'
              +			}
              +		},
              +		'463': {
              +			typeId: '5',
              +			metadata: {
              +				uaFamily: 'XML-RPC for Ruby',
              +				uaUrl: 'http://www.ntecs.de/ruby/xmlrpc4r/howto.html',
              +				uaCompany: 'Michael Neumann',
              +				uaCompanyUrl: 'http://www.ntecs.de/',
              +				uaIcon: 'ruby-on-rails.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=XML-RPC for Ruby'
              +			}
              +		},
              +		'464': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'Pattern',
              +				uaUrl: 'http://www.clips.ua.ac.be/pages/pattern',
              +				uaCompany: 'Computational Linguistics & Psycholinguistics Research Center ',
              +				uaCompanyUrl: 'http://www.clips.ua.ac.be/',
              +				uaIcon: 'pythonurllib.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Pattern'
              +			}
              +		},
              +		'465': {
              +			typeId: '4',
              +			metadata: {
              +				uaFamily: 'Eudora',
              +				uaUrl: 'http://www.eudora.com/archive.html',
              +				uaCompany: 'Qualcomm Incorporated.',
              +				uaCompanyUrl: 'http://www.qualcomm.com/',
              +				uaIcon: 'eudora.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Eudora'
              +			}
              +		},
              +		'466': {
              +			typeId: '4',
              +			metadata: {
              +				uaFamily: 'Apple Mail',
              +				uaUrl: 'http://en.wikipedia.org/wiki/Apple_mail',
              +				uaCompany: 'Apple Inc.',
              +				uaCompanyUrl: 'http://www.apple.com/',
              +				uaIcon: 'apple-mail.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Apple Mail'
              +			}
              +		},
              +		'467': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Polarity',
              +				uaUrl: 'http://polarityweb.webs.com/',
              +				uaCompany: 'Stanley Lim',
              +				uaCompanyUrl: '',
              +				uaIcon: 'polarity.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Polarity'
              +			}
              +		},
              +		'468': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Superbird',
              +				uaUrl: 'http://superbird.me/',
              +				uaCompany: 'The Superbird Authors',
              +				uaCompanyUrl: '',
              +				uaIcon: 'superbird.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Superbird'
              +			}
              +		},
              +		'469': {
              +			typeId: '3',
              +			metadata: {
              +				uaFamily: 'NetFront Life',
              +				uaUrl: 'http://gl.access-company.com/files/legacy/products/nflife/app_browser2.html',
              +				uaCompany: 'ACCESS CO., LTD.',
              +				uaCompanyUrl: 'http://www.access-company.com/',
              +				uaIcon: 'netfrontlife.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=NetFront Life'
              +			}
              +		},
              +		'470': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'YRC Weblink',
              +				uaUrl: 'http://weblink.justyrc.com/',
              +				uaCompany: 'YRC Group Inc.',
              +				uaCompanyUrl: 'http://www.justyrc.com/',
              +				uaIcon: 'yrc_webling.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=YRC Weblink'
              +			}
              +		},
              +		'471': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'IceDragon',
              +				uaUrl: 'http://www.comodo.com/home/browsers-toolbars/icedragon-browser.php',
              +				uaCompany: 'Comodo Group, Inc.',
              +				uaCompanyUrl: 'http://www.comodo.com/',
              +				uaIcon: 'icedragon.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=IceDragon'
              +			}
              +		},
              +		'473': {
              +			typeId: '4',
              +			metadata: {
              +				uaFamily: 'Outlook 2013',
              +				uaUrl: 'http://en.wikipedia.org/wiki/Microsoft_Outlook',
              +				uaCompany: 'Microsoft Corporation.',
              +				uaCompanyUrl: 'http://www.microsoft.com/',
              +				uaIcon: 'outlook2013.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Outlook 2013'
              +			}
              +		},
              +		'474': {
              +			typeId: '5',
              +			metadata: {
              +				uaFamily: 'RestSharp',
              +				uaUrl: 'http://restsharp.org/',
              +				uaCompany: 'John Sheehan',
              +				uaCompanyUrl: 'http://john-sheehan.com/',
              +				uaIcon: 'DLLicon.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=RestSharp'
              +			}
              +		},
              +		'475': {
              +			typeId: '3',
              +			metadata: {
              +				uaFamily: 'Yandex.Browser mobile',
              +				uaUrl: 'http://mobil.yandex.com/',
              +				uaCompany: 'Yandex ',
              +				uaCompanyUrl: 'http://yandex.com/',
              +				uaIcon: 'Yandex.Browser.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Yandex.Browser mobile'
              +			}
              +		},
              +		'476': {
              +			typeId: '3',
              +			metadata: {
              +				uaFamily: 'Puffin',
              +				uaUrl: 'http://www.puffinbrowser.com/',
              +				uaCompany: 'CloudMosa Inc.',
              +				uaCompanyUrl: 'http://www.cloudmosa.com/',
              +				uaIcon: 'puffin.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Puffin'
              +			}
              +		},
              +		'477': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: 'Roccat browser',
              +				uaUrl: 'http://www.runecats.com/roccat.html',
              +				uaCompany: 'Runecats',
              +				uaCompanyUrl: 'http://runecats.com/',
              +				uaIcon: 'roccat.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Roccat browser'
              +			}
              +		},
              +		'478': {
              +			typeId: '4',
              +			metadata: {
              +				uaFamily: 'AirMail',
              +				uaUrl: 'http://airmailapp.com/',
              +				uaCompany: 'Bloop S.R.L.',
              +				uaCompanyUrl: 'http://bloop.info/',
              +				uaIcon: 'airmail.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=AirMail'
              +			}
              +		},
              +		'479': {
              +			typeId: '0',
              +			metadata: {
              +				uaFamily: '3DS Browser',
              +				uaUrl: 'http://en.wikipedia.org/wiki/Internet_Browser_(Nintendo_3DS)',
              +				uaCompany: 'Nintendo of America Inc.',
              +				uaCompanyUrl: 'http://www.nintendo.com/',
              +				uaIcon: '3DS-Browser.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=3DS Browser'
              +			}
              +		},
              +		'481': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'BrowserEmulator',
              +				uaUrl: 'http://www.dejavu.org/emulator.htm',
              +				uaCompany: 'Metamatrix AB',
              +				uaCompanyUrl: 'http://www.metamatrix.se/',
              +				uaIcon: 'browseremulator.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=BrowserEmulator'
              +			}
              +		},
              +		'482': {
              +			typeId: '3',
              +			metadata: {
              +				uaFamily: 'Palm WebPro',
              +				uaUrl: 'http://www.hpwebos.com/us/support/handbooks/tungstent/webbrowser_hb.pdf',
              +				uaCompany: 'Palm Inc.',
              +				uaCompanyUrl: 'http://www.palm.com/',
              +				uaIcon: 'palmWebPro.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=Palm WebPro'
              +			}
              +		},
              +		'483': {
              +			typeId: '20',
              +			metadata: {
              +				uaFamily: 'PhantomJS',
              +				uaUrl: 'http://phantomjs.org/',
              +				uaCompany: 'Ariya Hidayat',
              +				uaCompanyUrl: 'http://ariya.ofilabs.com/about',
              +				uaIcon: 'PhantomJS.png',
              +				uaInfoUrl: '/list-of-ua/browser-detail?browser=PhantomJS'
              +			}
              +		},
              +		order: [
              +			'1',
              +			'2',
              +			'3',
              +			'4',
              +			'5',
              +			'6',
              +			'7',
              +			'8',
              +			'9',
              +			'10',
              +			'11',
              +			'14',
              +			'15',
              +			'16',
              +			'17',
              +			'18',
              +			'19',
              +			'21',
              +			'22',
              +			'23',
              +			'24',
              +			'25',
              +			'27',
              +			'28',
              +			'29',
              +			'30',
              +			'31',
              +			'32',
              +			'33',
              +			'35',
              +			'39',
              +			'40',
              +			'41',
              +			'42',
              +			'43',
              +			'44',
              +			'45',
              +			'46',
              +			'47',
              +			'48',
              +			'49',
              +			'50',
              +			'51',
              +			'52',
              +			'53',
              +			'54',
              +			'55',
              +			'56',
              +			'57',
              +			'58',
              +			'59',
              +			'61',
              +			'62',
              +			'71',
              +			'74',
              +			'79',
              +			'81',
              +			'82',
              +			'85',
              +			'86',
              +			'87',
              +			'88',
              +			'89',
              +			'90',
              +			'91',
              +			'93',
              +			'94',
              +			'96',
              +			'99',
              +			'100',
              +			'105',
              +			'111',
              +			'117',
              +			'119',
              +			'120',
              +			'121',
              +			'122',
              +			'123',
              +			'124',
              +			'125',
              +			'126',
              +			'128',
              +			'129',
              +			'130',
              +			'131',
              +			'132',
              +			'133',
              +			'134',
              +			'135',
              +			'136',
              +			'137',
              +			'138',
              +			'139',
              +			'140',
              +			'141',
              +			'142',
              +			'143',
              +			'144',
              +			'145',
              +			'146',
              +			'147',
              +			'148',
              +			'149',
              +			'150',
              +			'151',
              +			'152',
              +			'153',
              +			'154',
              +			'155',
              +			'156',
              +			'157',
              +			'158',
              +			'159',
              +			'160',
              +			'161',
              +			'162',
              +			'163',
              +			'165',
              +			'166',
              +			'167',
              +			'168',
              +			'169',
              +			'170',
              +			'171',
              +			'172',
              +			'173',
              +			'174',
              +			'175',
              +			'176',
              +			'177',
              +			'178',
              +			'179',
              +			'180',
              +			'181',
              +			'182',
              +			'183',
              +			'184',
              +			'185',
              +			'187',
              +			'188',
              +			'189',
              +			'190',
              +			'191',
              +			'192',
              +			'193',
              +			'194',
              +			'195',
              +			'196',
              +			'197',
              +			'198',
              +			'199',
              +			'200',
              +			'201',
              +			'202',
              +			'204',
              +			'205',
              +			'206',
              +			'207',
              +			'208',
              +			'209',
              +			'210',
              +			'211',
              +			'212',
              +			'213',
              +			'214',
              +			'216',
              +			'217',
              +			'218',
              +			'219',
              +			'220',
              +			'221',
              +			'222',
              +			'223',
              +			'225',
              +			'226',
              +			'227',
              +			'228',
              +			'229',
              +			'230',
              +			'231',
              +			'232',
              +			'233',
              +			'234',
              +			'235',
              +			'236',
              +			'237',
              +			'238',
              +			'239',
              +			'240',
              +			'241',
              +			'242',
              +			'243',
              +			'244',
              +			'245',
              +			'246',
              +			'247',
              +			'248',
              +			'249',
              +			'250',
              +			'251',
              +			'252',
              +			'253',
              +			'254',
              +			'255',
              +			'256',
              +			'257',
              +			'258',
              +			'259',
              +			'260',
              +			'261',
              +			'262',
              +			'263',
              +			'264',
              +			'265',
              +			'266',
              +			'267',
              +			'268',
              +			'269',
              +			'270',
              +			'271',
              +			'272',
              +			'273',
              +			'274',
              +			'276',
              +			'277',
              +			'278',
              +			'279',
              +			'280',
              +			'281',
              +			'282',
              +			'283',
              +			'284',
              +			'285',
              +			'286',
              +			'287',
              +			'288',
              +			'289',
              +			'290',
              +			'291',
              +			'292',
              +			'293',
              +			'294',
              +			'296',
              +			'297',
              +			'298',
              +			'299',
              +			'300',
              +			'301',
              +			'302',
              +			'303',
              +			'304',
              +			'305',
              +			'306',
              +			'307',
              +			'308',
              +			'309',
              +			'310',
              +			'311',
              +			'312',
              +			'313',
              +			'314',
              +			'315',
              +			'316',
              +			'317',
              +			'318',
              +			'319',
              +			'320',
              +			'321',
              +			'322',
              +			'323',
              +			'324',
              +			'325',
              +			'326',
              +			'327',
              +			'328',
              +			'329',
              +			'330',
              +			'331',
              +			'332',
              +			'333',
              +			'334',
              +			'335',
              +			'336',
              +			'337',
              +			'338',
              +			'339',
              +			'340',
              +			'341',
              +			'342',
              +			'343',
              +			'344',
              +			'345',
              +			'346',
              +			'347',
              +			'348',
              +			'349',
              +			'350',
              +			'351',
              +			'352',
              +			'353',
              +			'354',
              +			'355',
              +			'356',
              +			'357',
              +			'358',
              +			'359',
              +			'360',
              +			'361',
              +			'362',
              +			'363',
              +			'364',
              +			'365',
              +			'366',
              +			'367',
              +			'368',
              +			'369',
              +			'370',
              +			'371',
              +			'372',
              +			'373',
              +			'374',
              +			'375',
              +			'376',
              +			'377',
              +			'378',
              +			'379',
              +			'380',
              +			'381',
              +			'382',
              +			'383',
              +			'384',
              +			'385',
              +			'386',
              +			'387',
              +			'388',
              +			'389',
              +			'390',
              +			'392',
              +			'393',
              +			'394',
              +			'395',
              +			'396',
              +			'397',
              +			'399',
              +			'400',
              +			'401',
              +			'402',
              +			'403',
              +			'404',
              +			'405',
              +			'406',
              +			'407',
              +			'408',
              +			'409',
              +			'410',
              +			'411',
              +			'412',
              +			'413',
              +			'414',
              +			'415',
              +			'416',
              +			'417',
              +			'418',
              +			'419',
              +			'420',
              +			'421',
              +			'422',
              +			'423',
              +			'424',
              +			'425',
              +			'426',
              +			'427',
              +			'428',
              +			'429',
              +			'430',
              +			'432',
              +			'433',
              +			'434',
              +			'436',
              +			'437',
              +			'438',
              +			'439',
              +			'440',
              +			'441',
              +			'442',
              +			'443',
              +			'445',
              +			'446',
              +			'447',
              +			'448',
              +			'449',
              +			'450',
              +			'451',
              +			'452',
              +			'453',
              +			'454',
              +			'455',
              +			'456',
              +			'457',
              +			'458',
              +			'459',
              +			'460',
              +			'461',
              +			'462',
              +			'463',
              +			'464',
              +			'465',
              +			'466',
              +			'467',
              +			'468',
              +			'469',
              +			'470',
              +			'471',
              +			'473',
              +			'474',
              +			'475',
              +			'476',
              +			'477',
              +			'478',
              +			'479',
              +			'481',
              +			'482',
              +			'483'
              +		]
              +	},
              +	browserType: {
              +		'0': 'Browser',
              +		'1': 'Offline Browser',
              +		'3': 'Mobile Browser',
              +		'4': 'Email client',
              +		'5': 'Library',
              +		'6': 'Wap Browser',
              +		'10': 'Validator',
              +		'15': 'Feed Reader',
              +		'18': 'Multimedia Player',
              +		'20': 'Other',
              +		'50': 'Useragent Anonymizer',
              +		order: [
              +			'0',
              +			'1',
              +			'3',
              +			'4',
              +			'5',
              +			'6',
              +			'10',
              +			'15',
              +			'18',
              +			'20',
              +			'50'
              +		]
              +	},
              +	browserReg: {
              +		'1': {
              +			regexp: /mozilla[\s\S]*rv:[0-9\.]+[\s\S]*gecko\/[0-9]+[\s\S]*seamonkey\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '2'
              +		},
              +		'2': {
              +			regexp: /mozilla[\s\S]*rv:[0-9\.]+[\s\S]*gecko\/[0-9]+[\s\S]*camino\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '1'
              +		},
              +		'3': {
              +			regexp: /mozilla[\s\S]*rv:[0-9\.]+[\s\S]*gecko[\s\S]*firefox\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '3'
              +		},
              +		'4': {
              +			regexp: /mozilla[\s\S]*netscape[0-9]?\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '4'
              +		},
              +		'5': {
              +			regexp: /mozilla[\s\S]*gecko\/[0-9]+[\s\S]*epiphany\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '5'
              +		},
              +		'6': {
              +			regexp: /mozilla[\s\S]*gecko\/[0-9]+[\s\S]*galeon\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '6'
              +		},
              +		'7': {
              +			regexp: /mozilla[\s\S]*gecko\/[0-9]+[\s\S]*flock\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '7'
              +		},
              +		'8': {
              +			regexp: /mozilla[\s\S]*gecko\/[0-9]+[\s\S]*minimo\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '8'
              +		},
              +		'9': {
              +			regexp: /mozilla[\s\S]*gecko\/[0-9]+[\s\S]*k\-meleon\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '9'
              +		},
              +		'10': {
              +			regexp: /mozilla[\s\S]*gecko\/[0-9]+[\s\S]*k-ninja\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '10'
              +		},
              +		'11': {
              +			regexp: /mozilla[\s\S]*gecko[\s\S]*kazehakase\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '11'
              +		},
              +		'14': {
              +			regexp: /mozilla[\s\S]*rv[ :][0-9\.]+[\s\S]*gecko\/[0-9]+[\s\S]*firebird\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '14'
              +		},
              +		'15': {
              +			regexp: /mozilla[\s\S]*rv:[0-9\.]+[\s\S]*gecko\/[0-9]+[\s\S]*phoenix\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '15'
              +		},
              +		'16': {
              +			regexp: /mozilla[\s\S]*konqueror\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '16'
              +		},
              +		'17': {
              +			regexp: /mozilla[\s\S]*opera ([0-9][0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '17'
              +		},
              +		'18': {
              +			regexp: /^opera\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '17'
              +		},
              +		'19': {
              +			regexp: /mozilla[\s\S]*applewebkit\/[0-9]+[\s\S]*omniweb\/v[0-9\.]+/i,
              +			browserId: '18'
              +		},
              +		'20': {
              +			regexp: /mozilla[\s\S]*applewebkit\/[0-9]+[\s\S]*sunrisebrowser\/([0-9a-z\+\-\.]+)/i,
              +			browserId: '19'
              +		},
              +		'22': {
              +			regexp: /mozilla[\s\S]*applewebkit[\s\S]*shiira\/([0-9a-z\+\-\.]+)[\s\S]*safari/i,
              +			browserId: '21'
              +		},
              +		'23': {
              +			regexp: /mozilla[\s\S]*applewebkit[\s\S]*\/[0-9a-z\+\-\.]+[\s\S]*safari\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '22'
              +		},
              +		'24': {
              +			regexp: /dillo\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '23'
              +		},
              +		'25': {
              +			regexp: /icab[ \/]([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '24'
              +		},
              +		'26': {
              +			regexp: /^lynx\/([0-9a-z\.]+)[\s\S]*/i,
              +			browserId: '25'
              +		},
              +		'28': {
              +			regexp: /^elinks \(([0-9a-z\.]+)[\s\S]*/i,
              +			browserId: '27'
              +		},
              +		'29': {
              +			regexp: /^elinks\/([0-9a-z\.]+)[\s\S]*/i,
              +			browserId: '27'
              +		},
              +		'30': {
              +			regexp: /^elinks$/i,
              +			browserId: '27'
              +		},
              +		'31': {
              +			regexp: /^Wget\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '28'
              +		},
              +		'32': {
              +			regexp: /Amiga\-Aweb\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '29'
              +		},
              +		'33': {
              +			regexp: /AmigaVoyager\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '30'
              +		},
              +		'34': {
              +			regexp: /IBrowse\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '31'
              +		},
              +		'35': {
              +			regexp: /UP\.Browser\/([0-9a-zA-Z\.]+)[\s\S]*/,
              +			browserId: '32'
              +		},
              +		'36': {
              +			regexp: /UP\/([0-9a-zA-Z\.]+)[\s\S]*/,
              +			browserId: '32'
              +		},
              +		'37': {
              +			regexp: /NetFront\/([0-9a-z\.]+)[\s\S]*/i,
              +			browserId: '33'
              +		},
              +		'39': {
              +			regexp: /mozilla\/[\s\S]*MSIE ([0-9b\.]+)[\s\S]*/i,
              +			browserId: '35'
              +		},
              +		'42': {
              +			regexp: /offline explorer\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '39'
              +		},
              +		'44': {
              +			regexp: /mozilla[\s\S]*MSIE [0-9a-z\+\-\.]+[\s\S]*AOL ([0-9a-z\+\-\.]+)/i,
              +			browserId: '40'
              +		},
              +		'45': {
              +			regexp: /mozilla[\s\S]*MSIE [0-9a-z\+\-\.]+[\s\S]*America Online Browser ([0-9a-z\+\-\.]+)/i,
              +			browserId: '40'
              +		},
              +		'46': {
              +			regexp: /mozilla[\s\S]*MSIE [0-9a-z\+\-\.]+[\s\S]*Avant Browser ([0-9a-z\+\-\.]+)/i,
              +			browserId: '41'
              +		},
              +		'47': {
              +			regexp: /mozilla[\s\S]*MSIE [0-9a-z\+\-\.]+[\s\S]*Avant Browser/i,
              +			browserId: '41'
              +		},
              +		'48': {
              +			regexp: /mozilla[\s\S]*AvantGo ([0-9a-z\+\-\.]+)/i,
              +			browserId: '42'
              +		},
              +		'49': {
              +			regexp: /mozilla[\s\S]*Blazer\/([0-9a-z\+\-\.]+)/i,
              +			browserId: '43'
              +		},
              +		'50': {
              +			regexp: /mozilla[\s\S]*MSIE [0-9a-z\+\-\.]+[\s\S]*Crazy Browser ([0-9a-z \+\-\.]+)/i,
              +			browserId: '44'
              +		},
              +		'51': {
              +			regexp: /mozilla[\s\S]*MSIE [0-9a-z\+\-\.]+[\s\S]*Deepnet Explorer ([0-9a-z\+\-\.]+)/i,
              +			browserId: '45'
              +		},
              +		'52': {
              +			regexp: /mozilla[\s\S]*MSIE [0-9a-z\+\-\.]+[\s\S]*Deepnet Explorer/i,
              +			browserId: '45'
              +		},
              +		'53': {
              +			regexp: /mozilla[\s\S]*HTTrack ([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '46'
              +		},
              +		'54': {
              +			regexp: /mozilla[\s\S]*rv:[0-9\.]+[\s\S]*gecko\/[0-9]+[\s\S]*IceWeasel\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '47'
              +		},
              +		'55': {
              +			regexp: /mozilla[\s\S]*MSIE [0-9a-z\+\-\.]+[\s\S]*iRider ([0-9a-z\+\-\.]+)/i,
              +			browserId: '48'
              +		},
              +		'56': {
              +			regexp: /[\s\S]*isilox\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '49'
              +		},
              +		'57': {
              +			regexp: /mozilla[\s\S]*MSIE [0-9a-z\+\-\.]+[\s\S]*KKman([0-9a-z\+\-\.]+)/i,
              +			browserId: '50'
              +		},
              +		'58': {
              +			regexp: /libwww\-perl\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '51'
              +		},
              +		'59': {
              +			regexp: /mozilla[\s\S]*Lunascape\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '52'
              +		},
              +		'60': {
              +			regexp: /mozilla[\s\S]*Maxthon ([0-9a-z\+\-\.]+)/i,
              +			browserId: '53'
              +		},
              +		'61': {
              +			regexp: /mozilla[\s\S]*MSIE [0-9a-z\+\-\.]+[\s\S]*MyIE2/i,
              +			browserId: '53'
              +		},
              +		'62': {
              +			regexp: /mozilla[\s\S]*(rv:[0-9\.]+)[\s\S]*gecko\/[0-9]+[\s\S]*/i,
              +			browserId: '54'
              +		},
              +		'63': {
              +			regexp: /mozilla[\s\S]*MultiZilla ([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '55'
              +		},
              +		'64': {
              +			regexp: /mozilla[\s\S]*MSIE [0-9a-z\+\-\.]+[\s\S]*NetCaptor ([0-9a-z\+\-\.]+)/i,
              +			browserId: '56'
              +		},
              +		'65': {
              +			regexp: /Netgem\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '57'
              +		},
              +		'66': {
              +			regexp: /netsurf\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '58'
              +		},
              +		'67': {
              +			regexp: /mozilla[\s\S]*MSIE [0-9a-z\+\-\.]+[\s\S]*Sleipnir\/([0-9a-z\+\-\.]+)/i,
              +			browserId: '59'
              +		},
              +		'69': {
              +			regexp: /mozilla[\s\S]*rv:[0-9\.]+[\s\S]*gecko\/[0-9]+[\s\S]*firefox\/([0-9a-z\+\-\.]+)[\s\S]*swiftfox/i,
              +			browserId: '61'
              +		},
              +		'70': {
              +			regexp: /Teleport Pro\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '62'
              +		},
              +		'77': {
              +			regexp: /sunrise[ \/]([0-9a-z\+\-\.\/]+)/i,
              +			browserId: '19'
              +		},
              +		'78': {
              +			regexp: /mozilla[\s\S]*galeon\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '6'
              +		},
              +		'79': {
              +			regexp: /^Mozilla[\s\S]*AppleWebKit[\s\S]*\(KHTML, like Gecko\)$/i,
              +			browserId: '466'
              +		},
              +		'80': {
              +			regexp: /Openwave/i,
              +			browserId: '32'
              +		},
              +		'81': {
              +			regexp: /MSIE ([0-9a-z\+\-\.]+)[\s\S]*windows ce/i,
              +			browserId: '157'
              +		},
              +		'82': {
              +			regexp: /mozilla[\s\S]*\/[0-9\.]+[\s\S]*gecko[\s\S]*firefox[\s\S]*/i,
              +			browserId: '3'
              +		},
              +		'83': {
              +			regexp: /mozilla[\s\S]*(rv:[0-9\.]+)[\s\S]*/i,
              +			browserId: '54'
              +		},
              +		'86': {
              +			regexp: /webcopier[\s\S]*v([0-9a-z\.]+)/i,
              +			browserId: '71'
              +		},
              +		'89': {
              +			regexp: /MSIE[\s\S]*PhaseOut/i,
              +			browserId: '74'
              +		},
              +		'94': {
              +			regexp: /^Mozilla[\s\S]*Thunderbird\/([0-9a-zA-Z\.]+)/i,
              +			browserId: '79'
              +		},
              +		'95': {
              +			regexp: /^DoCoMo\//i,
              +			browserId: '33'
              +		},
              +		'97': {
              +			regexp: /doris\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '81'
              +		},
              +		'98': {
              +			regexp: /^Enigma browser$/i,
              +			browserId: '82'
              +		},
              +		'100': {
              +			regexp: /lwp\-request\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '51'
              +		},
              +		'102': {
              +			regexp: /Jakarta Commons-HttpClient\/([0-9a-zA-Z\.\-]+)/i,
              +			browserId: '85'
              +		},
              +		'103': {
              +			regexp: /IBrowse/i,
              +			browserId: '31'
              +		},
              +		'104': {
              +			regexp: /^curl ([0-9a-zA-Z\.\-]+)/i,
              +			browserId: '86'
              +		},
              +		'105': {
              +			regexp: /Aweb[\s\S]*Amiga/i,
              +			browserId: '29'
              +		},
              +		'106': {
              +			regexp: /amaya\/([0-9a-zA-Z\.\-+]+)/i,
              +			browserId: '87'
              +		},
              +		'107': {
              +			regexp: /GetRight\/([0-9a-zA-Z\.\-\+]+)/i,
              +			browserId: '88'
              +		},
              +		'108': {
              +			regexp: /^Mozilla[\s\S]*OmniWeb\/([1-9a-zA-z\.\-]+)/i,
              +			browserId: '18'
              +		},
              +		'109': {
              +			regexp: /Mozilla[\s\S]*OffByOne/i,
              +			browserId: '89'
              +		},
              +		'110': {
              +			regexp: /Python\-urllib\/([0-9a-zA-Z\.\-]+)/i,
              +			browserId: '90'
              +		},
              +		'111': {
              +			regexp: /w3m\/([0-9a-zA-z\-\+\.]+)/i,
              +			browserId: '91'
              +		},
              +		'113': {
              +			regexp: /^WebZIP\/([0-9a-zA-Z\.\-]+)/i,
              +			browserId: '93'
              +		},
              +		'114': {
              +			regexp: /^Mozilla[\s\S]*AppleWebKit[\s\S]*Shiira\/([0-9a-zA-z\.\-]+)/i,
              +			browserId: '21'
              +		},
              +		'115': {
              +			regexp: /ICEbrowser\/([0-9a-z_\.\-]+)/i,
              +			browserId: '94'
              +		},
              +		'117': {
              +			regexp: /Blazer ([0-9\.]+)/i,
              +			browserId: '43'
              +		},
              +		'118': {
              +			regexp: /Iceape\/([0-9a-zA-z\.\-]+)/i,
              +			browserId: '96'
              +		},
              +		'120': {
              +			regexp: /Jakarta Commons\-HttpClient/i,
              +			browserId: '85'
              +		},
              +		'122': {
              +			regexp: /HotJava\/([0-9a-zA-Z\.\- ]+)/i,
              +			browserId: '99'
              +		},
              +		'123': {
              +			regexp: /JoBo\/([0-9a-z\.\-]+)/i,
              +			browserId: '100'
              +		},
              +		'126': {
              +			regexp: /Sleipnir Version ([0-9a-z\.]+)/i,
              +			browserId: '59'
              +		},
              +		'130': {
              +			regexp: /poe-component-client-http\/([0-9a-z\.\-]+)/i,
              +			browserId: '105'
              +		},
              +		'137': {
              +			regexp: /snoopy v([1-9\.]+)/i,
              +			browserId: '111'
              +		},
              +		'138': {
              +			regexp: /Lynx/i,
              +			browserId: '25'
              +		},
              +		'139': {
              +			regexp: /libwww\-perl/i,
              +			browserId: '51'
              +		},
              +		'141': {
              +			regexp: /NetFront([0-9a-z\.]+)[\s\S]*/i,
              +			browserId: '33'
              +		},
              +		'143': {
              +			regexp: /^opera ([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '17'
              +		},
              +		'147': {
              +			regexp: /NCSA_Mosaic\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '117'
              +		},
              +		'149': {
              +			regexp: /mozilla[\s\S]*rv:[0-9\.]+[\s\S]*gecko[\s\S]*kapiko\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '119'
              +		},
              +		'150': {
              +			regexp: /mozilla[\s\S]*chrome\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '120'
              +		},
              +		'151': {
              +			regexp: /mozilla[\s\S]*applewebkit[\s\S]*AdobeAIR\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '121'
              +		},
              +		'152': {
              +			regexp: /^lwp-trivial\/([0-9.]+)$/i,
              +			browserId: '122'
              +		},
              +		'153': {
              +			regexp: /^WWW-Mechanize\/([0-9a-z\+\-\.]+)/i,
              +			browserId: '123'
              +		},
              +		'155': {
              +			regexp: /^Xenu Link Sleuth ([0-9a-z\+\-\.]+)$/i,
              +			browserId: '124'
              +		},
              +		'156': {
              +			regexp: /^SiteSucker\/([0-9a-z\.]+)/i,
              +			browserId: '125'
              +		},
              +		'157': {
              +			regexp: /mozilla[\s\S]*applewebkit[\s\S]*arora\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '126'
              +		},
              +		'160': {
              +			regexp: /mozilla[\s\S]*rv:[0-9\.]+[\s\S]*gecko\/[0-9]+[\s\S]*Shiretoko\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '128'
              +		},
              +		'161': {
              +			regexp: /mozilla[\s\S]*rv:[0-9\.]+[\s\S]*gecko\/[0-9]+[\s\S]*Minefield\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '129'
              +		},
              +		'162': {
              +			regexp: /mozilla[\s\S]*applewebkit[\s\S]*iron\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '130'
              +		},
              +		'163': {
              +			regexp: /mozilla[\s\S][\s\S]*lobo\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '131'
              +		},
              +		'164': {
              +			regexp: /^links \(([0-9a-z\.]+)[\s\S]*/i,
              +			browserId: '132'
              +		},
              +		'165': {
              +			regexp: /mozilla[\s\S]*PlayStation\ Portable[\s\S]*/i,
              +			browserId: '33'
              +		},
              +		'166': {
              +			regexp: /mozilla[\s\S]*MSIE [0-9a-z\+\-\.]+[\s\S]*Maxthon/i,
              +			browserId: '53'
              +		},
              +		'167': {
              +			regexp: /Netbox\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '57'
              +		},
              +		'169': {
              +			regexp: /^Mozilla\/(3\.0)[\s\S]*Sun\)$/i,
              +			browserId: '99'
              +		},
              +		'170': {
              +			regexp: /mozilla[\s\S]*rv:[0-9\.]+[\s\S]*gecko\/[0-9]+[\s\S]*fennec\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '133'
              +		},
              +		'171': {
              +			regexp: /mozilla[\s\S]*Lotus-Notes\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '134'
              +		},
              +		'172': {
              +			regexp: /^klondike\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '135'
              +		},
              +		'173': {
              +			regexp: /^WapTiger\/5[\s\S]0 \(http:\/\/www\.waptiger\.com\/[\s\S]*/i,
              +			browserId: '136'
              +		},
              +		'174': {
              +			regexp: /^W3C_Validator\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '137'
              +		},
              +		'175': {
              +			regexp: /^W3C-checklink\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '138'
              +		},
              +		'176': {
              +			regexp: /^HTMLParser\/([0-9a-z\.]+)$/i,
              +			browserId: '139'
              +		},
              +		'177': {
              +			regexp: /^LWP::Simple\/([0-9a-z\.]+)$/i,
              +			browserId: '122'
              +		},
              +		'178': {
              +			regexp: /^Java\/([0-9a-z\._]+)/i,
              +			browserId: '140'
              +		},
              +		'179': {
              +			regexp: /Bolt\/([0-9\.]+)/i,
              +			browserId: '141'
              +		},
              +		'180': {
              +			regexp: /Demeter\/([0-9\.]+)/i,
              +			browserId: '142'
              +		},
              +		'181': {
              +			regexp: /^UniversalFeedParser\/([0-9\.]+)/i,
              +			browserId: '143'
              +		},
              +		'182': {
              +			regexp: /mozilla[\s\S]*applewebkit[\s\S]*shiira[\s\S]*safari/i,
              +			browserId: '21'
              +		},
              +		'183': {
              +			regexp: /mozilla[\s\S]*firefox[\s\S]*orca\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '144'
              +		},
              +		'184': {
              +			regexp: /mozilla[\s\S]*applewebkit[\s\S]*fluid\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '145'
              +		},
              +		'185': {
              +			regexp: /Bookdog\/([0-9\.]+)/i,
              +			browserId: '146'
              +		},
              +		'186': {
              +			regexp: /http:\/\/Anonymouse[\s\S]org\/ \(Unix\)/i,
              +			browserId: '147'
              +		},
              +		'187': {
              +			regexp: /^Midori\/([0-9\.]+)/i,
              +			browserId: '148'
              +		},
              +		'188': {
              +			regexp: /boxee[\s\S]*\([\s\S]*\ ([0-9a-zA-Z\.]+)\)/i,
              +			browserId: '149'
              +		},
              +		'189': {
              +			regexp: /^gPodder\/([0-9\.]+)/i,
              +			browserId: '150'
              +		},
              +		'190': {
              +			regexp: /^Samsung-[a-zA-Z09]+[\s\S]*AU-MIC-[a-zA-Z0-9]+\/([0-9\.]+)/i,
              +			browserId: '151'
              +		},
              +		'191': {
              +			regexp: /^SonyEricsson[\s\S]*SEMC-Browser\/([0-9\.]+)/i,
              +			browserId: '152'
              +		},
              +		'192': {
              +			regexp: /NF-Browser\/([0-9\.]+)/i,
              +			browserId: '33'
              +		},
              +		'193': {
              +			regexp: /mozilla[\s\S]*rv:[0-9\.]+[\s\S]*gecko[\s\S]*GranParadiso\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '153'
              +		},
              +		'194': {
              +			regexp: /^WDG_Validator\/([0-9\.]+)/i,
              +			browserId: '154'
              +		},
              +		'195': {
              +			regexp: /^CSSCheck\/([0-9\.]+)/i,
              +			browserId: '155'
              +		},
              +		'196': {
              +			regexp: /^Page Valet\/([0-9a-z\.]+)/i,
              +			browserId: '156'
              +		},
              +		'197': {
              +			regexp: /IEMobile ([0-9\.]+)/i,
              +			browserId: '157'
              +		},
              +		'198': {
              +			regexp: /mozilla[\s\S]*Lunascape ([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '52'
              +		},
              +		'199': {
              +			regexp: /BlackBerry/i,
              +			browserId: '158'
              +		},
              +		'200': {
              +			regexp: /Obigo[\s\S]*Profile\/MIDP/i,
              +			browserId: '151'
              +		},
              +		'201': {
              +			regexp: /Browser\/Teleca|Teleca\/[\s\S]*MIDP/i,
              +			browserId: '151'
              +		},
              +		'202': {
              +			regexp: /Polaris\/([0-9\.]+)/i,
              +			browserId: '159'
              +		},
              +		'203': {
              +			regexp: /Hv3\/([0-9a-z\.])/i,
              +			browserId: '160'
              +		},
              +		'204': {
              +			regexp: /^WinWAP\/([0-9\.]+)/i,
              +			browserId: '161'
              +		},
              +		'205': {
              +			regexp: /^XBMC\/([0-9a-z\.\-]+)/i,
              +			browserId: '162'
              +		},
              +		'206': {
              +			regexp: /^XML-RPC for PHP ([0-9a-z\.]+)$/i,
              +			browserId: '163'
              +		},
              +		'207': {
              +			regexp: /^OmniWeb\/([0-9a-z\.\-]+)/i,
              +			browserId: '18'
              +		},
              +		'208': {
              +			regexp: /^FlyCast\/([0-9\.]+)/i,
              +			browserId: '165'
              +		},
              +		'209': {
              +			regexp: /^Bloglines\/([0-9\.]+)/i,
              +			browserId: '166'
              +		},
              +		'210': {
              +			regexp: /^Gregarius\/([0-9\.]+)/i,
              +			browserId: '167'
              +		},
              +		'211': {
              +			regexp: /^SimplePie\/([0-9a-z\. ]+)/i,
              +			browserId: '168'
              +		},
              +		'212': {
              +			regexp: /^PycURL\/([0-9\.]+)$/i,
              +			browserId: '169'
              +		},
              +		'213': {
              +			regexp: /^Apple-PubSub\/([0-9\.]+)$/i,
              +			browserId: '170'
              +		},
              +		'214': {
              +			regexp: /^Feedfetcher-Google[\s\S]*http:\/\/www\.google\.com\/feedfetcher\.html/i,
              +			browserId: '171'
              +		},
              +		'215': {
              +			regexp: /^FeedValidator\/([0-9\.]+)$/i,
              +			browserId: '172'
              +		},
              +		'216': {
              +			regexp: /^MagpieRSS\/([0-9\.]+)/i,
              +			browserId: '173'
              +		},
              +		'217': {
              +			regexp: /^BlogBridge ([0-9\.]+)/i,
              +			browserId: '174'
              +		},
              +		'218': {
              +			regexp: /Miro\/([0-9a-z\-\.]+)[\s\S]*http:\/\/www\.getmiro\.com\//i,
              +			browserId: '175'
              +		},
              +		'219': {
              +			regexp: /^Liferea\/([0-9\.]+)[\s\S]*http:\/\/liferea\.sf\.net\//i,
              +			browserId: '176'
              +		},
              +		'220': {
              +			regexp: /^HomePage Rss Reader ([0-9\.]+)/i,
              +			browserId: '177'
              +		},
              +		'221': {
              +			regexp: /^PHP\/([0-9a-z\.\-]+)$/i,
              +			browserId: '178'
              +		},
              +		'222': {
              +			regexp: /^REL Link Checker Lite ([0-9\.]+)$/i,
              +			browserId: '179'
              +		},
              +		'223': {
              +			regexp: /^CPG RSS Module File Reader/i,
              +			browserId: '180'
              +		},
              +		'224': {
              +			regexp: /^Dragonfly File Reader/i,
              +			browserId: '180'
              +		},
              +		'225': {
              +			regexp: /^CPG Dragonfly RSS Module Feed Viewer/i,
              +			browserId: '180'
              +		},
              +		'226': {
              +			regexp: /^newsbeuter\/([0-9\.]+)/i,
              +			browserId: '181'
              +		},
              +		'227': {
              +			regexp: /^Jigsaw\/[0-9\.]+ W3C_CSS_Validator_JFouffa\/([0-9\.]+)$/i,
              +			browserId: '182'
              +		},
              +		'228': {
              +			regexp: /^FPLinkChecker\/([0-9\.]+)$/i,
              +			browserId: '183'
              +		},
              +		'229': {
              +			regexp: /^GoldenPod ([0-9\.]+)/i,
              +			browserId: '184'
              +		},
              +		'230': {
              +			regexp: /Cheshire\/([0-9a-z\.]+)/i,
              +			browserId: '185'
              +		},
              +		'231': {
              +			regexp: /mozilla[\s\S]*rv:[0-9\.]+[\s\S]*gecko\/[0-9]+[\s\S]*chimera\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '1'
              +		},
              +		'232': {
              +			regexp: /mozilla[\s\S]*rv:[0-9\.]+[\s\S]*gecko[\s\S]*CometBird\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '187'
              +		},
              +		'233': {
              +			regexp: /mozilla[\s\S]*rv:[0-9\.]+[\s\S]*gecko[\s\S]*IceCat\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '188'
              +		},
              +		'234': {
              +			regexp: /mozilla[\s\S]*applewebkit[\s\S]*Stainless\/([0-9a-z\+\-\.]+)[\s\S]*safari/i,
              +			browserId: '189'
              +		},
              +		'235': {
              +			regexp: /mozilla[\s\S]*rv:[0-9\.]+[\s\S]*gecko[\s\S]*Prism\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '190'
              +		},
              +		'236': {
              +			regexp: /^curl\/([0-9a-zA-Z\.\-]+)/i,
              +			browserId: '86'
              +		},
              +		'237': {
              +			regexp: /^MPlayer\//i,
              +			browserId: '191'
              +		},
              +		'238': {
              +			regexp: /^Mozilla\/4\.0[\s\S]*Win32[\s\S]*ActiveXperts\.Http\.([0-9\.]+)/i,
              +			browserId: '192'
              +		},
              +		'239': {
              +			regexp: /^MOT[\s\S]*MIB\/([0-9\.]+)/i,
              +			browserId: '193'
              +		},
              +		'240': {
              +			regexp: /^Abilon$/i,
              +			browserId: '194'
              +		},
              +		'241': {
              +			regexp: /^check_http\/([0-9a-z\.]+) \(nagios\-plugins/i,
              +			browserId: '195'
              +		},
              +		'242': {
              +			regexp: /^Windows\-Media\-Player\/([0-9\.]+)$/i,
              +			browserId: '196'
              +		},
              +		'243': {
              +			regexp: /^VLC media player \- version ([0-9a-z\-\.]+) [\s\S]* VideoLAN team$/i,
              +			browserId: '197'
              +		},
              +		'244': {
              +			regexp: /^P3P Validator$/i,
              +			browserId: '198'
              +		},
              +		'245': {
              +			regexp: /^CSE HTML Validator Lite Online/i,
              +			browserId: '199'
              +		},
              +		'246': {
              +			regexp: /mozilla[\s\S]*rv:[0-9\.]+[\s\S]*gecko[\s\S]*Navigator\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '4'
              +		},
              +		'247': {
              +			regexp: /^JetBrains Omea Reader ([0-9\.]+)/i,
              +			browserId: '200'
              +		},
              +		'248': {
              +			regexp: /^GSiteCrawler\/([0-9a-z\.]+)/i,
              +			browserId: '201'
              +		},
              +		'249': {
              +			regexp: /^YahooFeedSeeker\/([0-9\.]+)/i,
              +			browserId: '202'
              +		},
              +		'250': {
              +			regexp: /^Democracy\/([0-9\.]+)/i,
              +			browserId: '175'
              +		},
              +		'251': {
              +			regexp: /^Java([0-9\._]+)$/i,
              +			browserId: '140'
              +		},
              +		'253': {
              +			regexp: /^mozilla\/[\s\S]*MSIE [0-9\.]+[\s\S]*TheWorld/i,
              +			browserId: '204'
              +		},
              +		'254': {
              +			regexp: /^webcollage\/([0-9\.]+)$/i,
              +			browserId: '205'
              +		},
              +		'255': {
              +			regexp: /^webcollage\-noporn\/([0-9\.]+)$/i,
              +			browserId: '205'
              +		},
              +		'256': {
              +			regexp: /^webcollage\.[a-z]+\/([0-9\.]+)$/i,
              +			browserId: '205'
              +		},
              +		'257': {
              +			regexp: /^webcollage1\/([0-9\.]+)$/i,
              +			browserId: '205'
              +		},
              +		'258': {
              +			regexp: /^NewsGatorOnline\/([0-9\.]+) \(http:\/\/www\.newsgator\.com/i,
              +			browserId: '206'
              +		},
              +		'259': {
              +			regexp: /^Mozilla[\s\S]*PRTG Network Monitor/i,
              +			browserId: '207'
              +		},
              +		'260': {
              +			regexp: /^Web Downloader\/([0-9\.]+)$/i,
              +			browserId: '39'
              +		},
              +		'261': {
              +			regexp: /^Opera\/[0-9\.]+[\s\S]*Presto\/[0-9\.]+ Version\/([0-9\.]+)$/i,
              +			browserId: '17'
              +		},
              +		'262': {
              +			regexp: /mozilla[\s\S]*rv:[0-9\.]+[\s\S]*gecko[\s\S]*Songbird\/([0-9\.]+)/i,
              +			browserId: '208'
              +		},
              +		'263': {
              +			regexp: /^Avant Browser/i,
              +			browserId: '41'
              +		},
              +		'264': {
              +			regexp: /^RSS_Radio ([0-9\.]+)$/i,
              +			browserId: '209'
              +		},
              +		'265': {
              +			regexp: /^Feed::Find\/([0-9\.]+)$/i,
              +			browserId: '210'
              +		},
              +		'266': {
              +			regexp: /^Mozilla\/[\s\S]*webOS\/[0-9\.]+[\s\S]*AppleWebKit[\s\S]*Pre\/([0-9\.]+)$/i,
              +			browserId: '211'
              +		},
              +		'267': {
              +			regexp: /mozilla[\s\S]*rv:[0-9\.]+[\s\S]*gecko[\s\S]*BonEcho\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '212'
              +		},
              +		'268': {
              +			regexp: /^QuickTime\/([0-9\.]+)/,
              +			browserId: '213'
              +		},
              +		'269': {
              +			regexp: /^QuickTime[\s\S]*qtver=([0-9\.a-z]+)/i,
              +			browserId: '213'
              +		},
              +		'270': {
              +			regexp: /^PHPCrawl$/i,
              +			browserId: '214'
              +		},
              +		'271': {
              +			regexp: /mozilla[\s\S]*Linux armv7l[\s\S]*rv:[0-9\.]+[\s\S]*gecko\/[0-9]+[\s\S]*Tablet browser ([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '260'
              +		},
              +		'272': {
              +			regexp: /mozilla[\s\S]*MSIE [0-9a-z\+\-\.]+[\s\S]*GreenBrowser/i,
              +			browserId: '216'
              +		},
              +		'273': {
              +			regexp: /^Awasu\/([0-9a-z\.]+)$/i,
              +			browserId: '217'
              +		},
              +		'274': {
              +			regexp: /^CorePlayer[\s\S]*CorePlayer\/([0-9\._]+)$/i,
              +			browserId: '218'
              +		},
              +		'275': {
              +			regexp: /^Mozilla\/[\s\S]*AppleWebKit[\s\S]*QtWeb Internet Browser\/([0-9\.]+)/i,
              +			browserId: '219'
              +		},
              +		'276': {
              +			regexp: /^Mozilla\/[\s\S]*AppleWebKit[\s\S]*TeaShark\/([0-9\.]+)$/i,
              +			browserId: '220'
              +		},
              +		'277': {
              +			regexp: /^libsoup\/([0-9a-z\.]+)$/i,
              +			browserId: '221'
              +		},
              +		'278': {
              +			regexp: /^Mozilla\/[\s\S]*AppleWebKit[\s\S]*NetNewsWire\/([0-9a-z\.]+)$/i,
              +			browserId: '222'
              +		},
              +		'279': {
              +			regexp: /^NetNewsWire\/([0-9a-z\.]+)[\s\S]*http:\/\/www\.newsgator\.com\/Individuals\/NetNews/i,
              +			browserId: '222'
              +		},
              +		'280': {
              +			regexp: /http:\/\/code\.google\.com\/appengine/i,
              +			browserId: '223'
              +		},
              +		'281': {
              +			regexp: /UCWEB/i,
              +			browserId: '225'
              +		},
              +		'287': {
              +			regexp: /NokiaN93/i,
              +			browserId: '226'
              +		},
              +		'289': {
              +			regexp: /Nokia[\s\S]*SymbianOS[\s\S]*Series60/i,
              +			browserId: '226'
              +		},
              +		'292': {
              +			regexp: /SymbianOS[\s\S]*Series60[\s\S]*Nokia[\s\S]*AppleWebKit/i,
              +			browserId: '226'
              +		},
              +		'293': {
              +			regexp: /^lftp\/([0-9a-z\.]+)$/,
              +			browserId: '227'
              +		},
              +		'294': {
              +			regexp: /^WinWAP-SPBE\/([0-9\.]+)/i,
              +			browserId: '161'
              +		},
              +		'295': {
              +			regexp: /^Mozilla[\s\S]*RISC[\s\S]*Oregano ([0-9\.]+)/i,
              +			browserId: '228'
              +		},
              +		'296': {
              +			regexp: /^libsummer\/([0-9\.]+)/i,
              +			browserId: '229'
              +		},
              +		'297': {
              +			regexp: /mozilla[\s\S]*MSIE [0-9a-z\+\-\.]+[\s\S]*Acoo Browser/i,
              +			browserId: '230'
              +		},
              +		'298': {
              +			regexp: /^Mozilla[\s\S]*NewsFox\/([0-9\.]+)/i,
              +			browserId: '231'
              +		},
              +		'299': {
              +			regexp: /^Mozilla[\s\S]*Danger hiptop/i,
              +			browserId: '33'
              +		},
              +		'300': {
              +			regexp: /Mozilla[\s\S]*MSIE[\s\S]*Hydra Browser/i,
              +			browserId: '232'
              +		},
              +		'301': {
              +			regexp: /^Mozilla[\s\S]*AppleWebKit[\s\S]*wKiosk/i,
              +			browserId: '233'
              +		},
              +		'302': {
              +			regexp: /Mozilla\/[\s\S]*AppleWebKit[\s\S]*Paparazzi!\/([0-9a-z\.]+)/i,
              +			browserId: '234'
              +		},
              +		'303': {
              +			regexp: /^xine\/([0-9a-z\.]+)/i,
              +			browserId: '235'
              +		},
              +		'304': {
              +			regexp: /^webfs\/([0-9\.]+) \(plan 9\)$/i,
              +			browserId: '236'
              +		},
              +		'305': {
              +			regexp: /^Ilium Software NewsBreak/i,
              +			browserId: '237'
              +		},
              +		'306': {
              +			regexp: /^LinkbackPlugin\/([0-9a-z\.]+) Laconica\//i,
              +			browserId: '238'
              +		},
              +		'307': {
              +			regexp: /^Microsoft Data Access Internet Publishing Provider DAV/i,
              +			browserId: '239'
              +		},
              +		'308': {
              +			regexp: /^gvfs\/([0-9a-z\.]+)/i,
              +			browserId: '240'
              +		},
              +		'309': {
              +			regexp: /^Webkit\/[\s\S]*Uzbl/i,
              +			browserId: '241'
              +		},
              +		'310': {
              +			regexp: /^Uzbl[\s\S]*Webkit/i,
              +			browserId: '241'
              +		},
              +		'311': {
              +			regexp: /^Cynthia ([0-9\.]+)$/i,
              +			browserId: '242'
              +		},
              +		'312': {
              +			regexp: /^Mozilla\/5\.0 \(Sage\)$/i,
              +			browserId: '243'
              +		},
              +		'313': {
              +			regexp: /^Banshee ([0-9a-z\.]+)[\s\S]*http:\/\/banshee-project\.org/i,
              +			browserId: '244'
              +		},
              +		'314': {
              +			regexp: /^Mozilla\/[\s\S]*Gecko[\s\S]* Firefox[\s\S]*Wyzo\/([0-9a-z\.]+)/i,
              +			browserId: '245'
              +		},
              +		'315': {
              +			regexp: /^RSSOwl\/([0-9]\.[0-9]\.[0-9])/i,
              +			browserId: '246'
              +		},
              +		'316': {
              +			regexp: /^Mozilla\/[\s\S]*ABrowse ([0-9\.]+)[\s\S]*Syllable/i,
              +			browserId: '247'
              +		},
              +		'317': {
              +			regexp: /^Funambol Outlook Plug-in[\s\S]*([0-9\.]+)$/i,
              +			browserId: '248'
              +		},
              +		'318': {
              +			regexp: /^Funambol Mozilla Sync Client v([0-9\.]+)$/i,
              +			browserId: '249'
              +		},
              +		'319': {
              +			regexp: /^RSS Menu\/([0-9\.]+)/i,
              +			browserId: '250'
              +		},
              +		'320': {
              +			regexp: /^foobar2000\/([0-9a-z\._]+$)/i,
              +			browserId: '251'
              +		},
              +		'321': {
              +			regexp: /^GStreamer souphttpsrc libsoup\/[0-9\.]+$/i,
              +			browserId: '252'
              +		},
              +		'322': {
              +			regexp: /^Mozilla\/[\s\S]*Mobile Content Viewer\/([0-9\.]+)[\s\S]*NetFront/i,
              +			browserId: '253'
              +		},
              +		'323': {
              +			regexp: /^php-openid\/([0-9\.]+)/i,
              +			browserId: '254'
              +		},
              +		'324': {
              +			regexp: /NCSA Mosaic\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '117'
              +		},
              +		'325': {
              +			regexp: /mozilla[\s\S]*rv:[0-9\.]+[\s\S]*gecko[\s\S]*Blackbird\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '255'
              +		},
              +		'326': {
              +			regexp: /^Mozilla\/4[\s\S]0 \(compatible; MSIE ([0-9\.]+); Windows/i,
              +			browserId: '35'
              +		},
              +		'327': {
              +			regexp: /ICE browser\/([0-9a-z_\.\-]+)/i,
              +			browserId: '94'
              +		},
              +		'328': {
              +			regexp: /^GreatNews\/([0-9\.]+)$/i,
              +			browserId: '256'
              +		},
              +		'329': {
              +			regexp: /mozilla[\s\S]*applewebkit[\s\S]*DeskBrowse\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '257'
              +		},
              +		'330': {
              +			regexp: /^TulipChain\/([0-9\.]+)[\s\S]*ostermiller[\s\S]org\/tulipchain[\s\S]*Java/i,
              +			browserId: '258'
              +		},
              +		'331': {
              +			regexp: /^Mozilla\/[\s\S]*AppleWebKit\/[\s\S]*Maxthon\/([0-9\.]+)/i,
              +			browserId: '53'
              +		},
              +		'332': {
              +			regexp: /^Axel ([0-9\.]+)/i,
              +			browserId: '259'
              +		},
              +		'333': {
              +			regexp: /^Mozilla\/[\s\S]*Linux[\s\S]*AppleWebKit[\s\S]*tear/i,
              +			browserId: '261'
              +		},
              +		'334': {
              +			regexp: /^LinkExaminer\/([0-9\.]+) \(Windows\)$/i,
              +			browserId: '262'
              +		},
              +		'335': {
              +			regexp: /^Mozilla\/[\s\S]*MSIE[\s\S]*http:\/\/www\.Abolimba\.de/i,
              +			browserId: '263'
              +		},
              +		'336': {
              +			regexp: /^Mozilla\/[\s\S]*Gecko\/[\s\S]*Beonex\/([0-9a-z\.\-]+)/i,
              +			browserId: '264'
              +		},
              +		'337': {
              +			regexp: /^DocZilla\/([0-9\.]+)[\s\S]*Gecko\//i,
              +			browserId: '265'
              +		},
              +		'338': {
              +			regexp: /^retawq\/([0-9a-z\.]+)[\s\S]*\(text\)$/i,
              +			browserId: '266'
              +		},
              +		'339': {
              +			regexp: /^SAMSUNG[\s\S]*Jasmine\/([0-9\.]+)/i,
              +			browserId: '267'
              +		},
              +		'340': {
              +			regexp: /Opera\/[\s\S]*Opera Mini\/([0-9\.]+)/i,
              +			browserId: '268'
              +		},
              +		'341': {
              +			regexp: /Mozilla\/[\s\S]*AppleWebKit[\s\S]*Dooble/i,
              +			browserId: '269'
              +		},
              +		'342': {
              +			regexp: /Mozilla\/[\s\S]*Gecko[\s\S]*Firefox[\s\S]*Madfox\/([0-9a-z\.]+)/i,
              +			browserId: '270'
              +		},
              +		'343': {
              +			regexp: /^DownloadStudio\/([0-9\.]+)$/i,
              +			browserId: '271'
              +		},
              +		'344': {
              +			regexp: /^WinPodder[\s\S]*http:\/\/winpodder\.com/i,
              +			browserId: '272'
              +		},
              +		'345': {
              +			regexp: /^Bunjalloo\/([0-9\.]+)[\s\S]*Nintendo/i,
              +			browserId: '273'
              +		},
              +		'346': {
              +			regexp: /^LinkChecker\/([0-9\.]+)[\s\S]*linkchecker\.sourceforge\.net/i,
              +			browserId: '274'
              +		},
              +		'348': {
              +			regexp: /urlgrabber\/([0-9\.]+)/i,
              +			browserId: '276'
              +		},
              +		'349': {
              +			regexp: /mozilla[\s\S]*rv:[0-9\.]+[\s\S]*gecko[\s\S]*Spicebird\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '277'
              +		},
              +		'350': {
              +			regexp: /[\s\S]*Obigo Browser ([0-9\.]+)/i,
              +			browserId: '151'
              +		},
              +		'351': {
              +			regexp: /ObigoInternetBrowser/i,
              +			browserId: '151'
              +		},
              +		'352': {
              +			regexp: /mozilla[\s\S]*rv:[0-9\.]+[\s\S]*gecko\/[0-9]+[\s\S]*Namoroka\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '278'
              +		},
              +		'353': {
              +			regexp: /mozilla[\s\S]*applewebkit[\s\S]*rekonq[\/]{0,1}([0-9a-z\.]+){0,1}[\s\S]*/i,
              +			browserId: '279'
              +		},
              +		'354': {
              +			regexp: /^W3C_Multipage_Validator\/([0-9a-z\.]+)[\s\S]*http:\/\/www\.validator\.ca\//i,
              +			browserId: '280'
              +		},
              +		'355': {
              +			regexp: /^X\-Smiles\/([0-9a-z\.]+)/i,
              +			browserId: '281'
              +		},
              +		'356': {
              +			regexp: /WinHttp/i,
              +			browserId: '282'
              +		},
              +		'357': {
              +			regexp: /^Xaldon_WebSpider\/([0-9a-z\.]+)/i,
              +			browserId: '283'
              +		},
              +		'358': {
              +			regexp: /^Xaldon WebSpider ([0-9a-z\.]+)/i,
              +			browserId: '283'
              +		},
              +		'359': {
              +			regexp: /\/szn-mobile-transcoder/i,
              +			browserId: '284'
              +		},
              +		'360': {
              +			regexp: /^SZN-Image-Resizer$/i,
              +			browserId: '284'
              +		},
              +		'361': {
              +			regexp: /Google Wireless Transcoder/i,
              +			browserId: '285'
              +		},
              +		'362': {
              +			regexp: /^Google-Listen\/([0-9a-z\.]+)/i,
              +			browserId: '286'
              +		},
              +		'363': {
              +			regexp: /^Typhoeus[\s\S]*http:\/\/github[\s\S]com\/pauldix\/typhoeus/i,
              +			browserId: '287'
              +		},
              +		'364': {
              +			regexp: /^Mozilla\/[\s\S]*Origyn Web Browser/i,
              +			browserId: '288'
              +		},
              +		'365': {
              +			regexp: /mozilla[\s\S]*MSIE [0-9a-z\+\-\.]+[\s\S]*Browzar/i,
              +			browserId: '289'
              +		},
              +		'366': {
              +			regexp: /^Claws Mail GtkHtml2 plugin ([0-9a-z\.]+)[\s\S]*http:\/\/www[\s\S]claws-mail[\s\S]org\/plugins[\s\S]php/i,
              +			browserId: '290'
              +		},
              +		'367': {
              +			regexp: /Python\-urllib$/i,
              +			browserId: '90'
              +		},
              +		'368': {
              +			regexp: /^Azureus ([0-9a-z\.]+)/i,
              +			browserId: '291'
              +		},
              +		'369': {
              +			regexp: /mozilla[\s\S]*rv:[0-9\.]+[\s\S]*gecko[\s\S]*GlobalMojo\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '292'
              +		},
              +		'370': {
              +			regexp: /^GomPlayer ([0-9, ]+)/i,
              +			browserId: '293'
              +		},
              +		'371': {
              +			regexp: /^Python-webchecker\/([0-9]+)$/i,
              +			browserId: '294'
              +		},
              +		'372': {
              +			regexp: /^W3C-mobileOK\/DDC-([0-9\.]+)[\s\S]* http:\/\/www[\s\S]w3[\s\S]org\/2006\/07\/mobileok-ddc/i,
              +			browserId: '296'
              +		},
              +		'373': {
              +			regexp: /^JoeDog\/[\s\S]*Siege ([0-9\.]+)/i,
              +			browserId: '297'
              +		},
              +		'374': {
              +			regexp: /^iSiloXC\/([0-9\.]+)/i,
              +			browserId: '298'
              +		},
              +		'375': {
              +			regexp: /^ApacheBench\/([0-9a-z\-\.]+)$/i,
              +			browserId: '299'
              +		},
              +		'376': {
              +			regexp: /^anw webtool LoadControl\/([0-9\.]+)$/i,
              +			browserId: '300'
              +		},
              +		'377': {
              +			regexp: /^topSUBMIT[\s\S]de HTMLChecker\/([0-9\.]+)$/i,
              +			browserId: '301'
              +		},
              +		'378': {
              +			regexp: /^edbrowse\/([0-9\.\-]+)/i,
              +			browserId: '302'
              +		},
              +		'379': {
              +			regexp: /^muCommander v([0-9\.]+)/i,
              +			browserId: '303'
              +		},
              +		'380': {
              +			regexp: /^muCommander-file-API/i,
              +			browserId: '303'
              +		},
              +		'381': {
              +			regexp: /^XMPlay\/([0-9\.]+)$/i,
              +			browserId: '304'
              +		},
              +		'382': {
              +			regexp: /^NFReader\/([0-9\.]+)/i,
              +			browserId: '305'
              +		},
              +		'383': {
              +			regexp: /^Mozilla\/[\s\S]*uZardWeb\/([0-9\.]+)/i,
              +			browserId: '306'
              +		},
              +		'384': {
              +			regexp: /^Mozilla\/3[\s\S]0 \(compatible; Indy Library\)$/i,
              +			browserId: '307'
              +		},
              +		'385': {
              +			regexp: /^Mozilla\/[\s\S]*MSIE[\s\S]*Multi\-Browser ([0-9\.]+)[\s\S]*www\.multibrowser\.de/i,
              +			browserId: '308'
              +		},
              +		'386': {
              +			regexp: /^LinkWalker\/([0-9\.]+)[\s\S]*www\.seventwentyfour\.com/i,
              +			browserId: '309'
              +		},
              +		'387': {
              +			regexp: /^Mozilla[\s\S]*compatible[\s\S]*NetPositive\/([0-9\.]+)/i,
              +			browserId: '310'
              +		},
              +		'388': {
              +			regexp: /^Radio Downloader ([0-9\.]+)$/i,
              +			browserId: '311'
              +		},
              +		'389': {
              +			regexp: /^WebStripper\/([0-9\.]+)/i,
              +			browserId: '312'
              +		},
              +		'390': {
              +			regexp: /^Cyberduck\/([0-9\.]+)/i,
              +			browserId: '313'
              +		},
              +		'391': {
              +			regexp: /^WorldWideweb \(NEXT\)$/i,
              +			browserId: '314'
              +		},
              +		'392': {
              +			regexp: /^iVideo ([a-z0-9\.\ ]+)[\s\S]*iPhone OS/i,
              +			browserId: '315'
              +		},
              +		'393': {
              +			regexp: /^Mozilla\/4[\s\S]0 \(compatible; RSS Popper\)$/i,
              +			browserId: '316'
              +		},
              +		'394': {
              +			regexp: /^Win[\s\S]*Jamcast\/([0-9\.]+)/i,
              +			browserId: '317'
              +		},
              +		'395': {
              +			regexp: /^Jamcast ([0-9\.]+)$/i,
              +			browserId: '317'
              +		},
              +		'396': {
              +			regexp: /mozilla[\s\S]*Comodo_Dragon\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '318'
              +		},
              +		'397': {
              +			regexp: /Mozilla\/4[\s\S]*OS\/2/i,
              +			browserId: '4'
              +		},
              +		'398': {
              +			regexp: /^SuperBot\/([0-9\.]+)/i,
              +			browserId: '319'
              +		},
              +		'399': {
              +			regexp: /^MyIBrow\/([0-9\.]+)[\s\S]*Windows/i,
              +			browserId: '320'
              +		},
              +		'400': {
              +			regexp: /Opera mobi[\s\S]*Version\/([0-9\.]+)/i,
              +			browserId: '321'
              +		},
              +		'401': {
              +			regexp: /Opera Mobi[\s\S]*Opera ([0-9\.]+)/i,
              +			browserId: '321'
              +		},
              +		'402': {
              +			regexp: /Opera ([0-9\.]+)[\s\S]*Opera Mobi/i,
              +			browserId: '321'
              +		},
              +		'403': {
              +			regexp: /^Mozilla[\s\S]*Gecko[\s\S]*Strata\/([0-9\.]+)/i,
              +			browserId: '322'
              +		},
              +		'404': {
              +			regexp: /^Mozilla[\s\S]*MSIE[\s\S]*TencentTraveler/i,
              +			browserId: '323'
              +		},
              +		'405': {
              +			regexp: /^Mozilla[\s\S]*MSIE[\s\S]*TencentTraveler ([0-9\.]+)/i,
              +			browserId: '323'
              +		},
              +		'406': {
              +			regexp: /^Mozilla[\s\S]*rv:[0-9\.]+[\s\S]*Gecko[\s\S]*Firefox[\s\S]*LBrowser\/([0-9a-z\-\.]+)/i,
              +			browserId: '324'
              +		},
              +		'407': {
              +			regexp: /^Mozilla[\s\S]*MSIE[\s\S]*MSOffice 12/i,
              +			browserId: '325'
              +		},
              +		'408': {
              +			regexp: /^Mozilla[\s\S]*MSIE[\s\S]*MSOffice 14/i,
              +			browserId: '326'
              +		},
              +		'409': {
              +			regexp: /^Outlook-Express\/7\.0 \(MSIE 7\.0[\s\S]*Windows/i,
              +			browserId: '327'
              +		},
              +		'410': {
              +			regexp: /^Mozilla[\s\S]*MSIE[\s\S]*Windows[\s\S]*Tjusig ([0-9\.]+)/i,
              +			browserId: '328'
              +		},
              +		'411': {
              +			regexp: /^Mozilla[\s\S]*MSIE[\s\S]*Windows[\s\S]*SiteKiosk ([0-9\.]+)/,
              +			browserId: '329'
              +		},
              +		'412': {
              +			regexp: /^The Bat! ([0-9\.]+)$/i,
              +			browserId: '330'
              +		},
              +		'413': {
              +			regexp: /^Mozilla[\s\S]*compatible[\s\S]*BorderManager ([0-9\.]+)/i,
              +			browserId: '331'
              +		},
              +		'414': {
              +			regexp: /^Mozilla[\s\S]*Shredder\/([0-9a-zA-Z\.]+)/i,
              +			browserId: '332'
              +		},
              +		'415': {
              +			regexp: /^PublicRadioPlayer\/([0-9\.]+)/i,
              +			browserId: '333'
              +		},
              +		'416': {
              +			regexp: /^PublicRadioApp\/([0-9\.]+)/i,
              +			browserId: '333'
              +		},
              +		'417': {
              +			regexp: /PLAYSTATION 3/i,
              +			browserId: '33'
              +		},
              +		'418': {
              +			regexp: /^RssBandit\/([0-9\.]+)/i,
              +			browserId: '334'
              +		},
              +		'419': {
              +			regexp: /^Microsoft Office\/14[\s\S]*MSOffice 14/i,
              +			browserId: '326'
              +		},
              +		'420': {
              +			regexp: /^Mozilla[\s\S]*Postbox\/([0-9a-zA-Z\.]+)/i,
              +			browserId: '335'
              +		},
              +		'421': {
              +			regexp: /^Postbox ([0-9a-z\.]+)/i,
              +			browserId: '335'
              +		},
              +		'422': {
              +			regexp: /^2Bone_LinkChecker\/([0-9\.]+)/i,
              +			browserId: '336'
              +		},
              +		'423': {
              +			regexp: /^Checkbot\/([0-9\.]+)/i,
              +			browserId: '337'
              +		},
              +		'424': {
              +			regexp: /^GcMail Browser\/([0-9\.]+)/i,
              +			browserId: '338'
              +		},
              +		'425': {
              +			regexp: /mozilla[\s\S]*rv:[0-9\.]+[\s\S]*gecko[\s\S]*Swiftweasel\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '339'
              +		},
              +		'426': {
              +			regexp: /^Fastladder FeedFetcher\/([0-9\.]+)[\s\S]*fastladder[\s\S]com/i,
              +			browserId: '340'
              +		},
              +		'427': {
              +			regexp: /mozilla[\s\S]*rv:[0-9\.]+[\s\S]*gecko[\s\S]*Lorentz\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '341'
              +		},
              +		'428': {
              +			regexp: /^PocketTunes\/([0-9a-z\.]+)$/i,
              +			browserId: '342'
              +		},
              +		'429': {
              +			regexp: /^SharpReader\/([0-9\.]+)/i,
              +			browserId: '343'
              +		},
              +		'430': {
              +			regexp: /^YeahReader/i,
              +			browserId: '344'
              +		},
              +		'431': {
              +			regexp: /mozilla[\s\S]*rv:[0-9\.]+[\s\S]*gecko[\s\S]*Palemoon\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '345'
              +		},
              +		'432': {
              +			regexp: /^holmes\/([0-9\.]+)/i,
              +			browserId: '346'
              +		},
              +		'433': {
              +			regexp: /^mozilla[\s\S]*AppleWebKit[\s\S]*Google Earth\/([0-9\.]+)/i,
              +			browserId: '347'
              +		},
              +		'434': {
              +			regexp: /mozilla[\s\S]*flock\/([0-9\.]+)[\s\S]*chrome/i,
              +			browserId: '7'
              +		},
              +		'435': {
              +			regexp: /^Rome Client \(http:\/\/tinyurl\.com\/64t5n\) Ver: ([0-9\.]+)/i,
              +			browserId: '348'
              +		},
              +		'436': {
              +			regexp: /mozilla[\s\S]*rv:[0-9\.]+[\s\S]*gecko[\s\S]*myibrow\/([0-9a-z\.]+)/i,
              +			browserId: '320'
              +		},
              +		'437': {
              +			regexp: /^Akregator\/([0-9\.]+)[\s\S]*librss\/remnants/i,
              +			browserId: '349'
              +		},
              +		'438': {
              +			regexp: /HTC[\s\S]*Opera\/([0-9\.]+)[\s\S]*Windows/i,
              +			browserId: '321'
              +		},
              +		'439': {
              +			regexp: /^Mozilla[\s\S]*Windows[\s\S]*AppleWebKit[\s\S]*MiniBrowser\/([0-9\.]+)/i,
              +			browserId: '350'
              +		},
              +		'440': {
              +			regexp: /^Mozilla[\s\S]*Escape ([0-9\.]+)/i,
              +			browserId: '351'
              +		},
              +		'441': {
              +			regexp: /^Mozilla[\s\S]*Windows[\s\S]*UltraBrowser ([0-9\.]+)/i,
              +			browserId: '352'
              +		},
              +		'442': {
              +			regexp: /^Mozilla[\s\S]*BrowseX \(([0-9\.]+)/i,
              +			browserId: '353'
              +		},
              +		'443': {
              +			regexp: /Mozilla[\s\S]*Linux[\s\S]*Android[\s\S]*AppleWebKit[\s\S]*Version\/([0-9\.]+)/i,
              +			browserId: '354'
              +		},
              +		'444': {
              +			regexp: /Mozilla[\s\S]*AppleWebKit[\s\S]*WeltweitimnetzBrowser\/([0-9\.]+)/i,
              +			browserId: '355'
              +		},
              +		'445': {
              +			regexp: /^Pocomail\/([0-9\.]+)/i,
              +			browserId: '356'
              +		},
              +		'446': {
              +			regexp: /^Mozilla[\s\S]*AppleWebKit[\s\S]*Element Browser ([0-9\.]+)/i,
              +			browserId: '357'
              +		},
              +		'447': {
              +			regexp: /^Mozilla[\s\S]*MSIE[\s\S]*SlimBrowser/i,
              +			browserId: '358'
              +		},
              +		'448': {
              +			regexp: /^LeechCraft/i,
              +			browserId: '359'
              +		},
              +		'449': {
              +			regexp: /^LeechCraft[\s\S]*LeechCraft\/Poshuku ([0-9a-z\-\.]+)/i,
              +			browserId: '359'
              +		},
              +		'450': {
              +			regexp: /^HTTP_Request2\/([0-9\.]+)/i,
              +			browserId: '360'
              +		},
              +		'451': {
              +			regexp: /^Mozilla[\s\S]*Gecko[\s\S]*Conkeror\/([0-9\.]+)/i,
              +			browserId: '361'
              +		},
              +		'452': {
              +			regexp: /^Mozilla[\s\S]*Dolfin\/([0-9\.]+)/i,
              +			browserId: '362'
              +		},
              +		'453': {
              +			regexp: /^SAMSUNG[\s\S]*Dolfin\/([0-9\.]+)/i,
              +			browserId: '362'
              +		},
              +		'455': {
              +			regexp: /^Netvibes[\s\S]*http:\/\/www\.netvibes\.com/i,
              +			browserId: '363'
              +		},
              +		'456': {
              +			regexp: /^Chilkat\/([0-9\.]+) \(\+http:\/\/www\.chilkatsoft\.com\/ChilkatHttpUA\.asp\)/i,
              +			browserId: '364'
              +		},
              +		'457': {
              +			regexp: /^The Incutio XML-RPC PHP Library/i,
              +			browserId: '365'
              +		},
              +		'458': {
              +			regexp: /^Web-sniffer\/([0-9\.]+)[\s\S]*web-sniffer\.net\/\)$/i,
              +			browserId: '366'
              +		},
              +		'459': {
              +			regexp: /^Atomic_Email_Hunter\/([0-9\.]+)$/i,
              +			browserId: '367'
              +		},
              +		'460': {
              +			regexp: /^iGetter\/([0-9a-z\.]+)[\s\S]*/i,
              +			browserId: '368'
              +		},
              +		'461': {
              +			regexp: /^webfetch\/([0-9\.]+)/i,
              +			browserId: '369'
              +		},
              +		'462': {
              +			regexp: /^Mozilla\/4\.0 \(compatible; Synapse\)$/i,
              +			browserId: '370'
              +		},
              +		'463': {
              +			regexp: /^Mozilla\/[\s\S]*Gecko[\s\S]*lolifox\/([0-9\.]+)/i,
              +			browserId: '371'
              +		},
              +		'464': {
              +			regexp: /^Mozilla[\s\S]*SkipStone ([0-9\.]+)/i,
              +			browserId: '372'
              +		},
              +		'465': {
              +			regexp: /^Mozilla\/[\s\S]*compatible[\s\S]*Powermarks\/([0-9\.]+)/i,
              +			browserId: '373'
              +		},
              +		'466': {
              +			regexp: /^AppleSyndication\/([0-9\.]+)$/i,
              +			browserId: '374'
              +		},
              +		'467': {
              +			regexp: /^GoogleFriendConnect\/([0-9\.]+)$/i,
              +			browserId: '375'
              +		},
              +		'468': {
              +			regexp: /Mozilla[\s\S]*AppleWebKit[\s\S]*RockMelt\/([0-9a-z\.]+)/i,
              +			browserId: '377'
              +		},
              +		'469': {
              +			regexp: /^Mozilla[\s\S]*rv:[0-9\.]+[\s\S]*gecko\/[0-9]+[\s\S]*Epic\/([0-9\.]+)/i,
              +			browserId: '378'
              +		},
              +		'470': {
              +			regexp: /Mozilla[\s\S]*AppleWebKit[\s\S]*InternetSurfboard\/([0-9\.a-z]+)/i,
              +			browserId: '379'
              +		},
              +		'471': {
              +			regexp: /^Mozilla[\s\S]*Gecko[\s\S]*Vonkeror\/([0-9\.]+)/i,
              +			browserId: '380'
              +		},
              +		'472': {
              +			regexp: /^Windows-RSS-Platform\/([0-9\.]+)[\s\S]*MSIE[\s\S]* Windows/i,
              +			browserId: '381'
              +		},
              +		'473': {
              +			regexp: /^Trileet NewsRoom[\s\S]*feedmonger\.blogspot\.com/i,
              +			browserId: '382'
              +		},
              +		'474': {
              +			regexp: /^Validator[\s\S]nu\/([0-9\.]+)$/i,
              +			browserId: '383'
              +		},
              +		'475': {
              +			regexp: /^Zend_Http_Client$/i,
              +			browserId: '384'
              +		},
              +		'476': {
              +			regexp: /^Mozilla[\s\S]*AppleWebKit[\s\S]*Skyfire\/([0-9\.]+)/i,
              +			browserId: '385'
              +		},
              +		'477': {
              +			regexp: /^Mozilla[\s\S]*Android[\s\S]*GoBrowser\/([0-9\.]+)/i,
              +			browserId: '386'
              +		},
              +		'478': {
              +			regexp: /^Mozilla[\s\S]*Android[\s\S]*GoBrowser/i,
              +			browserId: '386'
              +		},
              +		'479': {
              +			regexp: /\/GoBrowser\/([0-9\.]+)/i,
              +			browserId: '386'
              +		},
              +		'480': {
              +			regexp: /^Surf\/([0-9\.]+)[\s\S]*AppleWebKit/i,
              +			browserId: '387'
              +		},
              +		'481': {
              +			regexp: /^iGooMap\/([0-9a-z\.]+)[\s\S]*pointworks/i,
              +			browserId: '388'
              +		},
              +		'482': {
              +			regexp: /^Xenu Link Sleuth\/([0-9a-z\+\-\.]+)$/i,
              +			browserId: '124'
              +		},
              +		'483': {
              +			regexp: /^iTunes\/([0-9\.]+)/i,
              +			browserId: '389'
              +		},
              +		'484': {
              +			regexp: /^Mozilla[\s\S]*WebKi[\s\S]*BlackHawk\/([0-9\.]+)[\s\S]*Chrome/i,
              +			browserId: '390'
              +		},
              +		'485': {
              +			regexp: /^Typhoeus[\s\S]*http:\/\/github[\s\S]com\/dbalatero\/typhoeus/i,
              +			browserId: '287'
              +		},
              +		'486': {
              +			regexp: /^Mozilla[\s\S]*Linux[\s\S]*Kindle\/([0-9\.]+)/i,
              +			browserId: '392'
              +		},
              +		'487': {
              +			regexp: /^Microsoft Office Existence Discovery/i,
              +			browserId: '393'
              +		},
              +		'488': {
              +			regexp: /mozilla[\s\S]*applewebkit[\s\S]*version\/([0-9a-z\+\-\.]+)[\s\S]*mobile[\s\S]*safari\/[0-9a-z\+\-\.]+[\s\S]*/i,
              +			browserId: '394'
              +		},
              +		'489': {
              +			regexp: /^Outlook-Express\/7\.0 \(MSIE 6\.0[\s\S]*Windows/i,
              +			browserId: '327'
              +		},
              +		'490': {
              +			regexp: /^BrownReclusePro v([0-9\.]+)[\s\S]*SoftByteLabs[\s\S]com/i,
              +			browserId: '395'
              +		},
              +		'491': {
              +			regexp: /^ColdFusion \(BookmarkTracker\.com\)$/i,
              +			browserId: '396'
              +		},
              +		'492': {
              +			regexp: /^BinGet\/([0-9a-zA-Z\.]+)/i,
              +			browserId: '397'
              +		},
              +		'493': {
              +			regexp: /^Mozilla[\s\S]*Gecko\/[0-9]+[\s\S]*WebianShell\/([0-9a-z\.]+)/i,
              +			browserId: '399'
              +		},
              +		'494': {
              +			regexp: /^Mozilla\/[\s\S]*Gecko\/[\s\S]*Firefox\/[\s\S]*Kylo\/([0-9\.]+)$/i,
              +			browserId: '400'
              +		},
              +		'495': {
              +			regexp: /^Outlook-Express\/7\.0 \(MSIE 8[\s\S]*Windows/i,
              +			browserId: '327'
              +		},
              +		'496': {
              +			regexp: /^Mozilla\/[\s\S]*Treco[\s\S]*Fireweb Navigator\/([0-9a-z\.]+)/i,
              +			browserId: '401'
              +		},
              +		'497': {
              +			regexp: /^CamelHttpStream\/([0-9\.]+)/i,
              +			browserId: '402'
              +		},
              +		'498': {
              +			regexp: /mozilla[\s\S]*AppleWebKit\/[\s\S]*epiphany\/([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '5'
              +		},
              +		'499': {
              +			regexp: /mozilla[\s\S]*rv:[0-9\.]+[\s\S]*Whistler[\s\S]*myibrow\/([0-9a-z\.]+)/i,
              +			browserId: '320'
              +		},
              +		'500': {
              +			regexp: /^Feed Viewer ([0-9\.]+)$/i,
              +			browserId: '376'
              +		},
              +		'501': {
              +			regexp: /^Mozilla[\s\S]*MSIE ([0-9\.]+)[\s\S]*XBLWP7/i,
              +			browserId: '157'
              +		},
              +		'502': {
              +			regexp: /^Mozilla[\s\S]*MSIE[\s\S]*Windows Phone[\s\S]*IEMobile\/([0-9\.]+)/i,
              +			browserId: '157'
              +		},
              +		'503': {
              +			regexp: /^EventMachine HttpClient/i,
              +			browserId: '403'
              +		},
              +		'504': {
              +			regexp: /Mozilla[\s\S]*Windows[\s\S]* Sundance\/([0-9a-z\.]+)/i,
              +			browserId: '404'
              +		},
              +		'505': {
              +			regexp: /Sundance[\s\S]*Windows[\s\S]*Version\/([0-9a-z\.]+)/i,
              +			browserId: '404'
              +		},
              +		'506': {
              +			regexp: /^Mozilla[\s\S]*Chromium\/([0-9a-z\+\-\.]+)[\s\S]*chrome[\s\S]*/i,
              +			browserId: '405'
              +		},
              +		'507': {
              +			regexp: /^Mozilla[\s\S]* AppleWebKit[\s\S]*Mobile/i,
              +			browserId: '394'
              +		},
              +		'508': {
              +			regexp: /Mozilla\/[\s\S]*AppleWebKit[\s\S]*Columbus\/([0-9\.]+)/i,
              +			browserId: '406'
              +		},
              +		'509': {
              +			regexp: /mozilla[\s\S]*iphone[\s\S]*os[\s\S]*/i,
              +			browserId: '394'
              +		},
              +		'510': {
              +			regexp: /Opera[\s\S]*Opera Mobi/i,
              +			browserId: '321'
              +		},
              +		'511': {
              +			regexp: /nokiac3[\s\S]*safari/i,
              +			browserId: '394'
              +		},
              +		'512': {
              +			regexp: /series60[\s\S]*applewebkit[\s\S]*/i,
              +			browserId: '226'
              +		},
              +		'513': {
              +			regexp: /mozilla[\s\S]*ipad[\s\S]*os[\s\S]*/i,
              +			browserId: '394'
              +		},
              +		'514': {
              +			regexp: /^Plex\/([0-9\.]+)[\s\S]*plexapp\.com/i,
              +			browserId: '407'
              +		},
              +		'515': {
              +			regexp: /Mozilla[\s\S]*AppleWebKit[\s\S]* WebRender/i,
              +			browserId: '408'
              +		},
              +		'516': {
              +			regexp: /^Mozilla[\s\S]*RIM Tablet OS[\s\S]*AppleWebKit[\s\S]*Safari/i,
              +			browserId: '158'
              +		},
              +		'517': {
              +			regexp: /Mozilla[\s\S]*Chrome[\s\S]*CoolNovo\/([a-z0-9\.]+)/i,
              +			browserId: '409'
              +		},
              +		'518': {
              +			regexp: /Mozilla[\s\S]*AppleWebKit[\s\S]*Usejump\/([0-9a-z\.]+)/i,
              +			browserId: '410'
              +		},
              +		'519': {
              +			regexp: /Mozilla[\s\S]*Gecko[\s\S]*Sundial\/([0-9a-z_\.]+)/i,
              +			browserId: '411'
              +		},
              +		'520': {
              +			regexp: /Symbian[\s\S]* NokiaBrowser/i,
              +			browserId: '226'
              +		},
              +		'521': {
              +			regexp: /Mozilla[\s\S]*Gecko[\s\S]*Alienforce\/([0-9a-z\.]+)/i,
              +			browserId: '412'
              +		},
              +		'522': {
              +			regexp: /^Googlebot-richsnippets/i,
              +			browserId: '413'
              +		},
              +		'523': {
              +			regexp: /^HTML2JPG[\s\S]*http:\/\/www[\s\S]html2jpg[\s\S]com/i,
              +			browserId: '414'
              +		},
              +		'524': {
              +			regexp: /^iCatcher! ([0-9\.]+)[\s\S]*iPhone OS/i,
              +			browserId: '415'
              +		},
              +		'525': {
              +			regexp: /Mozilla[\s\S]*AppleWebKit[\s\S]*Chrome[\s\S]*baidubrowser\/([0-9a-z\.]+)/i,
              +			browserId: '416'
              +		},
              +		'526': {
              +			regexp: /Mozilla[\s\S]*MSIE[\s\S]*Windows[\s\S]*baidubrowser ([0-9a-z\.]+)/i,
              +			browserId: '416'
              +		},
              +		'527': {
              +			regexp: /Mozilla[\s\S]*AppleWebKit[\s\S]*Chrome[\s\S]*SE ([0-9a-z\.]+) MetaSr/i,
              +			browserId: '417'
              +		},
              +		'528': {
              +			regexp: /Mozilla[\s\S]*MSIE[\s\S]* Windows[\s\S]*SE ([0-9a-z\.]+) MetaSr/i,
              +			browserId: '417'
              +		},
              +		'529': {
              +			regexp: /^MPlayer ([0-9\.]+)/i,
              +			browserId: '418'
              +		},
              +		'530': {
              +			regexp: /^Mozilla[\s\S]*AppleWebKit[\s\S]*Chrome[\s\S]*ZipZap ([0-9\.]+)/i,
              +			browserId: '419'
              +		},
              +		'531': {
              +			regexp: /Mozilla[\s\S]*AppleWebKit[\s\S]*QupZilla\/([0-9a-z\.\-]+)/i,
              +			browserId: '420'
              +		},
              +		'532': {
              +			regexp: /Mozilla[\s\S]*AppleWebKit[\s\S]*Patriott::Browser\/([0-9\.]+)/i,
              +			browserId: '421'
              +		},
              +		'533': {
              +			regexp: /^Mozilla[\s\S]*AppleWebKit[\s\S]*SLP Browser\/([0-9\.]+)/i,
              +			browserId: '422'
              +		},
              +		'534': {
              +			regexp: /^Mozilla[\s\S]*AppleWebKit[\s\S]*Tizen Browser|Tizenbrowser\/([0-9\.]+)/i,
              +			browserId: '422'
              +		},
              +		'535': {
              +			regexp: /Mozilla[\s\S]*Android[\s\S]*AppleWebKit[\s\S]*CrMo\/([0-9\.]+)/i,
              +			browserId: '423'
              +		},
              +		'536': {
              +			regexp: /^Plex\/([0-9\.]+)[\s\S]*Android/i,
              +			browserId: '407'
              +		},
              +		'537': {
              +			regexp: /^WAFA\/([0-9\.]+)[\s\S]*Android/i,
              +			browserId: '424'
              +		},
              +		'538': {
              +			regexp: /^Apache[\s\S]*internal dummy connection/i,
              +			browserId: '425'
              +		},
              +		'539': {
              +			regexp: /^Mozilla[\s\S]*Android [\s\S]*Ninesky\-android\-mobile\/([0-9\.]+)/i,
              +			browserId: '426'
              +		},
              +		'540': {
              +			regexp: /^Mozilla[\s\S]*Linux\/SmartTV[\s\S]*AppleWebKit[\s\S]*WebBrowser[\s\S]*SmartTV/i,
              +			browserId: '427'
              +		},
              +		'541': {
              +			regexp: /Mozilla[\s\S]*Linux[\s\S]*webOS[\s\S]*webOSBrowser\/([0-9\.]+)/i,
              +			browserId: '428'
              +		},
              +		'542': {
              +			regexp: /Mozilla[\s\S]*Linux[\s\S]*hpwOS[\s\S]*wOSBrowser\/([0-9\.]+)/i,
              +			browserId: '428'
              +		},
              +		'543': {
              +			regexp: /Nokia SyncML HTTP Client/i,
              +			browserId: '429'
              +		},
              +		'544': {
              +			regexp: /^Mozilla.*Charon.*Inferno/,
              +			browserId: '430'
              +		},
              +		'545': {
              +			regexp: /^JS\-Kit URL Resolver[\s\S]*js-kit\.com/i,
              +			browserId: '432'
              +		},
              +		'546': {
              +			regexp: /^Outlook-Express\/7\.0 \(MSIE 9[\s\S]*Windows/i,
              +			browserId: '327'
              +		},
              +		'547': {
              +			regexp: /^PocoMail ([0-9\.]+)/i,
              +			browserId: '356'
              +		},
              +		'548': {
              +			regexp: /^Podkicker\/([0-9\.]+)/i,
              +			browserId: '433'
              +		},
              +		'549': {
              +			regexp: /^Podkicker Pro\/([0-9\.]+)/i,
              +			browserId: '433'
              +		},
              +		'550': {
              +			regexp: /^python-requests\/([0-9\.]+)/i,
              +			browserId: '434'
              +		},
              +		'551': {
              +			regexp: /^AtomicBrowser\/([0-9\.]+)[\s\S]*CFNetwork/i,
              +			browserId: '436'
              +		},
              +		'552': {
              +			regexp: /^Reeder\/([0-9\.]+)[\s\S]*CFNetwork/i,
              +			browserId: '437'
              +		},
              +		'553': {
              +			regexp: /^Mozilla[\s\S]*Mobile[\s\S]*rv[\s\S]*Gecko[\s\S]*Firefox\/([0-9\.]+)/i,
              +			browserId: '133'
              +		},
              +		'554': {
              +			regexp: /Mozilla[\s\S]*Mac[\s\S]*rv[\s\S]*Gecko[\s\S]*Firefox\/([0-9a-b\.]+)[\s\S]*TenFourFox/i,
              +			browserId: '439'
              +		},
              +		'555': {
              +			regexp: /^PEAR HTTP_Request class \( http:\/\/pear[\s\S]php[\s\S]net\/ \)/i,
              +			browserId: '440'
              +		},
              +		'556': {
              +			regexp: /Mozilla[\s\S]*compatible[\s\S]*DPlus ([0-9\.]+)/i,
              +			browserId: '441'
              +		},
              +		'557': {
              +			regexp: /^WordPress\/[0-9\.]+; http:\/\//i,
              +			browserId: '438'
              +		},
              +		'558': {
              +			regexp: /Mozilla[\s\S]*Windows[\s\S]*Gecko[\s\S]*Firefox[\s\S]*AvantBrowser\/Tri-Core/i,
              +			browserId: '41'
              +		},
              +		'559': {
              +			regexp: /Mozilla[\s\S]*AppleWebKit[\s\S]*zBrowser\/SpringSun-([0-9\.]+)/i,
              +			browserId: '442'
              +		},
              +		'560': {
              +			regexp: /Mozilla[\s\S]*AppleWebKit[\s\S]*zBrowser\/NigtSky-([0-9\.]+)/i,
              +			browserId: '442'
              +		},
              +		'561': {
              +			regexp: /Mozilla[\s\S]*AppleWebKit[\s\S]*KHTML[\s\S]*SlimBoat\/([0-9\.]+)/i,
              +			browserId: '443'
              +		},
              +		'562': {
              +			regexp: /Opera[\s\S]*Opera Tablet[\s\S]*Presto[\s\S]*Version\/([0-9\.]+)/i,
              +			browserId: '321'
              +		},
              +		'563': {
              +			regexp: /^Mozilla[\s\S]*AppleWebKit[\s\S]*Chrome\/([0-9\.]+)[\s\S]*Mobile Safari/i,
              +			browserId: '423'
              +		},
              +		'564': {
              +			regexp: /^Mozilla[\s\S]*iPhone[\s\S]*AppleWebKit[\s\S]*CriOS\/([0-9\.]+)[\s\S]*Mobile[\s\S]*Safari/i,
              +			browserId: '423'
              +		},
              +		'565': {
              +			regexp: /^Mechanize\/([0-9\.]+)[\s\S]*Ruby[\s\S]*github[\s\S]com\/tenderlove\/mechanize/i,
              +			browserId: '445'
              +		},
              +		'566': {
              +			regexp: /^htmlayout ([0-9\.]+)[\s\S]*Win[\s\S]*www\.terrainformatica\.com/i,
              +			browserId: '446'
              +		},
              +		'567': {
              +			regexp: /^The Bat! Voyager ([0-9\.]+)$/i,
              +			browserId: '330'
              +		},
              +		'568': {
              +			regexp: /^Mozilla[\s\S]*MSIE[\s\S]*Windows[\s\S]*SaaYaa/i,
              +			browserId: '447'
              +		},
              +		'569': {
              +			regexp: /^Mozilla[\s\S]*AppleWebKit[\s\S]*Qt\/[0-9\.]+[\s\S]*Ryouko\/([0-9\.]+)[\s\S]*Safari/i,
              +			browserId: '448'
              +		},
              +		'570': {
              +			regexp: /^Anemone\/([0-9\.]+)$/i,
              +			browserId: '449'
              +		},
              +		'571': {
              +			regexp: /^Mozilla[\s\S]*OS X[\s\S]*AppleWebKit[\s\S]*KHTML[\s\S]*Sparrow\/([0-9\.]+)/i,
              +			browserId: '450'
              +		},
              +		'572': {
              +			regexp: /^SubStream\/([0-9\.]+)[\s\S]* CFNetwork/i,
              +			browserId: '451'
              +		},
              +		'573': {
              +			regexp: /^Mozilla[\s\S]*iPad[\s\S]*AppleWebKit[\s\S]*CriOS\/([0-9\.]+)[\s\S]*Mobile[\s\S]*Safari/i,
              +			browserId: '423'
              +		},
              +		'574': {
              +			regexp: /^Barca\/([0-9\.]+)/i,
              +			browserId: '452'
              +		},
              +		'575': {
              +			regexp: /^BarcaPro\/([0-9\.]+)/i,
              +			browserId: '452'
              +		},
              +		'576': {
              +			regexp: /A1 Sitemap Generator\/([0-9\.]+)[\s\S]*microsystools[\s\S]com/i,
              +			browserId: '453'
              +		},
              +		'577': {
              +			regexp: /^Mozilla[\s\S]*Playstation Vita[\s\S]*AppleWebKit[\s\S]*Silk\/([0-9\.]+)/i,
              +			browserId: '454'
              +		},
              +		'578': {
              +			regexp: /^MQQBrowser\/([0-9\.]+)/i,
              +			browserId: '455'
              +		},
              +		'579': {
              +			regexp: /^MQQBrowser\/(Mini[0-9\.]+)/i,
              +			browserId: '455'
              +		},
              +		'580': {
              +			regexp: /^Mozilla[\s\S]*AppleWebKit[\s\S]*Chrome[\s\S]*Beamrise\/([0-9\.]+)/i,
              +			browserId: '456'
              +		},
              +		'581': {
              +			regexp: /^Mozilla[\s\S]*AppleWebKit[\s\S]*Beamrise\/([0-9\.]+)[\s\S]*Chrome/i,
              +			browserId: '456'
              +		},
              +		'582': {
              +			regexp: /^Mozilla[\s\S]*AppleWebKit[\s\S]*Chrome[\s\S]*YaBrowser\/([0-9\.]+)/i,
              +			browserId: '457'
              +		},
              +		'583': {
              +			regexp: /^Mozilla[\s\S]*Silk\/([0-9\.\-]+)[\s\S]*safari/i,
              +			browserId: '458'
              +		},
              +		'584': {
              +			regexp: /^Apache-HttpClient\/([0-9\.]+)/i,
              +			browserId: '459'
              +		},
              +		'585': {
              +			regexp: /^Mozilla.*Nintendo WiiU.*AppleWebKit.*NX.*NintendoBrowser\/([0-9\.]+)/,
              +			browserId: '460'
              +		},
              +		'586': {
              +			regexp: /^DellWebMonitor\/([0-9\.]+)/,
              +			browserId: '461'
              +		},
              +		'587': {
              +			regexp: /^FeedDemon\/([0-9\.]+)[\s\S]*(www\.feeddemon\.com|www\.newsgator\.com)/i,
              +			browserId: '462'
              +		},
              +		'588': {
              +			regexp: /^XMLRPC::Client \(Ruby ([0-9\.]+)\)$/i,
              +			browserId: '463'
              +		},
              +		'589': {
              +			regexp: /^PocomailPE\/([0-9\.]+)/i,
              +			browserId: '356'
              +		},
              +		'590': {
              +			regexp: /Pattern\/([0-9\.]+)[\s\S]*[\s\S]clips\.ua\.ac\.be\/pages\/pattern/i,
              +			browserId: '464'
              +		},
              +		'592': {
              +			regexp: /^Eudora\/?([0-9a-z\.]+)*/i,
              +			browserId: '465'
              +		},
              +		'593': {
              +			regexp: /^Mozilla[\s\S]*Windows[\s\S]*Gecko[\s\S]*Polarity\/([0-9\.]+)/i,
              +			browserId: '467'
              +		},
              +		'594': {
              +			regexp: /^Mozilla[\s\S]*AppleWebKit[\s\S]*Superbird\/([0-9\.]+)/i,
              +			browserId: '468'
              +		},
              +		'595': {
              +			regexp: /^Microsoft Office\/14[\s\S]*Microsoft Outlook 14/i,
              +			browserId: '326'
              +		},
              +		'596': {
              +			regexp: /mozilla[\s\S]*AppleWebKit[\s\S]*NetFrontLifeBrowser\/([0-9\.]+)/i,
              +			browserId: '469'
              +		},
              +		'597': {
              +			regexp: /mozilla[\s\S]*applewebkit[\s\S]*\/[0-9a-z\+\-\.]+[\s\S]*version\/([0-9a-z\+\-\.]+)[\s\S]*safari\/[0-9a-z\+\-\.]+[\s\S]*/i,
              +			browserId: '22'
              +		},
              +		'598': {
              +			regexp: /^Mozilla[\s\S]*ASUS Transformer Pad[\s\S]*AppleWebKit[\s\S]*Chrome\/([0-9\.]+)[\s\S]*Safari/i,
              +			browserId: '423'
              +		},
              +		'599': {
              +			regexp: /^Mozilla[\s\S]*Android[\s\S]*AppleWebKit[\s\S]*Chrome[\s\S]*OPR\/([0-9\.]+)/i,
              +			browserId: '321'
              +		},
              +		'600': {
              +			regexp: /^Mozilla[\s\S]*AppleWebKit[\s\S]*YRCWeblink\/([0-9\.]+)[\s\S]*Safari/i,
              +			browserId: '470'
              +		},
              +		'601': {
              +			regexp: /^Mozilla[\s\S]*AppleWebKit[\s\S]*Chrome[\s\S]*OPR\/([0-9\.]+)/i,
              +			browserId: '17'
              +		},
              +		'602': {
              +			regexp: /Mozilla[\s\S]*Gecko[\s\S]*Firefox[\s\S]*IceDragon\/([0-9\.]+)/i,
              +			browserId: '471'
              +		},
              +		'603': {
              +			regexp: /^Mozilla[\s\S]*AppleWebKit[\s\S]*YaBrowser\/([0-9\.]+)[\s\S]*Chrome/i,
              +			browserId: '457'
              +		},
              +		'604': {
              +			regexp: /^Mozilla[\s\S]*AppleWebKit[\s\S]*Chrome[\s\S]*Safari[\s\S]*Midori\/([0-9\.]+)/i,
              +			browserId: '148'
              +		},
              +		'605': {
              +			regexp: /^Mozilla[\s\S]*AppleWebKit[\s\S]*Dooble\/([0-9\.]+)[\s\S]*Safari/i,
              +			browserId: '269'
              +		},
              +		'606': {
              +			regexp: /^Mozilla[\s\S]*AppleWebKit[\s\S]*UCBrowser\/([0-9\.]+)[\s\S]*Mobile[\s\S]*Safari/i,
              +			browserId: '225'
              +		},
              +		'607': {
              +			regexp: /^Microsoft Office\/15[\s\S]*Microsoft Outlook 15/i,
              +			browserId: '473'
              +		},
              +		'608': {
              +			regexp: /^Mozilla[\s\S]*MSIE[\s\S]*Microsoft Outlook 15/i,
              +			browserId: '473'
              +		},
              +		'609': {
              +			regexp: /^Typhoeus[\s\S]*https:\/\/github[\s\S]com\/typhoeus\/typhoeus/i,
              +			browserId: '287'
              +		},
              +		'610': {
              +			regexp: /^RestSharp ([0-9\.]+)$/i,
              +			browserId: '474'
              +		},
              +		'611': {
              +			regexp: /^Mozilla[\s\S]*Android[\s\S]*AppleWebKit[\s\S]*Chrome[\s\S]*YaBrowser\/([0-9\.]+)[\s\S]*Mobile/i,
              +			browserId: '475'
              +		},
              +		'612': {
              +			regexp: /Mozilla[\s\S]*AppleWebKit[\s\S]*Chrome[\s\S]*Safari[\s\S]*Puffin\/([0-9\.]+)/i,
              +			browserId: '476'
              +		},
              +		'613': {
              +			regexp: /Mozilla[\s\S]*Windows NT 6\.[\s\S]*Trident\/7\.0[\s\S]*rv:([0-9\.]+)/i,
              +			browserId: '35'
              +		},
              +		'614': {
              +			regexp: /Mozilla[\s\S]*AppleWebKit[\s\S]*Roccat\/([0-9\.]+)[\s\S]*R/i,
              +			browserId: '477'
              +		},
              +		'615': {
              +			regexp: /^Airmail ([0-9\.]+)[\s\S]*Mac OS X/i,
              +			browserId: '478'
              +		},
              +		'616': {
              +			regexp: /^Mozilla[\s\S]*Nintendo 3DS/i,
              +			browserId: '479'
              +		},
              +		'617': {
              +			regexp: /^Mozilla[\s\S]*Tizen 2[\s\S]*Version\/([0-9\.]+)[\s\S]*Mobile Safari/i,
              +			browserId: '422'
              +		},
              +		'619': {
              +			regexp: /mozilla[\s\S]*Linux armv7l[\s\S]*rv:[0-9\.]+[\s\S]*gecko\/[0-9]+[\s\S]*maemo browser ([0-9a-z\+\-\.]+)[\s\S]*/i,
              +			browserId: '260'
              +		},
              +		'620': {
              +			regexp: /^Mozilla[\s\S]*Polaris ([0-9\.])/i,
              +			browserId: '159'
              +		},
              +		'621': {
              +			regexp: /^Mozilla[\s\S]*BB10[\s\S]*Touch[\s\S]*AppleWebKit[\s\S]*Mobile/i,
              +			browserId: '158'
              +		},
              +		'622': {
              +			regexp: /^BrowserEmulator\/0\.9 see http:\/\/dejavu\.org/i,
              +			browserId: '481'
              +		},
              +		'623': {
              +			regexp: /^Mozilla\/5\.0[\s\S]*SymbianOS\/[0-9\.]+[\s\S]*AppleWebKit[\s\S]*KHTML[\s\S]*Safari\/[0-9\.]+/i,
              +			browserId: '226'
              +		},
              +		'624': {
              +			regexp: /^Mozilla[\s\S]*PalmOS[\s\S]*WebPro\/([0-9\.]+)[\s\S]*Palm/i,
              +			browserId: '482'
              +		},
              +		'625': {
              +			regexp: /^Mozilla[\s\S]*AppleWebKit[\s\S]*PhantomJS\/([0-9\.]+) Safari/i,
              +			browserId: '483'
              +		},
              +		order: [
              +			'599',
              +			'539',
              +			'596',
              +			'208',
              +			'583',
              +			'611',
              +			'2',
              +			'11',
              +			'49',
              +			'69',
              +			'94',
              +			'149',
              +			'197',
              +			'218',
              +			'359',
              +			'361',
              +			'414',
              +			'443',
              +			'535',
              +			'563',
              +			'564',
              +			'571',
              +			'573',
              +			'578',
              +			'579',
              +			'598',
              +			'612',
              +			'621',
              +			'199',
              +			'407',
              +			'408',
              +			'419',
              +			'541',
              +			'595',
              +			'608',
              +			'5',
              +			'593',
              +			'59',
              +			'117',
              +			'157',
              +			'175',
              +			'179',
              +			'180',
              +			'184',
              +			'203',
              +			'230',
              +			'232',
              +			'233',
              +			'234',
              +			'235',
              +			'266',
              +			'322',
              +			'396',
              +			'403',
              +			'406',
              +			'409',
              +			'439',
              +			'446',
              +			'489',
              +			'494',
              +			'495',
              +			'498',
              +			'533',
              +			'534',
              +			'546',
              +			'561',
              +			'577',
              +			'580',
              +			'581',
              +			'582',
              +			'594',
              +			'603',
              +			'614',
              +			'617',
              +			'170',
              +			'278',
              +			'410',
              +			'411',
              +			'444',
              +			'476',
              +			'506',
              +			'508',
              +			'515',
              +			'517',
              +			'520',
              +			'553',
              +			'554',
              +			'558',
              +			'559',
              +			'560',
              +			'600',
              +			'601',
              +			'602',
              +			'604',
              +			'605',
              +			'606',
              +			'7',
              +			'162',
              +			'22',
              +			'54',
              +			'60',
              +			'61',
              +			'114',
              +			'163',
              +			'182',
              +			'183',
              +			'314',
              +			'331',
              +			'340',
              +			'369',
              +			'431',
              +			'434',
              +			'436',
              +			'440',
              +			'441',
              +			'442',
              +			'452',
              +			'463',
              +			'468',
              +			'469',
              +			'470',
              +			'471',
              +			'484',
              +			'488',
              +			'496',
              +			'502',
              +			'507',
              +			'516',
              +			'519',
              +			'521',
              +			'525',
              +			'526',
              +			'527',
              +			'528',
              +			'530',
              +			'531',
              +			'532',
              +			'569',
              +			'499',
              +			'246',
              +			'400',
              +			'401',
              +			'402',
              +			'509',
              +			'513',
              +			'562',
              +			'438',
              +			'510',
              +			'511',
              +			'150',
              +			'261',
              +			'271',
              +			'342',
              +			'422',
              +			'486',
              +			'512',
              +			'619',
              +			'1',
              +			'3',
              +			'4',
              +			'6',
              +			'8',
              +			'9',
              +			'10',
              +			'14',
              +			'15',
              +			'16',
              +			'19',
              +			'20',
              +			'303',
              +			'24',
              +			'25',
              +			'26',
              +			'28',
              +			'29',
              +			'30',
              +			'31',
              +			'32',
              +			'33',
              +			'35',
              +			'36',
              +			'37',
              +			'223',
              +			'42',
              +			'304',
              +			'44',
              +			'45',
              +			'46',
              +			'48',
              +			'50',
              +			'51',
              +			'53',
              +			'55',
              +			'56',
              +			'57',
              +			'58',
              +			'63',
              +			'64',
              +			'65',
              +			'66',
              +			'67',
              +			'70',
              +			'77',
              +			'78',
              +			'80',
              +			'302',
              +			'86',
              +			'89',
              +			'97',
              +			'98',
              +			'100',
              +			'102',
              +			'104',
              +			'106',
              +			'107',
              +			'108',
              +			'109',
              +			'110',
              +			'111',
              +			'113',
              +			'115',
              +			'327',
              +			'118',
              +			'120',
              +			'122',
              +			'123',
              +			'371',
              +			'126',
              +			'130',
              +			'300',
              +			'169',
              +			'301',
              +			'137',
              +			'141',
              +			'147',
              +			'151',
              +			'152',
              +			'153',
              +			'156',
              +			'155',
              +			'160',
              +			'161',
              +			'164',
              +			'167',
              +			'171',
              +			'172',
              +			'173',
              +			'174',
              +			'176',
              +			'177',
              +			'178',
              +			'181',
              +			'185',
              +			'186',
              +			'187',
              +			'188',
              +			'189',
              +			'192',
              +			'194',
              +			'195',
              +			'196',
              +			'198',
              +			'204',
              +			'205',
              +			'206',
              +			'207',
              +			'209',
              +			'210',
              +			'211',
              +			'212',
              +			'213',
              +			'214',
              +			'215',
              +			'216',
              +			'217',
              +			'219',
              +			'220',
              +			'221',
              +			'222',
              +			'224',
              +			'225',
              +			'226',
              +			'227',
              +			'228',
              +			'229',
              +			'231',
              +			'236',
              +			'238',
              +			'241',
              +			'244',
              +			'247',
              +			'248',
              +			'249',
              +			'250',
              +			'251',
              +			'253',
              +			'258',
              +			'260',
              +			'262',
              +			'264',
              +			'265',
              +			'267',
              +			'272',
              +			'273',
              +			'274',
              +			'275',
              +			'276',
              +			'277',
              +			'279',
              +			'295',
              +			'293',
              +			'294',
              +			'287',
              +			'289',
              +			'296',
              +			'292',
              +			'297',
              +			'298',
              +			'305',
              +			'306',
              +			'307',
              +			'308',
              +			'311',
              +			'313',
              +			'316',
              +			'317',
              +			'318',
              +			'320',
              +			'321',
              +			'323',
              +			'324',
              +			'325',
              +			'328',
              +			'329',
              +			'330',
              +			'333',
              +			'334',
              +			'335',
              +			'336',
              +			'337',
              +			'338',
              +			'339',
              +			'341',
              +			'345',
              +			'346',
              +			'348',
              +			'349',
              +			'352',
              +			'353',
              +			'354',
              +			'355',
              +			'360',
              +			'362',
              +			'364',
              +			'365',
              +			'366',
              +			'367',
              +			'370',
              +			'372',
              +			'373',
              +			'374',
              +			'375',
              +			'376',
              +			'377',
              +			'378',
              +			'379',
              +			'381',
              +			'383',
              +			'384',
              +			'385',
              +			'386',
              +			'387',
              +			'388',
              +			'389',
              +			'390',
              +			'391',
              +			'393',
              +			'394',
              +			'395',
              +			'399',
              +			'405',
              +			'412',
              +			'413',
              +			'415',
              +			'416',
              +			'418',
              +			'420',
              +			'423',
              +			'424',
              +			'425',
              +			'426',
              +			'427',
              +			'428',
              +			'433',
              +			'435',
              +			'437',
              +			'445',
              +			'447',
              +			'449',
              +			'450',
              +			'451',
              +			'458',
              +			'459',
              +			'461',
              +			'466',
              +			'472',
              +			'473',
              +			'474',
              +			'475',
              +			'477',
              +			'478',
              +			'482',
              +			'487',
              +			'490',
              +			'493',
              +			'497',
              +			'500',
              +			'503',
              +			'504',
              +			'505',
              +			'514',
              +			'518',
              +			'524',
              +			'537',
              +			'540',
              +			'542',
              +			'543',
              +			'544',
              +			'545',
              +			'547',
              +			'548',
              +			'549',
              +			'550',
              +			'551',
              +			'552',
              +			'555',
              +			'556',
              +			'557',
              +			'565',
              +			'566',
              +			'567',
              +			'568',
              +			'570',
              +			'572',
              +			'576',
              +			'584',
              +			'585',
              +			'587',
              +			'588',
              +			'589',
              +			'590',
              +			'592',
              +			'607',
              +			'610',
              +			'613',
              +			'615',
              +			'616',
              +			'620',
              +			'622',
              +			'623',
              +			'624',
              +			'625',
              +			'17',
              +			'404',
              +			'47',
              +			'52',
              +			'79',
              +			'82',
              +			'166',
              +			'193',
              +			'239',
              +			'18',
              +			'34',
              +			'103',
              +			'105',
              +			'138',
              +			'139',
              +			'143',
              +			'190',
              +			'191',
              +			'201',
              +			'237',
              +			'242',
              +			'243',
              +			'245',
              +			'268',
              +			'269',
              +			'270',
              +			'280',
              +			'299',
              +			'309',
              +			'310',
              +			'312',
              +			'357',
              +			'358',
              +			'397',
              +			'455',
              +			'457',
              +			'479',
              +			'481',
              +			'491',
              +			'492',
              +			'501',
              +			'529',
              +			'536',
              +			'480',
              +			'62',
              +			'202',
              +			'240',
              +			'254',
              +			'255',
              +			'256',
              +			'257',
              +			'319',
              +			'350',
              +			'392',
              +			'462',
              +			'464',
              +			'465',
              +			'483',
              +			'522',
              +			'597',
              +			'23',
              +			'95',
              +			'165',
              +			'200',
              +			'259',
              +			'281',
              +			'315',
              +			'332',
              +			'343',
              +			'344',
              +			'363',
              +			'368',
              +			'380',
              +			'382',
              +			'398',
              +			'417',
              +			'421',
              +			'429',
              +			'430',
              +			'448',
              +			'453',
              +			'456',
              +			'460',
              +			'467',
              +			'485',
              +			'523',
              +			'538',
              +			'574',
              +			'575',
              +			'586',
              +			'609',
              +			'351',
              +			'83',
              +			'263',
              +			'432',
              +			'326',
              +			'39',
              +			'81',
              +			'356'
              +		]
              +	},
              +	browserOs: {
              +		'18': '44',
              +		'23': '19',
              +		'39': '43',
              +		'43': '35',
              +		'59': '43',
              +		'62': '43',
              +		'71': '43',
              +		'82': '43',
              +		'88': '43',
              +		'93': '43',
              +		'100': '47',
              +		'124': '43',
              +		'125': '44',
              +		'146': '44',
              +		'151': '10',
              +		'152': '47',
              +		'159': '10',
              +		'170': '44',
              +		'179': '43',
              +		'194': '43',
              +		'200': '43',
              +		'201': '43',
              +		'209': '43',
              +		'217': '43',
              +		'220': '10',
              +		'221': '19',
              +		'235': '19',
              +		'239': '43',
              +		'240': '19',
              +		'248': '43',
              +		'251': '43',
              +		'256': '43',
              +		'260': '75',
              +		'261': '75',
              +		'271': '43',
              +		'272': '43',
              +		'281': '47',
              +		'282': '43',
              +		'283': '43',
              +		'286': '62',
              +		'293': '43',
              +		'304': '43',
              +		'305': '43',
              +		'310': '33',
              +		'311': '43',
              +		'312': '43',
              +		'313': '44',
              +		'316': '43',
              +		'330': '43',
              +		'334': '43',
              +		'344': '43',
              +		'349': '19',
              +		'356': '43',
              +		'367': '43',
              +		'369': '43',
              +		'373': '43',
              +		'376': '43',
              +		'385': '114',
              +		'388': '86',
              +		'393': '43',
              +		'395': '43',
              +		'414': '43',
              +		'429': '34',
              +		'436': '65',
              +		'437': '65',
              +		'452': '43',
              +		'453': '43',
              +		order: [
              +			'18',
              +			'23',
              +			'39',
              +			'43',
              +			'59',
              +			'62',
              +			'71',
              +			'82',
              +			'88',
              +			'93',
              +			'100',
              +			'124',
              +			'125',
              +			'146',
              +			'151',
              +			'152',
              +			'159',
              +			'170',
              +			'179',
              +			'194',
              +			'200',
              +			'201',
              +			'209',
              +			'217',
              +			'220',
              +			'221',
              +			'235',
              +			'239',
              +			'240',
              +			'248',
              +			'251',
              +			'256',
              +			'260',
              +			'261',
              +			'271',
              +			'272',
              +			'281',
              +			'282',
              +			'283',
              +			'286',
              +			'293',
              +			'304',
              +			'305',
              +			'310',
              +			'311',
              +			'312',
              +			'313',
              +			'316',
              +			'330',
              +			'334',
              +			'344',
              +			'349',
              +			'356',
              +			'367',
              +			'369',
              +			'373',
              +			'376',
              +			'385',
              +			'388',
              +			'393',
              +			'395',
              +			'414',
              +			'429',
              +			'436',
              +			'437',
              +			'452',
              +			'453'
              +		]
              +	},
              +	osReg: {
              +		'1': {
              +			regexp: /windows nt 5\.1/i,
              +			osId: '1'
              +		},
              +		'3': {
              +			regexp: /windows nt 5\.0/i,
              +			osId: '2'
              +		},
              +		'4': {
              +			regexp: /[\s\S]*windows nt 5\.2( |;)[\s\S]*/i,
              +			osId: '3'
              +		},
              +		'5': {
              +			regexp: /[\s\S]*windows 95[\s\S]*/i,
              +			osId: '4'
              +		},
              +		'6': {
              +			regexp: /[\s\S]*win95[\s\S]*/i,
              +			osId: '4'
              +		},
              +		'7': {
              +			regexp: /windows 98/i,
              +			osId: '5'
              +		},
              +		'8': {
              +			regexp: /[\s\S]*win16( |;)[\s\S]*/i,
              +			osId: '6'
              +		},
              +		'9': {
              +			regexp: /[\s\S]*win98( |;)[\s\S]*/i,
              +			osId: '5'
              +		},
              +		'10': {
              +			regexp: /[\s\S]*windows 4\.10( |;)[\s\S]*/i,
              +			osId: '5'
              +		},
              +		'11': {
              +			regexp: /windows ce|PocketPC/i,
              +			osId: '7'
              +		},
              +		'12': {
              +			regexp: /[\s\S]*windows me( |;)[\s\S]*/i,
              +			osId: '8'
              +		},
              +		'13': {
              +			regexp: /[\s\S]*windows nt 6\.0( |;)[\s\S]*/i,
              +			osId: '9'
              +		},
              +		'14': {
              +			regexp: /j2me/i,
              +			osId: '10'
              +		},
              +		'15': {
              +			regexp: /centos/i,
              +			osId: '11'
              +		},
              +		'16': {
              +			regexp: /ubuntu/i,
              +			osId: '12'
              +		},
              +		'17': {
              +			regexp: /linux[\s\S]*debian/i,
              +			osId: '13'
              +		},
              +		'18': {
              +			regexp: /linux[\s\S]*fedora/i,
              +			osId: '14'
              +		},
              +		'19': {
              +			regexp: /linux[\s\S]*gentoo/i,
              +			osId: '15'
              +		},
              +		'20': {
              +			regexp: /linux[\s\S]*linspire/i,
              +			osId: '16'
              +		},
              +		'21': {
              +			regexp: /linux[\s\S]*mandriva/i,
              +			osId: '17'
              +		},
              +		'22': {
              +			regexp: /linux[\s\S]*mdk/i,
              +			osId: '17'
              +		},
              +		'23': {
              +			regexp: /linux[\s\S]*redhat/i,
              +			osId: '18'
              +		},
              +		'24': {
              +			regexp: /linux/i,
              +			osId: '19'
              +		},
              +		'25': {
              +			regexp: /linux[\s\S]*slackware/i,
              +			osId: '20'
              +		},
              +		'26': {
              +			regexp: /linux[\s\S]*kanotix/i,
              +			osId: '21'
              +		},
              +		'27': {
              +			regexp: /linux[\s\S]*suse/i,
              +			osId: '22'
              +		},
              +		'28': {
              +			regexp: /linux[\s\S]*knoppix/i,
              +			osId: '23'
              +		},
              +		'29': {
              +			regexp: /[\s\S]*netbsd[\s\S]*/i,
              +			osId: '24'
              +		},
              +		'30': {
              +			regexp: /[\s\S]*freebsd[\s\S]*/i,
              +			osId: '25'
              +		},
              +		'31': {
              +			regexp: /[\s\S]*openbsd[\s\S]*/i,
              +			osId: '26'
              +		},
              +		'34': {
              +			regexp: /sunos/i,
              +			osId: '29'
              +		},
              +		'35': {
              +			regexp: /amiga/i,
              +			osId: '30'
              +		},
              +		'36': {
              +			regexp: /irix/i,
              +			osId: '31'
              +		},
              +		'37': {
              +			regexp: /open[\s\S]*vms/i,
              +			osId: '32'
              +		},
              +		'38': {
              +			regexp: /beos/i,
              +			osId: '33'
              +		},
              +		'39': {
              +			regexp: /symbian/i,
              +			osId: '34'
              +		},
              +		'40': {
              +			regexp: /palm/i,
              +			osId: '35'
              +		},
              +		'42': {
              +			regexp: /webtv/i,
              +			osId: '37'
              +		},
              +		'43': {
              +			regexp: /os\/2[\s\S]*warp/i,
              +			osId: '39'
              +		},
              +		'44': {
              +			regexp: /os\/2/i,
              +			osId: '87'
              +		},
              +		'45': {
              +			regexp: /RISC[\s\S]OS/i,
              +			osId: '40'
              +		},
              +		'46': {
              +			regexp: /hp-ux/i,
              +			osId: '41'
              +		},
              +		'47': {
              +			regexp: /Nintendo[\s\S]Wii/i,
              +			osId: '42'
              +		},
              +		'48': {
              +			regexp: /windows/i,
              +			osId: '43'
              +		},
              +		'49': {
              +			regexp: /mac_powerpc/i,
              +			osId: '44'
              +		},
              +		'50': {
              +			regexp: /Macintosh/i,
              +			osId: '44'
              +		},
              +		'51': {
              +			regexp: /aix/i,
              +			osId: '45'
              +		},
              +		'52': {
              +			regexp: /Win32/i,
              +			osId: '43'
              +		},
              +		'53': {
              +			regexp: /winnt/i,
              +			osId: '46'
              +		},
              +		'54': {
              +			regexp: /java\/[0-9a-z\.]+/i,
              +			osId: '47'
              +		},
              +		'55': {
              +			regexp: /[\s\S]*windows XP[\s\S]*/i,
              +			osId: '1'
              +		},
              +		'56': {
              +			regexp: /Series80\/2\.0/i,
              +			osId: '34'
              +		},
              +		'57': {
              +			regexp: /SonyEricssonP900/i,
              +			osId: '34'
              +		},
              +		'58': {
              +			regexp: /plan 9/i,
              +			osId: '49'
              +		},
              +		'59': {
              +			regexp: /NetFront[\s\S]*Profile\/MIDP/i,
              +			osId: '10'
              +		},
              +		'60': {
              +			regexp: /BlackBerry/i,
              +			osId: '50'
              +		},
              +		'61': {
              +			regexp: /Series90[\s\S]*Nokia7710/i,
              +			osId: '34'
              +		},
              +		'63': {
              +			regexp: /linux[\s\S]*\(Dropline GNOME\)[\s\S]*/i,
              +			osId: '20'
              +		},
              +		'64': {
              +			regexp: /Win 9x 4\.90/i,
              +			osId: '8'
              +		},
              +		'65': {
              +			regexp: /WinNT4\.0/i,
              +			osId: '46'
              +		},
              +		'66': {
              +			regexp: /linux[\s\S]*red hat/i,
              +			osId: '18'
              +		},
              +		'67': {
              +			regexp: /Solaris/i,
              +			osId: '29'
              +		},
              +		'68': {
              +			regexp: /QNX x86pc/i,
              +			osId: '52'
              +		},
              +		'69': {
              +			regexp: /Red Hat modified/i,
              +			osId: '18'
              +		},
              +		'70': {
              +			regexp: /Windows\-NT/i,
              +			osId: '46'
              +		},
              +		'71': {
              +			regexp: /MorphOS/i,
              +			osId: '53'
              +		},
              +		'73': {
              +			regexp: /CYGWIN_NT\-5[\s\S]0/i,
              +			osId: '2'
              +		},
              +		'74': {
              +			regexp: /powerpc\-apple/i,
              +			osId: '44'
              +		},
              +		'75': {
              +			regexp: /^DoCoMo[\s\S]*F900i/i,
              +			osId: '34'
              +		},
              +		'76': {
              +			regexp: /Vector Linux/i,
              +			osId: '55'
              +		},
              +		'77': {
              +			regexp: /riscos/i,
              +			osId: '40'
              +		},
              +		'78': {
              +			regexp: /Linux Mint/i,
              +			osId: '56'
              +		},
              +		'79': {
              +			regexp: /SCO_SV/i,
              +			osId: '57'
              +		},
              +		'80': {
              +			regexp: /suse\-linux/i,
              +			osId: '22'
              +		},
              +		'81': {
              +			regexp: /Arch Linux ([0-9a-zA-Z\.\-]+)/i,
              +			osId: '58'
              +		},
              +		'82': {
              +			regexp: /Gentoo i686/i,
              +			osId: '15'
              +		},
              +		'83': {
              +			regexp: /SkyOS/i,
              +			osId: '59'
              +		},
              +		'84': {
              +			regexp: /[\s\S]*windows 3\.1[\s\S]*/i,
              +			osId: '6'
              +		},
              +		'85': {
              +			regexp: /[\s\S]*dragonfly[\s\S]*/i,
              +			osId: '61'
              +		},
              +		'86': {
              +			regexp: /Android ([0-9\.]+)/i,
              +			osId: '62'
              +		},
              +		'87': {
              +			regexp: /windows nt 6\.1/i,
              +			osId: '64'
              +		},
              +		'88': {
              +			regexp: /[\s\S]*windows 2000( |;)[\s\S]*/i,
              +			osId: '2'
              +		},
              +		'90': {
              +			regexp: /iPhone OS 2_0/i,
              +			osId: '65'
              +		},
              +		'92': {
              +			regexp: /iPhone OS ([0-9_]+) like Mac OS X/i,
              +			osId: '65'
              +		},
              +		'93': {
              +			regexp: /NT4\.0/i,
              +			osId: '46'
              +		},
              +		'94': {
              +			regexp: /java[0-9a-z\.]+/i,
              +			osId: '47'
              +		},
              +		'95': {
              +			regexp: /webOS\/[\s\S]*AppleWebKit/i,
              +			osId: '69'
              +		},
              +		'96': {
              +			regexp: /BeOS[\s\S]*Haiku BePC/i,
              +			osId: '70'
              +		},
              +		'98': {
              +			regexp: /Windows NT 6\.0/i,
              +			osId: '9'
              +		},
              +		'99': {
              +			regexp: /macos/i,
              +			osId: '44'
              +		},
              +		'100': {
              +			regexp: /Series 60/i,
              +			osId: '34'
              +		},
              +		'101': {
              +			regexp: /os=Mac/i,
              +			osId: '44'
              +		},
              +		'102': {
              +			regexp: /Series60/i,
              +			osId: '34'
              +		},
              +		'103': {
              +			regexp: /Danger hiptop [0-9\.]+/i,
              +			osId: '72'
              +		},
              +		'105': {
              +			regexp: /Konqueror[\s\S]*SUSE/i,
              +			osId: '22'
              +		},
              +		'106': {
              +			regexp: /Konqueror[\s\S]*Fedora/i,
              +			osId: '14'
              +		},
              +		'107': {
              +			regexp: /Obigo[\s\S]*MIDP/i,
              +			osId: '10'
              +		},
              +		'108': {
              +			regexp: /Teleca[\s\S]*MIDP/i,
              +			osId: '10'
              +		},
              +		'109': {
              +			regexp: /Syllable/i,
              +			osId: '74'
              +		},
              +		'110': {
              +			regexp: /Windows_XP\/5[\s\S]1/i,
              +			osId: '1'
              +		},
              +		'111': {
              +			regexp: /SO=MAC10,6/i,
              +			osId: '44'
              +		},
              +		'112': {
              +			regexp: /so=Mac 10[\s\S]5[\s\S]8/i,
              +			osId: '44'
              +		},
              +		'114': {
              +			regexp: /[\s\S]*windows 7[\s\S]*/i,
              +			osId: '64'
              +		},
              +		'115': {
              +			regexp: /iPhone OS [0-9\.]+/i,
              +			osId: '65'
              +		},
              +		'116': {
              +			regexp: /Mac OS X (10_6|10\.6)/i,
              +			osId: '85'
              +		},
              +		'117': {
              +			regexp: /Mac OS X (10_5|10\.5)/i,
              +			osId: '84'
              +		},
              +		'118': {
              +			regexp: /Mac OS X (10_4|10\.4)/i,
              +			osId: '83'
              +		},
              +		'119': {
              +			regexp: /Mac OS X/i,
              +			osId: '86'
              +		},
              +		'120': {
              +			regexp: /Mozilla[\s\S]*Linux[\s\S]*Maemo/i,
              +			osId: '75'
              +		},
              +		'121': {
              +			regexp: /Windows NT 4/i,
              +			osId: '46'
              +		},
              +		'122': {
              +			regexp: /Windows ME/i,
              +			osId: '8'
              +		},
              +		'123': {
              +			regexp: /Windows 2000/i,
              +			osId: '2'
              +		},
              +		'124': {
              +			regexp: /S60; SymbOS/i,
              +			osId: '34'
              +		},
              +		'125': {
              +			regexp: /Windows Mobile/i,
              +			osId: '88'
              +		},
              +		'126': {
              +			regexp: /Darwin 10\.3/i,
              +			osId: '90'
              +		},
              +		'127': {
              +			regexp: /Minix 3/i,
              +			osId: '91'
              +		},
              +		'128': {
              +			regexp: /iPhone/i,
              +			osId: '65'
              +		},
              +		'129': {
              +			regexp: /Darwin/i,
              +			osId: '44'
              +		},
              +		'130': {
              +			regexp: /PCLinuxOS\/([0-9a-z\.\-]+)/i,
              +			osId: '92'
              +		},
              +		'131': {
              +			regexp: /^Mozilla\/[\s\S]*Linux[\s\S]*Jolicloud/i,
              +			osId: '93'
              +		},
              +		'132': {
              +			regexp: /PLAYSTATION 3/i,
              +			osId: '94'
              +		},
              +		'133': {
              +			regexp: /PlayStation Portable/i,
              +			osId: '94'
              +		},
              +		'134': {
              +			regexp: /SymbianOS/i,
              +			osId: '34'
              +		},
              +		'135': {
              +			regexp: /AROS/i,
              +			osId: '95'
              +		},
              +		'136': {
              +			regexp: /iPhone[\s\S]*like Mac OS X/i,
              +			osId: '65'
              +		},
              +		'137': {
              +			regexp: /iPad[\s\S]*OS[\s\S]*like Mac OS X/i,
              +			osId: '65'
              +		},
              +		'138': {
              +			regexp: /^HTC_HD2[\s\S]*Opera[\s\S]*windows/i,
              +			osId: '96'
              +		},
              +		'139': {
              +			regexp: /^Mozilla[\s\S]*CrOS[\s\S]*Chrome/i,
              +			osId: '97'
              +		},
              +		'140': {
              +			regexp: /Android[\s\S]*Linux[\s\S]*Opera Mobi/i,
              +			osId: '62'
              +		},
              +		'141': {
              +			regexp: /Nintendo DS/i,
              +			osId: '98'
              +		},
              +		'142': {
              +			regexp: /^Opera[\s\S]*Android/i,
              +			osId: '62'
              +		},
              +		'143': {
              +			regexp: /NokiaN97/i,
              +			osId: '34'
              +		},
              +		'144': {
              +			regexp: /Nokia[\s\S]*XpressMusic/i,
              +			osId: '34'
              +		},
              +		'145': {
              +			regexp: /NokiaE66/i,
              +			osId: '34'
              +		},
              +		'146': {
              +			regexp: /Nokia6700/i,
              +			osId: '34'
              +		},
              +		'147': {
              +			regexp: /\(GNU;/i,
              +			osId: '99'
              +		},
              +		'148': {
              +			regexp: /Unix/i,
              +			osId: '19'
              +		},
              +		'149': {
              +			regexp: /^Mozilla[\s\S]*MSIE[\s\S]*Windows[\s\S]* XBLWP7/i,
              +			osId: '96'
              +		},
              +		'150': {
              +			regexp: /Windows Phone OS 7/,
              +			osId: '96'
              +		},
              +		'151': {
              +			regexp: /windows nt 6\.2/i,
              +			osId: '100'
              +		},
              +		'152': {
              +			regexp: /RIM Tablet OS 1[0-9\.]+/i,
              +			osId: '101'
              +		},
              +		'153': {
              +			regexp: /Android/i,
              +			osId: '62'
              +		},
              +		'154': {
              +			regexp: /Bada\/[0-9\.]+/i,
              +			osId: '102'
              +		},
              +		'155': {
              +			regexp: /Android 1[\s\S]0/i,
              +			osId: '110'
              +		},
              +		'156': {
              +			regexp: /Android 1[\s\S]5/i,
              +			osId: '103'
              +		},
              +		'157': {
              +			regexp: /Android 1[\s\S]6/i,
              +			osId: '104'
              +		},
              +		'158': {
              +			regexp: /Android 2[\s\S]0|Android 2[\s\S]1/i,
              +			osId: '105'
              +		},
              +		'159': {
              +			regexp: /Android 2[\s\S]2/i,
              +			osId: '106'
              +		},
              +		'160': {
              +			regexp: /Android 2[\s\S]3|Android 2[\s\S]4/i,
              +			osId: '107'
              +		},
              +		'161': {
              +			regexp: /Android 3[\s\S]/i,
              +			osId: '108'
              +		},
              +		'162': {
              +			regexp: /Android Donut/i,
              +			osId: '104'
              +		},
              +		'163': {
              +			regexp: /Android Eclair/i,
              +			osId: '105'
              +		},
              +		'164': {
              +			regexp: /Android 4[\s\S]/i,
              +			osId: '111'
              +		},
              +		'165': {
              +			regexp: /Mac OS X (10_7|10\.7)/i,
              +			osId: '112'
              +		},
              +		'166': {
              +			regexp: /^Mozilla[\s\S]*Tizen\/1/i,
              +			osId: '113'
              +		},
              +		'167': {
              +			regexp: /Android-4[\s\S]/i,
              +			osId: '111'
              +		},
              +		'168': {
              +			regexp: /Android\/3/i,
              +			osId: '108'
              +		},
              +		'169': {
              +			regexp: /Linux.*hpwOS/,
              +			osId: '69'
              +		},
              +		'170': {
              +			regexp: /^Mozilla.*Charon.*Inferno/,
              +			osId: '115'
              +		},
              +		'171': {
              +			regexp: /Mac OS X (10_8|10\.8)/i,
              +			osId: '116'
              +		},
              +		'172': {
              +			regexp: /[\s\S]*Windows\-Vista/i,
              +			osId: '9'
              +		},
              +		'173': {
              +			regexp: /iPhone OS 5_[0-9_]+/i,
              +			osId: '118'
              +		},
              +		'174': {
              +			regexp: /iPhone OS 4_[0-9_]+/i,
              +			osId: '117'
              +		},
              +		'175': {
              +			regexp: /iPad[\s\S]*OS 5_[0-9_]+/i,
              +			osId: '118'
              +		},
              +		'176': {
              +			regexp: /RIM Tablet OS 2[0-9\.]+/i,
              +			osId: '119'
              +		},
              +		'177': {
              +			regexp: /Android 4\.1/i,
              +			osId: '120'
              +		},
              +		'178': {
              +			regexp: /iPad[\s\S]*OS 6_[0-9_]+/i,
              +			osId: '121'
              +		},
              +		'179': {
              +			regexp: /iPhone OS 6_[0-9_]+/i,
              +			osId: '121'
              +		},
              +		'180': {
              +			regexp: /PlayStation Vita/i,
              +			osId: '122'
              +		},
              +		'181': {
              +			regexp: /^Mozilla[\s\S]*MSIE[\s\S]*Windows NT 6[\s\S]1[\s\S]* Xbox/i,
              +			osId: '123'
              +		},
              +		'182': {
              +			regexp: /^XBMC[\s\S]*Xbox[\s\S]*www\.xbmc\.org/i,
              +			osId: '123'
              +		},
              +		'183': {
              +			regexp: /Android 4\.2/i,
              +			osId: '124'
              +		},
              +		'184': {
              +			regexp: /^Mozilla\/5\.0 \(Mobile; rv:[0-9\.]+[\s\S]*\) Gecko\/[0-9\.]+ Firefox\/[0-9\.]+$/i,
              +			osId: '125'
              +		},
              +		'186': {
              +			regexp: /windows nt 6\.2[\s\S]*ARM/i,
              +			osId: '126'
              +		},
              +		'187': {
              +			regexp: /^Mozilla[\s\S]*Windows Phone 8[\s\S]0/i,
              +			osId: '127'
              +		},
              +		'188': {
              +			regexp: /Linux[\s\S]*Mageia/i,
              +			osId: '128'
              +		},
              +		'189': {
              +			regexp: /iPhone OS 7_[0-9_]+/i,
              +			osId: '129'
              +		},
              +		'190': {
              +			regexp: /Windows NT 6\.3/i,
              +			osId: '130'
              +		},
              +		'191': {
              +			regexp: /Android 4\.3/i,
              +			osId: '131'
              +		},
              +		'192': {
              +			regexp: /Mac OS X (10_9|10\.9)/i,
              +			osId: '132'
              +		},
              +		'193': {
              +			regexp: /iPad[\s\S]*OS 7_[0-9_]+/i,
              +			osId: '129'
              +		},
              +		'194': {
              +			regexp: /Samsung[\s\S]*SmartTV/i,
              +			osId: '19'
              +		},
              +		'195': {
              +			regexp: /AppleTV/i,
              +			osId: '86'
              +		},
              +		'196': {
              +			regexp: /VectorLinux/i,
              +			osId: '55'
              +		},
              +		'197': {
              +			regexp: /^Mozilla[\s\S]*Nintendo 3DS/i,
              +			osId: '133'
              +		},
              +		'198': {
              +			regexp: /^Mozilla[\s\S]*Tizen 2/i,
              +			osId: '134'
              +		},
              +		'199': {
              +			regexp: /^Mozilla[\s\S]*BB10[\s\S]*Touch[\s\S]*AppleWebKit[\s\S]*Mobile/i,
              +			osId: '50'
              +		},
              +		order: [
              +			'40',
              +			'64',
              +			'71',
              +			'173',
              +			'174',
              +			'175',
              +			'178',
              +			'179',
              +			'186',
              +			'189',
              +			'193',
              +			'92',
              +			'67',
              +			'90',
              +			'102',
              +			'136',
              +			'138',
              +			'181',
              +			'177',
              +			'183',
              +			'191',
              +			'60',
              +			'96',
              +			'149',
              +			'155',
              +			'156',
              +			'157',
              +			'158',
              +			'159',
              +			'160',
              +			'161',
              +			'162',
              +			'163',
              +			'164',
              +			'166',
              +			'167',
              +			'168',
              +			'198',
              +			'125',
              +			'1',
              +			'5',
              +			'3',
              +			'4',
              +			'56',
              +			'6',
              +			'7',
              +			'8',
              +			'9',
              +			'10',
              +			'11',
              +			'12',
              +			'13',
              +			'14',
              +			'15',
              +			'16',
              +			'17',
              +			'18',
              +			'19',
              +			'20',
              +			'21',
              +			'22',
              +			'23',
              +			'25',
              +			'26',
              +			'27',
              +			'28',
              +			'29',
              +			'30',
              +			'31',
              +			'116',
              +			'34',
              +			'35',
              +			'36',
              +			'37',
              +			'38',
              +			'42',
              +			'43',
              +			'45',
              +			'46',
              +			'47',
              +			'53',
              +			'57',
              +			'58',
              +			'59',
              +			'61',
              +			'63',
              +			'65',
              +			'66',
              +			'68',
              +			'69',
              +			'70',
              +			'137',
              +			'73',
              +			'75',
              +			'76',
              +			'77',
              +			'78',
              +			'79',
              +			'80',
              +			'81',
              +			'83',
              +			'84',
              +			'86',
              +			'87',
              +			'88',
              +			'117',
              +			'95',
              +			'98',
              +			'118',
              +			'103',
              +			'110',
              +			'134',
              +			'114',
              +			'115',
              +			'120',
              +			'124',
              +			'130',
              +			'131',
              +			'132',
              +			'139',
              +			'140',
              +			'150',
              +			'151',
              +			'152',
              +			'153',
              +			'154',
              +			'165',
              +			'169',
              +			'170',
              +			'171',
              +			'172',
              +			'176',
              +			'180',
              +			'182',
              +			'184',
              +			'188',
              +			'190',
              +			'192',
              +			'194',
              +			'195',
              +			'196',
              +			'197',
              +			'199',
              +			'119',
              +			'24',
              +			'82',
              +			'105',
              +			'106',
              +			'107',
              +			'108',
              +			'123',
              +			'121',
              +			'39',
              +			'44',
              +			'55',
              +			'85',
              +			'122',
              +			'187',
              +			'93',
              +			'133',
              +			'48',
              +			'49',
              +			'50',
              +			'51',
              +			'52',
              +			'54',
              +			'109',
              +			'74',
              +			'135',
              +			'94',
              +			'100',
              +			'101',
              +			'111',
              +			'112',
              +			'127',
              +			'141',
              +			'142',
              +			'143',
              +			'144',
              +			'145',
              +			'146',
              +			'147',
              +			'99',
              +			'126',
              +			'128',
              +			'148',
              +			'129'
              +		]
              +	},
              +	device: {
              +		'1': {
              +			deviceType: 'Other',
              +			deviceIcon: 'other.png',
              +			deviceInfoUrl: '/list-of-ua/device-detail?device=Other'
              +		},
              +		'2': {
              +			deviceType: 'Personal computer',
              +			deviceIcon: 'desktop.png',
              +			deviceInfoUrl: '/list-of-ua/device-detail?device=Personal computer'
              +		},
              +		'3': {
              +			deviceType: 'Smartphone',
              +			deviceIcon: 'phone.png',
              +			deviceInfoUrl: '/list-of-ua/device-detail?device=Smartphone'
              +		},
              +		'4': {
              +			deviceType: 'Tablet',
              +			deviceIcon: 'tablet.png',
              +			deviceInfoUrl: '/list-of-ua/device-detail?device=Tablet'
              +		},
              +		'5': {
              +			deviceType: 'Game console',
              +			deviceIcon: 'console.png',
              +			deviceInfoUrl: '/list-of-ua/device-detail?device=Game console'
              +		},
              +		'6': {
              +			deviceType: 'Smart TV',
              +			deviceIcon: 'smarttv.png',
              +			deviceInfoUrl: '/list-of-ua/device-detail?device=Smart TV'
              +		},
              +		'7': {
              +			deviceType: 'PDA',
              +			deviceIcon: 'pda.png',
              +			deviceInfoUrl: '/list-of-ua/device-detail?device=PDA'
              +		},
              +		order: [
              +			'1',
              +			'2',
              +			'3',
              +			'4',
              +			'5',
              +			'6',
              +			'7'
              +		]
              +	},
              +	deviceReg: {
              +		'1': {
              +			regexp: /iPad[\s\S]*OS[\s\S]*like Mac OS X/i,
              +			deviceId: '4'
              +		},
              +		'2': {
              +			regexp: /Nintendo/i,
              +			deviceId: '5'
              +		},
              +		'3': {
              +			regexp: /Playstation/i,
              +			deviceId: '5'
              +		},
              +		'5': {
              +			regexp: /PlayBook|RIM Tablet/i,
              +			deviceId: '4'
              +		},
              +		'6': {
              +			regexp: /Bada\/[0-9\.]+/i,
              +			deviceId: '3'
              +		},
              +		'9': {
              +			regexp: /^HbbTV/i,
              +			deviceId: '6'
              +		},
              +		'10': {
              +			regexp: /^Mozilla[\s\S]*Escape [0-9\.]+/i,
              +			deviceId: '6'
              +		},
              +		'11': {
              +			regexp: /^Mozilla[\s\S]*Linux[\s\S]*Kindle\/[0-9\.]+/i,
              +			deviceId: '4'
              +		},
              +		'12': {
              +			regexp: /Kindle Fire/i,
              +			deviceId: '4'
              +		},
              +		'13': {
              +			regexp: /^Mozilla[\s\S]*Android[\s\S]*Transformer/i,
              +			deviceId: '4'
              +		},
              +		'14': {
              +			regexp: /^Mozilla[\s\S]*MSIE[\s\S]*Windows[\s\S]*ARM[\s\S]*Touch/i,
              +			deviceId: '4'
              +		},
              +		'15': {
              +			regexp: /^Mozilla[\s\S]*SmartHub[\s\S]*Linux/i,
              +			deviceId: '6'
              +		},
              +		'16': {
              +			regexp: /^Mozilla[\s\S]*SMART\-TV|SMARTTV[\s\S]*Linux/i,
              +			deviceId: '6'
              +		},
              +		'17': {
              +			regexp: /^Mozilla[\s\S]*Android[\s\S]*SMARTTVBOX/i,
              +			deviceId: '6'
              +		},
              +		'18': {
              +			regexp: /^Opera[\s\S]*Linux[\s\S]*HbbTV/i,
              +			deviceId: '6'
              +		},
              +		'19': {
              +			regexp: /^Mozilla[\s\S]*Chrome[\s\S]*GoogleTV/i,
              +			deviceId: '6'
              +		},
              +		'20': {
              +			regexp: /AppleTV/i,
              +			deviceId: '6'
              +		},
              +		'21': {
              +			regexp: /^Mozilla[\s\S]*Android[\s\S]*SGP311/i,
              +			deviceId: '4'
              +		},
              +		'22': {
              +			regexp: /^Mozilla[\s\S]*Android[\s\S]*SGPT12/i,
              +			deviceId: '4'
              +		},
              +		'23': {
              +			regexp: /^Mozilla[\s\S]*Android[\s\S]*Sony Tablet P/i,
              +			deviceId: '4'
              +		},
              +		'24': {
              +			regexp: /^Mozilla[\s\S]*Android[\s\S]*SonySGP311/i,
              +			deviceId: '4'
              +		},
              +		'25': {
              +			regexp: /^Mozilla[\s\S]*Gecko[\s\S]*Firefox[\s\S]*Kylo\/([0-9\.]+)$/i,
              +			deviceId: '6'
              +		},
              +		'26': {
              +			regexp: /^Mozilla[\s\S]*linux[\s\S]*KFTT[\s\S]*Silk/i,
              +			deviceId: '4'
              +		},
              +		'27': {
              +			regexp: /^Mozilla[\s\S]*linux[\s\S]*KFOT[\s\S]*Silk/i,
              +			deviceId: '4'
              +		},
              +		'28': {
              +			regexp: /^Mozilla[\s\S]*Android|Linux[\s\S]*KFJWI[\s\S]*Silk/i,
              +			deviceId: '4'
              +		},
              +		'29': {
              +			regexp: /^Mozilla[\s\S]*linux[\s\S]*KFJWA[\s\S]*Silk/i,
              +			deviceId: '4'
              +		},
              +		'30': {
              +			regexp: /j2me/i,
              +			deviceId: '3'
              +		},
              +		'31': {
              +			regexp: /Obigo[\s\S]*MIDP/i,
              +			deviceId: '3'
              +		},
              +		'32': {
              +			regexp: /Teleca[\s\S]*MIDP/i,
              +			deviceId: '3'
              +		},
              +		'33': {
              +			regexp: /^Mozilla[\s\S]*MSIE[\s\S]*Windows[\s\S]* Tablet PC [0-9\.]+/i,
              +			deviceId: '4'
              +		},
              +		'34': {
              +			regexp: /^Mozilla[\s\S]*Android[\s\S]*SurfTab/i,
              +			deviceId: '4'
              +		},
              +		'35': {
              +			regexp: /xbox/i,
              +			deviceId: '5'
              +		},
              +		'36': {
              +			regexp: /^Mozilla[\s\S]*Android[\s\S]*OUYA/i,
              +			deviceId: '5'
              +		},
              +		'37': {
              +			regexp: /Opera Tablet/i,
              +			deviceId: '4'
              +		},
              +		'38': {
              +			regexp: /^Mozilla[\s\S]*Android[\s\S]*POV_TV-HDMI[\s\S]* Safari/i,
              +			deviceId: '6'
              +		},
              +		'40': {
              +			regexp: /^Mozilla[\s\S]*Android[\s\S]* Enjoy/i,
              +			deviceId: '4'
              +		},
              +		'41': {
              +			regexp: /^Mozilla[\s\S]*Android[\s\S]*SmartTab/i,
              +			deviceId: '4'
              +		},
              +		'42': {
              +			regexp: /^Mozilla[\s\S]*Android[\s\S]*ViewPad 10/i,
              +			deviceId: '4'
              +		},
              +		'43': {
              +			regexp: /^Mozilla[\s\S]*Android[\s\S]*GT\-N8005|N8010|N8013|N8020/i,
              +			deviceId: '4'
              +		},
              +		'44': {
              +			regexp: /^Mozilla[\s\S]*Android[\s\S]*GT\-P1000|P1010|P3100|P3105|P3110|P3113|P5100|P5110|P5113|P5200|P5210|P6200|P6201|P6210|P6211|P6800|P6810|P7110|P7300|P7310|P7320|P7500|P7510|P7511/i,
              +			deviceId: '4'
              +		},
              +		'45': {
              +			regexp: /^Mozilla[\s\S]*Android[\s\S]*SPH\-P500/i,
              +			deviceId: '4'
              +		},
              +		'46': {
              +			regexp: /^Mozilla[\s\S]*Android[\s\S]*SHW\-M380|M480K|M500|M305/i,
              +			deviceId: '4'
              +		},
              +		'47': {
              +			regexp: /^Mozilla[\s\S]*Android[\s\S]*SHV\-E230|E140/i,
              +			deviceId: '4'
              +		},
              +		'48': {
              +			regexp: /^Mozilla[\s\S]*Android[\s\S]*SGH\-I957M|I497|I467/i,
              +			deviceId: '4'
              +		},
              +		'49': {
              +			regexp: /^Mozilla[\s\S]*Android[\s\S]*SCH\-I925|I915/i,
              +			deviceId: '4'
              +		},
              +		'50': {
              +			regexp: /^Mozilla[\s\S]*Android[\s\S]*PocketBook A10|PocketBook A7/i,
              +			deviceId: '4'
              +		},
              +		'51': {
              +			regexp: /^Mozilla[\s\S]*Android[\s\S]*Obreey SURFpad/i,
              +			deviceId: '4'
              +		},
              +		'52': {
              +			regexp: /^Mozilla[\s\S]*Android[\s\S]*MZ505|MZ601|MZ603|MZ604|MZ605|MZ606|MZ607|MZ608|MZ609|MZ616|MZ617/i,
              +			deviceId: '4'
              +		},
              +		'53': {
              +			regexp: /^Mozilla[\s\S]*Android[\s\S]*Xoom/i,
              +			deviceId: '4'
              +		},
              +		'54': {
              +			regexp: /^Mozilla[\s\S]*Android[\s\S]*IdeaTab|SmartTabII7|Lenovo A1|K1 Build\/K1/i,
              +			deviceId: '4'
              +		},
              +		'55': {
              +			regexp: /^Mozilla[\s\S]*Android[\s\S]*LG\-F200K|F200L|F200S/i,
              +			deviceId: '4'
              +		},
              +		'56': {
              +			regexp: /^Mozilla[\s\S]*Android[\s\S]*HUAWEI MediaPad/i,
              +			deviceId: '4'
              +		},
              +		'57': {
              +			regexp: /^Mozilla[\s\S]*Android[\s\S]*HTC PG09410/i,
              +			deviceId: '4'
              +		},
              +		'58': {
              +			regexp: /^Mozilla[\s\S]*Android[\s\S]*Nexus 10/i,
              +			deviceId: '4'
              +		},
              +		'59': {
              +			regexp: /^Mozilla[\s\S]*Android[\s\S]*L-06C Build/i,
              +			deviceId: '4'
              +		},
              +		'60': {
              +			regexp: /^BlackBerry[0-9]+[\s\S]*Profile\/MIDP/i,
              +			deviceId: '3'
              +		},
              +		'61': {
              +			regexp: /^Mozilla[\s\S]*hp-tablet[\s\S]*hpwOS[\s\S]*TouchPad/i,
              +			deviceId: '4'
              +		},
              +		'62': {
              +			regexp: /^Mozilla[\s\S]*Linux[\s\S]*HbbTV/i,
              +			deviceId: '6'
              +		},
              +		'63': {
              +			regexp: /^Mozilla[\s\S]*Silk[\s\S]*Safari/i,
              +			deviceId: '4'
              +		},
              +		'64': {
              +			regexp: /^Mozilla[\s\S]*Tizen\/[0-9\.]+/i,
              +			deviceId: '3'
              +		},
              +		'65': {
              +			regexp: /^Mozilla[\s\S]*Windows Phone[\s\S]*ARM[\s\S]*NOKIA[\s\S]*Lumia 820/i,
              +			deviceId: '3'
              +		},
              +		'66': {
              +			regexp: /^Mozilla[\s\S]*linux[\s\S]*KFJWI[\s\S]*Silk/i,
              +			deviceId: '4'
              +		},
              +		'67': {
              +			regexp: /^Mozilla[\s\S]*linux[\s\S]*KFSOWI[\s\S]*Silk/i,
              +			deviceId: '4'
              +		},
              +		'68': {
              +			regexp: /^Mozilla[\s\S]*linux[\s\S]*KFTHWI[\s\S]*Silk/i,
              +			deviceId: '4'
              +		},
              +		'69': {
              +			regexp: /^Mozilla[\s\S]*linux[\s\S]*KFTHWA[\s\S]*Silk/i,
              +			deviceId: '4'
              +		},
              +		'70': {
              +			regexp: /^Mozilla[\s\S]*linux[\s\S]*KFAPWI[\s\S]*Silk/i,
              +			deviceId: '4'
              +		},
              +		'71': {
              +			regexp: /^Mozilla[\s\S]*linux[\s\S]*KFAPWA[\s\S]*Silk/i,
              +			deviceId: '4'
              +		},
              +		'72': {
              +			regexp: /^Mozilla[\s\S]*Windows Phone[\s\S]*ARM[\s\S]*NOKIA[\s\S]*Lumia 920/i,
              +			deviceId: '3'
              +		},
              +		'73': {
              +			regexp: /^Mozilla[\s\S]*PalmOS[\s\S]*WebPro[\s\S]*Palm/i,
              +			deviceId: '7'
              +		},
              +		'74': {
              +			regexp: /PalmSource[\s\S]*Blazer/i,
              +			deviceId: '7'
              +		},
              +		'75': {
              +			regexp: /^Mozilla[\s\S]*WebTV[\s\S]*MSIE/i,
              +			deviceId: '6'
              +		},
              +		order: [
              +			'9',
              +			'64',
              +			'65',
              +			'72',
              +			'51',
              +			'52',
              +			'50',
              +			'49',
              +			'47',
              +			'53',
              +			'75',
              +			'46',
              +			'45',
              +			'44',
              +			'43',
              +			'42',
              +			'41',
              +			'40',
              +			'54',
              +			'55',
              +			'74',
              +			'73',
              +			'71',
              +			'70',
              +			'69',
              +			'68',
              +			'66',
              +			'62',
              +			'61',
              +			'59',
              +			'58',
              +			'57',
              +			'56',
              +			'38',
              +			'1',
              +			'23',
              +			'22',
              +			'21',
              +			'10',
              +			'19',
              +			'18',
              +			'17',
              +			'16',
              +			'11',
              +			'15',
              +			'67',
              +			'24',
              +			'25',
              +			'26',
              +			'36',
              +			'34',
              +			'33',
              +			'13',
              +			'48',
              +			'29',
              +			'28',
              +			'27',
              +			'60',
              +			'5',
              +			'3',
              +			'6',
              +			'2',
              +			'12',
              +			'14',
              +			'63',
              +			'20',
              +			'31',
              +			'32',
              +			'37',
              +			'30',
              +			'35'
              +		]
              +	}
              +};
              \ No newline at end of file
              diff --git a/src/js/lib/unzip.js b/src/js/lib/unzip.js
              new file mode 100755
              index 00000000..e046ca93
              --- /dev/null
              +++ b/src/js/lib/unzip.js
              @@ -0,0 +1,31 @@
              +/* zlib.js 2012 - imaya [ https://github.com/imaya/zlib.js ] The MIT License */(function() {'use strict';function m(a){throw a;}var q=void 0,u,aa=this;function v(a,b){var c=a.split("."),d=aa;!(c[0]in d)&&d.execScript&&d.execScript("var "+c[0]);for(var f;c.length&&(f=c.shift());)!c.length&&b!==q?d[f]=b:d=d[f]?d[f]:d[f]={}};var w="undefined"!==typeof Uint8Array&&"undefined"!==typeof Uint16Array&&"undefined"!==typeof Uint32Array&&"undefined"!==typeof DataView;new (w?Uint8Array:Array)(256);var x;for(x=0;256>x;++x)for(var y=x,ba=7,y=y>>>1;y;y>>>=1)--ba;var z=[0,1996959894,3993919788,2567524794,124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,3686517206,2898065728,853044451,1172266101,3705015759,
              +2882616665,651767980,1373503546,3369554304,3218104598,565507253,1454621731,3485111705,3099436303,671266974,1594198024,3322730930,2970347812,795835527,1483230225,3244367275,3060149565,1994146192,31158534,2563907772,4023717930,1907459465,112637215,2680153253,3904427059,2013776290,251722036,2517215374,3775830040,2137656763,141376813,2439277719,3865271297,1802195444,476864866,2238001368,4066508878,1812370925,453092731,2181625025,4111451223,1706088902,314042704,2344532202,4240017532,1658658271,366619977,
              +2362670323,4224994405,1303535960,984961486,2747007092,3569037538,1256170817,1037604311,2765210733,3554079995,1131014506,879679996,2909243462,3663771856,1141124467,855842277,2852801631,3708648649,1342533948,654459306,3188396048,3373015174,1466479909,544179635,3110523913,3462522015,1591671054,702138776,2966460450,3352799412,1504918807,783551873,3082640443,3233442989,3988292384,2596254646,62317068,1957810842,3939845945,2647816111,81470997,1943803523,3814918930,2489596804,225274430,2053790376,3826175755,
              +2466906013,167816743,2097651377,4027552580,2265490386,503444072,1762050814,4150417245,2154129355,426522225,1852507879,4275313526,2312317920,282753626,1742555852,4189708143,2394877945,397917763,1622183637,3604390888,2714866558,953729732,1340076626,3518719985,2797360999,1068828381,1219638859,3624741850,2936675148,906185462,1090812512,3747672003,2825379669,829329135,1181335161,3412177804,3160834842,628085408,1382605366,3423369109,3138078467,570562233,1426400815,3317316542,2998733608,733239954,1555261956,
              +3268935591,3050360625,752459403,1541320221,2607071920,3965973030,1969922972,40735498,2617837225,3943577151,1913087877,83908371,2512341634,3803740692,2075208622,213261112,2463272603,3855990285,2094854071,198958881,2262029012,4057260610,1759359992,534414190,2176718541,4139329115,1873836001,414664567,2282248934,4279200368,1711684554,285281116,2405801727,4167216745,1634467795,376229701,2685067896,3608007406,1308918612,956543938,2808555105,3495958263,1231636301,1047427035,2932959818,3654703836,1088359270,
              +936918E3,2847714899,3736837829,1202900863,817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117],B=w?new Uint32Array(z):z;function C(a){var b=a.length,c=0,d=Number.POSITIVE_INFINITY,f,h,k,e,g,l,p,s,r,A;for(s=0;s<b;++s)a[s]>c&&(c=a[s]),a[s]<d&&(d=a[s]);f=1<<c;h=new (w?Uint32Array:Array)(f);k=1;e=0;for(g=2;k<=c;){for(s=0;s<b;++s)if(a[s]===k){l=0;p=e;for(r=0;r<k;++r)l=l<<1|p&1,p>>=1;A=k<<16|s;for(r=l;r<f;r+=g)h[r]=A;++e}++k;e<<=1;g<<=1}return[h,c,d]};var D=[],E;for(E=0;288>E;E++)switch(!0){case 143>=E:D.push([E+48,8]);break;case 255>=E:D.push([E-144+400,9]);break;case 279>=E:D.push([E-256+0,7]);break;case 287>=E:D.push([E-280+192,8]);break;default:m("invalid literal: "+E)}
              +var ca=function(){function a(a){switch(!0){case 3===a:return[257,a-3,0];case 4===a:return[258,a-4,0];case 5===a:return[259,a-5,0];case 6===a:return[260,a-6,0];case 7===a:return[261,a-7,0];case 8===a:return[262,a-8,0];case 9===a:return[263,a-9,0];case 10===a:return[264,a-10,0];case 12>=a:return[265,a-11,1];case 14>=a:return[266,a-13,1];case 16>=a:return[267,a-15,1];case 18>=a:return[268,a-17,1];case 22>=a:return[269,a-19,2];case 26>=a:return[270,a-23,2];case 30>=a:return[271,a-27,2];case 34>=a:return[272,
              +a-31,2];case 42>=a:return[273,a-35,3];case 50>=a:return[274,a-43,3];case 58>=a:return[275,a-51,3];case 66>=a:return[276,a-59,3];case 82>=a:return[277,a-67,4];case 98>=a:return[278,a-83,4];case 114>=a:return[279,a-99,4];case 130>=a:return[280,a-115,4];case 162>=a:return[281,a-131,5];case 194>=a:return[282,a-163,5];case 226>=a:return[283,a-195,5];case 257>=a:return[284,a-227,5];case 258===a:return[285,a-258,0];default:m("invalid length: "+a)}}var b=[],c,d;for(c=3;258>=c;c++)d=a(c),b[c]=d[2]<<24|d[1]<<
              +16|d[0];return b}();w&&new Uint32Array(ca);function F(a,b){this.l=[];this.m=32768;this.d=this.f=this.c=this.t=0;this.input=w?new Uint8Array(a):a;this.u=!1;this.n=G;this.L=!1;if(b||!(b={}))b.index&&(this.c=b.index),b.bufferSize&&(this.m=b.bufferSize),b.bufferType&&(this.n=b.bufferType),b.resize&&(this.L=b.resize);switch(this.n){case H:this.a=32768;this.b=new (w?Uint8Array:Array)(32768+this.m+258);break;case G:this.a=0;this.b=new (w?Uint8Array:Array)(this.m);this.e=this.X;this.B=this.S;this.q=this.W;break;default:m(Error("invalid inflate mode"))}}
              +var H=0,G=1;
              +F.prototype.r=function(){for(;!this.u;){var a=I(this,3);a&1&&(this.u=!0);a>>>=1;switch(a){case 0:var b=this.input,c=this.c,d=this.b,f=this.a,h=b.length,k=q,e=q,g=d.length,l=q;this.d=this.f=0;c+1>=h&&m(Error("invalid uncompressed block header: LEN"));k=b[c++]|b[c++]<<8;c+1>=h&&m(Error("invalid uncompressed block header: NLEN"));e=b[c++]|b[c++]<<8;k===~e&&m(Error("invalid uncompressed block header: length verify"));c+k>b.length&&m(Error("input buffer is broken"));switch(this.n){case H:for(;f+k>d.length;){l=
              +g-f;k-=l;if(w)d.set(b.subarray(c,c+l),f),f+=l,c+=l;else for(;l--;)d[f++]=b[c++];this.a=f;d=this.e();f=this.a}break;case G:for(;f+k>d.length;)d=this.e({H:2});break;default:m(Error("invalid inflate mode"))}if(w)d.set(b.subarray(c,c+k),f),f+=k,c+=k;else for(;k--;)d[f++]=b[c++];this.c=c;this.a=f;this.b=d;break;case 1:this.q(da,ea);break;case 2:fa(this);break;default:m(Error("unknown BTYPE: "+a))}}return this.B()};
              +var J=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],K=w?new Uint16Array(J):J,L=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,258,258],M=w?new Uint16Array(L):L,ga=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0],O=w?new Uint8Array(ga):ga,ha=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577],ia=w?new Uint16Array(ha):ha,ja=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,
              +12,12,13,13],P=w?new Uint8Array(ja):ja,Q=new (w?Uint8Array:Array)(288),R,la;R=0;for(la=Q.length;R<la;++R)Q[R]=143>=R?8:255>=R?9:279>=R?7:8;var da=C(Q),S=new (w?Uint8Array:Array)(30),T,ma;T=0;for(ma=S.length;T<ma;++T)S[T]=5;var ea=C(S);function I(a,b){for(var c=a.f,d=a.d,f=a.input,h=a.c,k=f.length,e;d<b;)h>=k&&m(Error("input buffer is broken")),c|=f[h++]<<d,d+=8;e=c&(1<<b)-1;a.f=c>>>b;a.d=d-b;a.c=h;return e}
              +function U(a,b){for(var c=a.f,d=a.d,f=a.input,h=a.c,k=f.length,e=b[0],g=b[1],l,p;d<g&&!(h>=k);)c|=f[h++]<<d,d+=8;l=e[c&(1<<g)-1];p=l>>>16;a.f=c>>p;a.d=d-p;a.c=h;return l&65535}
              +function fa(a){function b(a,b,c){var d,e=this.K,f,g;for(g=0;g<a;)switch(d=U(this,b),d){case 16:for(f=3+I(this,2);f--;)c[g++]=e;break;case 17:for(f=3+I(this,3);f--;)c[g++]=0;e=0;break;case 18:for(f=11+I(this,7);f--;)c[g++]=0;e=0;break;default:e=c[g++]=d}this.K=e;return c}var c=I(a,5)+257,d=I(a,5)+1,f=I(a,4)+4,h=new (w?Uint8Array:Array)(K.length),k,e,g,l;for(l=0;l<f;++l)h[K[l]]=I(a,3);if(!w){l=f;for(f=h.length;l<f;++l)h[K[l]]=0}k=C(h);e=new (w?Uint8Array:Array)(c);g=new (w?Uint8Array:Array)(d);a.K=
              +0;a.q(C(b.call(a,c,k,e)),C(b.call(a,d,k,g)))}u=F.prototype;u.q=function(a,b){var c=this.b,d=this.a;this.C=a;for(var f=c.length-258,h,k,e,g;256!==(h=U(this,a));)if(256>h)d>=f&&(this.a=d,c=this.e(),d=this.a),c[d++]=h;else{k=h-257;g=M[k];0<O[k]&&(g+=I(this,O[k]));h=U(this,b);e=ia[h];0<P[h]&&(e+=I(this,P[h]));d>=f&&(this.a=d,c=this.e(),d=this.a);for(;g--;)c[d]=c[d++-e]}for(;8<=this.d;)this.d-=8,this.c--;this.a=d};
              +u.W=function(a,b){var c=this.b,d=this.a;this.C=a;for(var f=c.length,h,k,e,g;256!==(h=U(this,a));)if(256>h)d>=f&&(c=this.e(),f=c.length),c[d++]=h;else{k=h-257;g=M[k];0<O[k]&&(g+=I(this,O[k]));h=U(this,b);e=ia[h];0<P[h]&&(e+=I(this,P[h]));d+g>f&&(c=this.e(),f=c.length);for(;g--;)c[d]=c[d++-e]}for(;8<=this.d;)this.d-=8,this.c--;this.a=d};
              +u.e=function(){var a=new (w?Uint8Array:Array)(this.a-32768),b=this.a-32768,c,d,f=this.b;if(w)a.set(f.subarray(32768,a.length));else{c=0;for(d=a.length;c<d;++c)a[c]=f[c+32768]}this.l.push(a);this.t+=a.length;if(w)f.set(f.subarray(b,b+32768));else for(c=0;32768>c;++c)f[c]=f[b+c];this.a=32768;return f};
              +u.X=function(a){var b,c=this.input.length/this.c+1|0,d,f,h,k=this.input,e=this.b;a&&("number"===typeof a.H&&(c=a.H),"number"===typeof a.Q&&(c+=a.Q));2>c?(d=(k.length-this.c)/this.C[2],h=258*(d/2)|0,f=h<e.length?e.length+h:e.length<<1):f=e.length*c;w?(b=new Uint8Array(f),b.set(e)):b=e;return this.b=b};
              +u.B=function(){var a=0,b=this.b,c=this.l,d,f=new (w?Uint8Array:Array)(this.t+(this.a-32768)),h,k,e,g;if(0===c.length)return w?this.b.subarray(32768,this.a):this.b.slice(32768,this.a);h=0;for(k=c.length;h<k;++h){d=c[h];e=0;for(g=d.length;e<g;++e)f[a++]=d[e]}h=32768;for(k=this.a;h<k;++h)f[a++]=b[h];this.l=[];return this.buffer=f};
              +u.S=function(){var a,b=this.a;w?this.L?(a=new Uint8Array(b),a.set(this.b.subarray(0,b))):a=this.b.subarray(0,b):(this.b.length>b&&(this.b.length=b),a=this.b);return this.buffer=a};function V(a){a=a||{};this.files=[];this.v=a.comment}V.prototype.M=function(a){this.j=a};V.prototype.s=function(a){var b=a[2]&65535|2;return b*(b^1)>>8&255};V.prototype.k=function(a,b){a[0]=(B[(a[0]^b)&255]^a[0]>>>8)>>>0;a[1]=(6681*(20173*(a[1]+(a[0]&255))>>>0)>>>0)+1>>>0;a[2]=(B[(a[2]^a[1]>>>24)&255]^a[2]>>>8)>>>0};V.prototype.U=function(a){var b=[305419896,591751049,878082192],c,d;w&&(b=new Uint32Array(b));c=0;for(d=a.length;c<d;++c)this.k(b,a[c]&255);return b};function W(a,b){b=b||{};this.input=w&&a instanceof Array?new Uint8Array(a):a;this.c=0;this.ca=b.verify||!1;this.j=b.password}var na={P:0,N:8},X=[80,75,1,2],Y=[80,75,3,4],Z=[80,75,5,6];function oa(a,b){this.input=a;this.offset=b}
              +oa.prototype.parse=function(){var a=this.input,b=this.offset;(a[b++]!==X[0]||a[b++]!==X[1]||a[b++]!==X[2]||a[b++]!==X[3])&&m(Error("invalid file header signature"));this.version=a[b++];this.ja=a[b++];this.$=a[b++]|a[b++]<<8;this.I=a[b++]|a[b++]<<8;this.A=a[b++]|a[b++]<<8;this.time=a[b++]|a[b++]<<8;this.V=a[b++]|a[b++]<<8;this.p=(a[b++]|a[b++]<<8|a[b++]<<16|a[b++]<<24)>>>0;this.z=(a[b++]|a[b++]<<8|a[b++]<<16|a[b++]<<24)>>>0;this.J=(a[b++]|a[b++]<<8|a[b++]<<16|a[b++]<<24)>>>0;this.h=a[b++]|a[b++]<<
              +8;this.g=a[b++]|a[b++]<<8;this.F=a[b++]|a[b++]<<8;this.fa=a[b++]|a[b++]<<8;this.ha=a[b++]|a[b++]<<8;this.ga=a[b++]|a[b++]<<8|a[b++]<<16|a[b++]<<24;this.aa=(a[b++]|a[b++]<<8|a[b++]<<16|a[b++]<<24)>>>0;this.filename=String.fromCharCode.apply(null,w?a.subarray(b,b+=this.h):a.slice(b,b+=this.h));this.Y=w?a.subarray(b,b+=this.g):a.slice(b,b+=this.g);this.v=w?a.subarray(b,b+this.F):a.slice(b,b+this.F);this.length=b-this.offset};function pa(a,b){this.input=a;this.offset=b}var qa={O:1,da:8,ea:2048};
              +pa.prototype.parse=function(){var a=this.input,b=this.offset;(a[b++]!==Y[0]||a[b++]!==Y[1]||a[b++]!==Y[2]||a[b++]!==Y[3])&&m(Error("invalid local file header signature"));this.$=a[b++]|a[b++]<<8;this.I=a[b++]|a[b++]<<8;this.A=a[b++]|a[b++]<<8;this.time=a[b++]|a[b++]<<8;this.V=a[b++]|a[b++]<<8;this.p=(a[b++]|a[b++]<<8|a[b++]<<16|a[b++]<<24)>>>0;this.z=(a[b++]|a[b++]<<8|a[b++]<<16|a[b++]<<24)>>>0;this.J=(a[b++]|a[b++]<<8|a[b++]<<16|a[b++]<<24)>>>0;this.h=a[b++]|a[b++]<<8;this.g=a[b++]|a[b++]<<8;this.filename=
              +String.fromCharCode.apply(null,w?a.subarray(b,b+=this.h):a.slice(b,b+=this.h));this.Y=w?a.subarray(b,b+=this.g):a.slice(b,b+=this.g);this.length=b-this.offset};
              +function $(a){var b=[],c={},d,f,h,k;if(!a.i){if(a.o===q){var e=a.input,g;if(!a.D)a:{var l=a.input,p;for(p=l.length-12;0<p;--p)if(l[p]===Z[0]&&l[p+1]===Z[1]&&l[p+2]===Z[2]&&l[p+3]===Z[3]){a.D=p;break a}m(Error("End of Central Directory Record not found"))}g=a.D;(e[g++]!==Z[0]||e[g++]!==Z[1]||e[g++]!==Z[2]||e[g++]!==Z[3])&&m(Error("invalid signature"));a.ia=e[g++]|e[g++]<<8;a.ka=e[g++]|e[g++]<<8;a.la=e[g++]|e[g++]<<8;a.ba=e[g++]|e[g++]<<8;a.R=(e[g++]|e[g++]<<8|e[g++]<<16|e[g++]<<24)>>>0;a.o=(e[g++]|
              +e[g++]<<8|e[g++]<<16|e[g++]<<24)>>>0;a.w=e[g++]|e[g++]<<8;a.v=w?e.subarray(g,g+a.w):e.slice(g,g+a.w)}d=a.o;h=0;for(k=a.ba;h<k;++h)f=new oa(a.input,d),f.parse(),d+=f.length,b[h]=f,c[f.filename]=h;a.R<d-a.o&&m(Error("invalid file header size"));a.i=b;a.G=c}}u=W.prototype;u.Z=function(){var a=[],b,c,d;this.i||$(this);d=this.i;b=0;for(c=d.length;b<c;++b)a[b]=d[b].filename;return a};
              +u.r=function(a,b){var c;this.G||$(this);c=this.G[a];c===q&&m(Error(a+" not found"));var d;d=b||{};var f=this.input,h=this.i,k,e,g,l,p,s,r,A;h||$(this);h[c]===q&&m(Error("wrong index"));e=h[c].aa;k=new pa(this.input,e);k.parse();e+=k.length;g=k.z;if(0!==(k.I&qa.O)){!d.password&&!this.j&&m(Error("please set password"));s=this.T(d.password||this.j);r=e;for(A=e+12;r<A;++r)ra(this,s,f[r]);e+=12;g-=12;r=e;for(A=e+g;r<A;++r)f[r]=ra(this,s,f[r])}switch(k.A){case na.P:l=w?this.input.subarray(e,e+g):this.input.slice(e,
              +e+g);break;case na.N:l=(new F(this.input,{index:e,bufferSize:k.J})).r();break;default:m(Error("unknown compression type"))}if(this.ca){var t=q,n,N="number"===typeof t?t:t=0,ka=l.length;n=-1;for(N=ka&7;N--;++t)n=n>>>8^B[(n^l[t])&255];for(N=ka>>3;N--;t+=8)n=n>>>8^B[(n^l[t])&255],n=n>>>8^B[(n^l[t+1])&255],n=n>>>8^B[(n^l[t+2])&255],n=n>>>8^B[(n^l[t+3])&255],n=n>>>8^B[(n^l[t+4])&255],n=n>>>8^B[(n^l[t+5])&255],n=n>>>8^B[(n^l[t+6])&255],n=n>>>8^B[(n^l[t+7])&255];p=(n^4294967295)>>>0;k.p!==p&&m(Error("wrong crc: file=0x"+
              +k.p.toString(16)+", data=0x"+p.toString(16)))}return l};u.M=function(a){this.j=a};function ra(a,b,c){c^=a.s(b);a.k(b,c);return c}u.k=V.prototype.k;u.T=V.prototype.U;u.s=V.prototype.s;v("Zlib.Unzip",W);v("Zlib.Unzip.prototype.decompress",W.prototype.r);v("Zlib.Unzip.prototype.getFilenames",W.prototype.Z);v("Zlib.Unzip.prototype.setPassword",W.prototype.M);}).call(this);
              diff --git a/src/js/lib/vkbeautify.js b/src/js/lib/vkbeautify.js
              new file mode 100755
              index 00000000..fc2cb135
              --- /dev/null
              +++ b/src/js/lib/vkbeautify.js
              @@ -0,0 +1,360 @@
              +/** @license
              +========================================================================
              +  vkBeautify - javascript plugin to pretty-print or minify text in XML, JSON, CSS and SQL formats.
              +   
              +  Version - 0.99.00.beta 
              +  Copyright (c) 2012 Vadim Kiryukhin
              +  vkiryukhin @ gmail.com
              +  http://www.eslinstructor.net/vkbeautify/
              +  
              +  Dual licensed under the MIT and GPL licenses:
              +    http://www.opensource.org/licenses/mit-license.php
              +    http://www.gnu.org/licenses/gpl.html
              +*/
              +
              +/*
              +*   Pretty print
              +*
              +*        vkbeautify.xml(text [,indent_pattern]);
              +*        vkbeautify.json(text [,indent_pattern]);
              +*        vkbeautify.css(text [,indent_pattern]);
              +*        vkbeautify.sql(text [,indent_pattern]);
              +*
              +*        @text - String; text to beatufy;
              +*        @indent_pattern - Integer | String;
              +*                Integer:  number of white spaces;
              +*                String:   character string to visualize indentation ( can also be a set of white spaces )
              +*   Minify
              +*
              +*        vkbeautify.xmlmin(text [,preserve_comments]);
              +*        vkbeautify.jsonmin(text);
              +*        vkbeautify.cssmin(text [,preserve_comments]);
              +*        vkbeautify.sqlmin(text);
              +*
              +*        @text - String; text to minify;
              +*        @preserve_comments - Bool; [optional];
              +*                Set this flag to true to prevent removing comments from @text ( minxml and mincss functions only. )
              +*
              +*   Examples:
              +*        vkbeautify.xml(text); // pretty print XML
              +*        vkbeautify.json(text, 4 ); // pretty print JSON
              +*        vkbeautify.css(text, '. . . .'); // pretty print CSS
              +*        vkbeautify.sql(text, '----'); // pretty print SQL
              +*
              +*        vkbeautify.xmlmin(text, true);// minify XML, preserve comments
              +*        vkbeautify.jsonmin(text);// minify JSON
              +*        vkbeautify.cssmin(text);// minify CSS, remove comments ( default )
              +*        vkbeautify.sqlmin(text);// minify SQL
              +*
              +*/
              +
              +(function() {
              +
              +function createShiftArr(step) {
              +
              +	var space = '    ';
              +	
              +	if ( isNaN(parseInt(step)) ) {  // argument is string
              +		space = step;
              +	} else { // argument is integer
              +		switch(step) {
              +			case 1: space = ' '; break;
              +			case 2: space = '  '; break;
              +			case 3: space = '   '; break;
              +			case 4: space = '    '; break;
              +			case 5: space = '     '; break;
              +			case 6: space = '      '; break;
              +			case 7: space = '       '; break;
              +			case 8: space = '        '; break;
              +			case 9: space = '         '; break;
              +			case 10: space = '          '; break;
              +			case 11: space = '           '; break;
              +			case 12: space = '            '; break;
              +		}
              +	}
              +
              +	var shift = ['\n']; // array of shifts
              +	for(var ix=0;ix<100;ix++){
              +		shift.push(shift[ix]+space); 
              +	}
              +	return shift;
              +}
              +
              +function vkbeautify(){
              +	this.step = '    '; // 4 spaces
              +	this.shift = createShiftArr(this.step);
              +};
              +
              +vkbeautify.prototype.xml = function(text,step) {
              +
              +	var ar = text.replace(/>\s{0,}</g,"><")
              +				 .replace(/</g,"~::~<")
              +				 .replace(/\s*xmlns\:/g,"~::~xmlns:")
              +				 .replace(/\s*xmlns\=/g,"~::~xmlns=")
              +				 .split('~::~'),
              +		len = ar.length,
              +		inComment = false,
              +		deep = 0,
              +		str = '',
              +		ix = 0,
              +		shift = step ? createShiftArr(step) : this.shift;
              +
              +		for(ix=0;ix<len;ix++) {
              +			// start comment or <![CDATA[...]]> or <!DOCTYPE //
              +			if(ar[ix].search(/<!/) > -1) { 
              +				str += shift[deep]+ar[ix];
              +				inComment = true; 
              +				// end comment  or <![CDATA[...]]> //
              +				if(ar[ix].search(/-->/) > -1 || ar[ix].search(/\]>/) > -1 || ar[ix].search(/!DOCTYPE/) > -1 ) { 
              +					inComment = false; 
              +				}
              +			} else 
              +			// end comment  or <![CDATA[...]]> //
              +			if(ar[ix].search(/-->/) > -1 || ar[ix].search(/\]>/) > -1) { 
              +				str += ar[ix];
              +				inComment = false; 
              +			} else 
              +			// <elm></elm> //
              +			if( /^<\w/.exec(ar[ix-1]) && /^<\/\w/.exec(ar[ix]) &&
              +				/^<[\w:\-\.\,]+/.exec(ar[ix-1]) == /^<\/[\w:\-\.\,]+/.exec(ar[ix])[0].replace('/','')) { 
              +				str += ar[ix];
              +				if(!inComment) deep--;
              +			} else
              +			 // <elm> //
              +			if(ar[ix].search(/<\w/) > -1 && ar[ix].search(/<\//) == -1 && ar[ix].search(/\/>/) == -1 ) {
              +				str = !inComment ? str += shift[deep++]+ar[ix] : str += ar[ix];
              +			} else 
              +			 // <elm>...</elm> //
              +			if(ar[ix].search(/<\w/) > -1 && ar[ix].search(/<\//) > -1) {
              +				str = !inComment ? str += shift[deep]+ar[ix] : str += ar[ix];
              +			} else 
              +			// </elm> //
              +			if(ar[ix].search(/<\//) > -1) { 
              +				str = !inComment ? str += shift[--deep]+ar[ix] : str += ar[ix];
              +			} else 
              +			// <elm/> //
              +			if(ar[ix].search(/\/>/) > -1 ) { 
              +				str = !inComment ? str += shift[deep]+ar[ix] : str += ar[ix];
              +			} else 
              +			// <? xml ... ?> //
              +			if(ar[ix].search(/<\?/) > -1) { 
              +				str += shift[deep]+ar[ix];
              +			} else 
              +			// xmlns //
              +			if( ar[ix].search(/xmlns\:/) > -1  || ar[ix].search(/xmlns\=/) > -1) { 
              +				str += shift[deep]+ar[ix];
              +			} 
              +			
              +			else {
              +				str += ar[ix];
              +			}
              +		}
              +		
              +	return  (str[0] == '\n') ? str.slice(1) : str;
              +}
              +
              +vkbeautify.prototype.json = function(text,step) {
              +
              +	var step = step ? step : this.step;
              +	
              +	if (typeof JSON === 'undefined' ) return text; 
              +	
              +	if ( typeof text === "string" ) return JSON.stringify(JSON.parse(text), null, step);
              +	if ( typeof text === "object" ) return JSON.stringify(text, null, step);
              +		
              +	return text; // text is not string nor object
              +}
              +
              +vkbeautify.prototype.css = function(text, step) {
              +
              +	var ar = text.replace(/\s{1,}/g,' ')
              +				.replace(/\{/g,"{~::~")
              +				.replace(/\}/g,"~::~}~::~")
              +				.replace(/\;/g,";~::~")
              +				.replace(/\/\*/g,"~::~/*")
              +				.replace(/\*\//g,"*/~::~")
              +				.replace(/~::~\s{0,}~::~/g,"~::~")
              +				.split('~::~'),
              +		len = ar.length,
              +		deep = 0,
              +		str = '',
              +		ix = 0,
              +		shift = step ? createShiftArr(step) : this.shift;
              +		
              +		for(ix=0;ix<len;ix++) {
              +
              +			if( /\{/.exec(ar[ix]))  { 
              +				str += shift[deep++]+ar[ix];
              +			} else 
              +			if( /\}/.exec(ar[ix]))  { 
              +				str += shift[--deep]+ar[ix];
              +			} else
              +			if( /\*\\/.exec(ar[ix]))  { 
              +				str += shift[deep]+ar[ix];
              +			}
              +			else {
              +				str += shift[deep]+ar[ix];
              +			}
              +		}
              +		return str.replace(/^\n{1,}/,'');
              +}
              +
              +//----------------------------------------------------------------------------
              +
              +function isSubquery(str, parenthesisLevel) {
              +	return  parenthesisLevel - (str.replace(/\(/g,'').length - str.replace(/\)/g,'').length )
              +}
              +
              +function split_sql(str, tab) {
              +
              +	return str.replace(/\s{1,}/g," ")
              +
              +				.replace(/ AND /ig,"~::~"+tab+tab+"AND ")
              +				.replace(/ BETWEEN /ig,"~::~"+tab+"BETWEEN ")
              +				.replace(/ CASE /ig,"~::~"+tab+"CASE ")
              +				.replace(/ ELSE /ig,"~::~"+tab+"ELSE ")
              +				.replace(/ END /ig,"~::~"+tab+"END ")
              +				.replace(/ FROM /ig,"~::~FROM ")
              +				.replace(/ GROUP\s{1,}BY/ig,"~::~GROUP BY ")
              +				.replace(/ HAVING /ig,"~::~HAVING ")
              +				//.replace(/ SET /ig," SET~::~")
              +				.replace(/ IN /ig," IN ")
              +				
              +				.replace(/ JOIN /ig,"~::~JOIN ")
              +				.replace(/ CROSS~::~{1,}JOIN /ig,"~::~CROSS JOIN ")
              +				.replace(/ INNER~::~{1,}JOIN /ig,"~::~INNER JOIN ")
              +				.replace(/ LEFT~::~{1,}JOIN /ig,"~::~LEFT JOIN ")
              +				.replace(/ RIGHT~::~{1,}JOIN /ig,"~::~RIGHT JOIN ")
              +				
              +				.replace(/ ON /ig,"~::~"+tab+"ON ")
              +				.replace(/ OR /ig,"~::~"+tab+tab+"OR ")
              +				.replace(/ ORDER\s{1,}BY/ig,"~::~ORDER BY ")
              +				.replace(/ OVER /ig,"~::~"+tab+"OVER ")
              +
              +				.replace(/\(\s{0,}SELECT /ig,"~::~(SELECT ")
              +				.replace(/\)\s{0,}SELECT /ig,")~::~SELECT ")
              +				
              +				.replace(/ THEN /ig," THEN~::~"+tab+"")
              +				.replace(/ UNION /ig,"~::~UNION~::~")
              +				.replace(/ USING /ig,"~::~USING ")
              +				.replace(/ WHEN /ig,"~::~"+tab+"WHEN ")
              +				.replace(/ WHERE /ig,"~::~WHERE ")
              +				.replace(/ WITH /ig,"~::~WITH ")
              +				
              +				//.replace(/\,\s{0,}\(/ig,",~::~( ")
              +				//.replace(/\,/ig,",~::~"+tab+tab+"")
              +
              +				.replace(/ ALL /ig," ALL ")
              +				.replace(/ AS /ig," AS ")
              +				.replace(/ ASC /ig," ASC ")	
              +				.replace(/ DESC /ig," DESC ")	
              +				.replace(/ DISTINCT /ig," DISTINCT ")
              +				.replace(/ EXISTS /ig," EXISTS ")
              +				.replace(/ NOT /ig," NOT ")
              +				.replace(/ NULL /ig," NULL ")
              +				.replace(/ LIKE /ig," LIKE ")
              +				.replace(/\s{0,}SELECT /ig,"SELECT ")
              +				.replace(/\s{0,}UPDATE /ig,"UPDATE ")
              +				.replace(/ SET /ig," SET ")
              +							
              +				.replace(/~::~{1,}/g,"~::~")
              +				.split('~::~');
              +}
              +
              +vkbeautify.prototype.sql = function(text,step) {
              +
              +	var ar_by_quote = text.replace(/\s{1,}/g," ")
              +							.replace(/\'/ig,"~::~\'")
              +							.split('~::~'),
              +		len = ar_by_quote.length,
              +		ar = [],
              +		deep = 0,
              +		tab = this.step,//+this.step,
              +		inComment = true,
              +		inQuote = false,
              +		parenthesisLevel = 0,
              +		str = '',
              +		ix = 0,
              +		shift = step ? createShiftArr(step) : this.shift;;
              +
              +		for(ix=0;ix<len;ix++) {
              +			if(ix%2) {
              +				ar = ar.concat(ar_by_quote[ix]);
              +			} else {
              +				ar = ar.concat(split_sql(ar_by_quote[ix], tab) );
              +			}
              +		}
              +		
              +		len = ar.length;
              +		for(ix=0;ix<len;ix++) {
              +			
              +			parenthesisLevel = isSubquery(ar[ix], parenthesisLevel);
              +			
              +			if( /\s{0,}\s{0,}SELECT\s{0,}/.exec(ar[ix]))  { 
              +				ar[ix] = ar[ix].replace(/\,/g,",\n"+tab+tab+"")
              +			} 
              +			
              +			if( /\s{0,}\s{0,}SET\s{0,}/.exec(ar[ix]))  { 
              +				ar[ix] = ar[ix].replace(/\,/g,",\n"+tab+tab+"")
              +			} 
              +			
              +			if( /\s{0,}\(\s{0,}SELECT\s{0,}/.exec(ar[ix]))  { 
              +				deep++;
              +				str += shift[deep]+ar[ix];
              +			} else 
              +			if( /\'/.exec(ar[ix]) )  { 
              +				if(parenthesisLevel<1 && deep) {
              +					deep--;
              +				}
              +				str += ar[ix];
              +			}
              +			else  { 
              +				str += shift[deep]+ar[ix];
              +				if(parenthesisLevel<1 && deep) {
              +					deep--;
              +				}
              +			} 
              +			var junk = 0;
              +		}
              +
              +		str = str.replace(/^\n{1,}/,'').replace(/\n{1,}/g,"\n");
              +		return str;
              +}
              +
              +
              +vkbeautify.prototype.xmlmin = function(text, preserveComments) {
              +
              +	var str = preserveComments ? text
              +							   : text.replace(/\<![ \r\n\t]*(--([^\-]|[\r\n]|-[^\-])*--[ \r\n\t]*)\>/g,"")
              +									 .replace(/[ \r\n\t]{1,}xmlns/g, ' xmlns');
              +	return  str.replace(/>\s{0,}</g,"><"); 
              +}
              +
              +vkbeautify.prototype.jsonmin = function(text) {
              +
              +	if (typeof JSON === 'undefined' ) return text; 
              +	
              +	return JSON.stringify(JSON.parse(text), null, 0); 
              +				
              +}
              +
              +vkbeautify.prototype.cssmin = function(text, preserveComments) {
              +	
              +	var str = preserveComments ? text
              +							   : text.replace(/\/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+\//g,"") ;
              +
              +	return str.replace(/\s{1,}/g,' ')
              +			  .replace(/\{\s{1,}/g,"{")
              +			  .replace(/\}\s{1,}/g,"}")
              +			  .replace(/\;\s{1,}/g,";")
              +			  .replace(/\/\*\s{1,}/g,"/*")
              +			  .replace(/\*\/\s{1,}/g,"*/");
              +}
              +
              +vkbeautify.prototype.sqlmin = function(text) {
              +	return text.replace(/\s{1,}/g," ").replace(/\s{1,}\(/,"(").replace(/\s{1,}\)/,")");
              +}
              +
              +window.vkbeautify = new vkbeautify();
              +
              +})();
              diff --git a/src/js/lib/yahoo.js b/src/js/lib/yahoo.js
              new file mode 100755
              index 00000000..46b0c56c
              --- /dev/null
              +++ b/src/js/lib/yahoo.js
              @@ -0,0 +1,1231 @@
              +/** @license
              +========================================================================
              +  Copyright (c) 2011, Yahoo! Inc. All rights reserved.
              +  Code licensed under the BSD License:
              +  http://developer.yahoo.com/yui/license.html
              +  version: 2.9.0
              +*/
              +/**
              + * The YAHOO object is the single global object used by YUI Library.  It
              + * contains utility function for setting up namespaces, inheritance, and
              + * logging.  YAHOO.util, YAHOO.widget, and YAHOO.example are namespaces
              + * created automatically for and used by the library.
              + * @module yahoo
              + * @title  YAHOO Global
              + */
              +
              +/**
              + * YAHOO_config is not included as part of the library.  Instead it is an
              + * object that can be defined by the implementer immediately before
              + * including the YUI library.  The properties included in this object
              + * will be used to configure global properties needed as soon as the
              + * library begins to load.
              + * @class YAHOO_config
              + * @static
              + */
              +
              +/**
              + * A reference to a function that will be executed every time a YAHOO module
              + * is loaded.  As parameter, this function will receive the version
              + * information for the module. See <a href="YAHOO.env.html#getVersion">
              + * YAHOO.env.getVersion</a> for the description of the version data structure.
              + * @property listener
              + * @type Function
              + * @static
              + * @default undefined
              + */
              +
              +/**
              + * Set to true if the library will be dynamically loaded after window.onload.
              + * Defaults to false
              + * @property injecting
              + * @type boolean
              + * @static
              + * @default undefined
              + */
              +
              +/**
              + * Instructs the yuiloader component to dynamically load yui components and
              + * their dependencies.  See the yuiloader documentation for more information
              + * about dynamic loading
              + * @property load
              + * @static
              + * @default undefined
              + * @see yuiloader
              + */
              +
              +/**
              + * Forces the use of the supplied locale where applicable in the library
              + * @property locale
              + * @type string
              + * @static
              + * @default undefined
              + */
              +
              +var typeof_yahoo = typeof YAHOO;
              +if (typeof_yahoo == "undefined" || !YAHOO) {
              +    /**
              +     * The YAHOO global namespace object.  If YAHOO is already defined, the
              +     * existing YAHOO object will not be overwritten so that defined
              +     * namespaces are preserved.
              +     * @class YAHOO
              +     * @static
              +     */
              +    var YAHOO = {};
              +}
              +
              +/**
              + * Returns the namespace specified and creates it if it doesn't exist
              + * <pre>
              + * YAHOO.namespace("property.package");
              + * YAHOO.namespace("YAHOO.property.package");
              + * </pre>
              + * Either of the above would create YAHOO.property, then
              + * YAHOO.property.package
              + *
              + * Be careful when naming packages. Reserved words may work in some browsers
              + * and not others. For instance, the following will fail in Safari:
              + * <pre>
              + * YAHOO.namespace("really.long.nested.namespace");
              + * </pre>
              + * This fails because "long" is a future reserved word in ECMAScript
              + *
              + * For implementation code that uses YUI, do not create your components
              + * in the namespaces defined by YUI (
              + * <code>YAHOO.util</code>,
              + * <code>YAHOO.widget</code>,
              + * <code>YAHOO.lang</code>,
              + * <code>YAHOO.tool</code>,
              + * <code>YAHOO.example</code>,
              + * <code>YAHOO.env</code>) -- create your own namespace (e.g., 'companyname').
              + *
              + * @method namespace
              + * @static
              + * @param  {String*} arguments 1-n namespaces to create
              + * @return {Object}  A reference to the last namespace object created
              + */
              +YAHOO.namespace = function() {
              +    var a=arguments, o=null, i, j, d;
              +    for (i=0; i<a.length; i=i+1) {
              +        d=(""+a[i]).split(".");
              +        o=YAHOO;
              +
              +        // YAHOO is implied, so it is ignored if it is included
              +        for (j=(d[0] == "YAHOO") ? 1 : 0; j<d.length; j=j+1) {
              +            o[d[j]]=o[d[j]] || {};
              +            o=o[d[j]];
              +        }
              +    }
              +
              +    return o;
              +};
              +
              +/**
              + * Uses YAHOO.widget.Logger to output a log message, if the widget is
              + * available.
              + * Note: LogReader adds the message, category, and source to the DOM as HTML.
              + *
              + * @method log
              + * @static
              + * @param  {HTML}  msg  The message to log.
              + * @param  {HTML}  cat  The log category for the message.  Default
              + *                        categories are "info", "warn", "error", time".
              + *                        Custom categories can be used as well. (opt)
              + * @param  {HTML}  src  The source of the the message (opt)
              + * @return {Boolean}      True if the log operation was successful.
              + */
              +YAHOO.log = function(msg, cat, src) {
              +    var l=YAHOO.widget.Logger;
              +    if(l && l.log) {
              +        return l.log(msg, cat, src);
              +    } else {
              +        return false;
              +    }
              +};
              +
              +/**
              + * Registers a module with the YAHOO object
              + * @method register
              + * @static
              + * @param {String}   name    the name of the module (event, slider, etc)
              + * @param {Function} mainClass a reference to class in the module.  This
              + *                             class will be tagged with the version info
              + *                             so that it will be possible to identify the
              + *                             version that is in use when multiple versions
              + *                             have loaded
              + * @param {Object}   data      metadata object for the module.  Currently it
              + *                             is expected to contain a "version" property
              + *                             and a "build" property at minimum.
              + */
              +YAHOO.register = function(name, mainClass, data) {
              +    var mods = YAHOO.env.modules, m, v, b, ls, i;
              +
              +    if (!mods[name]) {
              +        mods[name] = {
              +            versions:[],
              +            builds:[]
              +        };
              +    }
              +
              +    m  = mods[name];
              +    v  = data.version;
              +    b  = data.build;
              +    ls = YAHOO.env.listeners;
              +
              +    m.name = name;
              +    m.version = v;
              +    m.build = b;
              +    m.versions.push(v);
              +    m.builds.push(b);
              +    m.mainClass = mainClass;
              +
              +    // fire the module load listeners
              +    for (i=0;i<ls.length;i=i+1) {
              +        ls[i](m);
              +    }
              +    // label the main class
              +    if (mainClass) {
              +        mainClass.VERSION = v;
              +        mainClass.BUILD = b;
              +    } else {
              +        YAHOO.log("mainClass is undefined for module " + name, "warn");
              +    }
              +};
              +
              +/**
              + * YAHOO.env is used to keep track of what is known about the YUI library and
              + * the browsing environment
              + * @class YAHOO.env
              + * @static
              + */
              +YAHOO.env = YAHOO.env || {
              +
              +    /**
              +     * Keeps the version info for all YUI modules that have reported themselves
              +     * @property modules
              +     * @type Object[]
              +     */
              +    modules: [],
              +
              +    /**
              +     * List of functions that should be executed every time a YUI module
              +     * reports itself.
              +     * @property listeners
              +     * @type Function[]
              +     */
              +    listeners: []
              +};
              +
              +/**
              + * Returns the version data for the specified module:
              + *      <dl>
              + *      <dt>name:</dt>      <dd>The name of the module</dd>
              + *      <dt>version:</dt>   <dd>The version in use</dd>
              + *      <dt>build:</dt>     <dd>The build number in use</dd>
              + *      <dt>versions:</dt>  <dd>All versions that were registered</dd>
              + *      <dt>builds:</dt>    <dd>All builds that were registered.</dd>
              + *      <dt>mainClass:</dt> <dd>An object that was was stamped with the
              + *                 current version and build. If
              + *                 mainClass.VERSION != version or mainClass.BUILD != build,
              + *                 multiple versions of pieces of the library have been
              + *                 loaded, potentially causing issues.</dd>
              + *       </dl>
              + *
              + * @method getVersion
              + * @static
              + * @param {String}  name the name of the module (event, slider, etc)
              + * @return {Object} The version info
              + */
              +YAHOO.env.getVersion = function(name) {
              +    return YAHOO.env.modules[name] || null;
              +};
              +
              +/**
              + * Do not fork for a browser if it can be avoided.  Use feature detection when
              + * you can.  Use the user agent as a last resort.  YAHOO.env.ua stores a version
              + * number for the browser engine, 0 otherwise.  This value may or may not map
              + * to the version number of the browser using the engine.  The value is
              + * presented as a float so that it can easily be used for boolean evaluation
              + * as well as for looking for a particular range of versions.  Because of this,
              + * some of the granularity of the version info may be lost (e.g., Gecko 1.8.0.9
              + * reports 1.8).
              + * @class YAHOO.env.ua
              + * @static
              + */
              +
              +/**
              + * parses a user agent string (or looks for one in navigator to parse if
              + * not supplied).
              + * @method parseUA
              + * @since 2.9.0
              + * @static
              + */
              +YAHOO.env.parseUA = function(agent) {
              +
              +        var numberify = function(s) {
              +            var c = 0;
              +            return parseFloat(s.replace(/\./g, function() {
              +                return (c++ == 1) ? '' : '.';
              +            }));
              +        },
              +
              +        nav = navigator,
              +
              +        o = {
              +
              +        /**
              +         * Internet Explorer version number or 0.  Example: 6
              +         * @property ie
              +         * @type float
              +         * @static
              +         */
              +        ie: 0,
              +
              +        /**
              +         * Opera version number or 0.  Example: 9.2
              +         * @property opera
              +         * @type float
              +         * @static
              +         */
              +        opera: 0,
              +
              +        /**
              +         * Gecko engine revision number.  Will evaluate to 1 if Gecko
              +         * is detected but the revision could not be found. Other browsers
              +         * will be 0.  Example: 1.8
              +         * <pre>
              +         * Firefox 1.0.0.4: 1.7.8   <-- Reports 1.7
              +         * Firefox 1.5.0.9: 1.8.0.9 <-- 1.8
              +         * Firefox 2.0.0.3: 1.8.1.3 <-- 1.81
              +         * Firefox 3.0   <-- 1.9
              +         * Firefox 3.5   <-- 1.91
              +         * </pre>
              +         * @property gecko
              +         * @type float
              +         * @static
              +         */
              +        gecko: 0,
              +
              +        /**
              +         * AppleWebKit version.  KHTML browsers that are not WebKit browsers
              +         * will evaluate to 1, other browsers 0.  Example: 418.9
              +         * <pre>
              +         * Safari 1.3.2 (312.6): 312.8.1 <-- Reports 312.8 -- currently the
              +         *                                   latest available for Mac OSX 10.3.
              +         * Safari 2.0.2:         416     <-- hasOwnProperty introduced
              +         * Safari 2.0.4:         418     <-- preventDefault fixed
              +         * Safari 2.0.4 (419.3): 418.9.1 <-- One version of Safari may run
              +         *                                   different versions of webkit
              +         * Safari 2.0.4 (419.3): 419     <-- Tiger installations that have been
              +         *                                   updated, but not updated
              +         *                                   to the latest patch.
              +         * Webkit 212 nightly:   522+    <-- Safari 3.0 precursor (with native
              +         * SVG and many major issues fixed).
              +         * Safari 3.0.4 (523.12) 523.12  <-- First Tiger release - automatic
              +         * update from 2.x via the 10.4.11 OS patch.
              +         * Webkit nightly 1/2008:525+    <-- Supports DOMContentLoaded event.
              +         *                                   yahoo.com user agent hack removed.
              +         * </pre>
              +         * http://en.wikipedia.org/wiki/Safari_version_history
              +         * @property webkit
              +         * @type float
              +         * @static
              +         */
              +        webkit: 0,
              +
              +        /**
              +         * Chrome will be detected as webkit, but this property will also
              +         * be populated with the Chrome version number
              +         * @property chrome
              +         * @type float
              +         * @static
              +         */
              +        chrome: 0,
              +
              +        /**
              +         * The mobile property will be set to a string containing any relevant
              +         * user agent information when a modern mobile browser is detected.
              +         * Currently limited to Safari on the iPhone/iPod Touch, Nokia N-series
              +         * devices with the WebKit-based browser, and Opera Mini.
              +         * @property mobile
              +         * @type string
              +         * @static
              +         */
              +        mobile: null,
              +
              +        /**
              +         * Adobe AIR version number or 0.  Only populated if webkit is detected.
              +         * Example: 1.0
              +         * @property air
              +         * @type float
              +         */
              +        air: 0,
              +        /**
              +         * Detects Apple iPad's OS version
              +         * @property ipad
              +         * @type float
              +         * @static
              +         */
              +        ipad: 0,
              +        /**
              +         * Detects Apple iPhone's OS version
              +         * @property iphone
              +         * @type float
              +         * @static
              +         */
              +        iphone: 0,
              +        /**
              +         * Detects Apples iPod's OS version
              +         * @property ipod
              +         * @type float
              +         * @static
              +         */
              +        ipod: 0,
              +        /**
              +         * General truthy check for iPad, iPhone or iPod
              +         * @property ios
              +         * @type float
              +         * @static
              +         */
              +        ios: null,
              +        /**
              +         * Detects Googles Android OS version
              +         * @property android
              +         * @type float
              +         * @static
              +         */
              +        android: 0,
              +        /**
              +         * Detects Palms WebOS version
              +         * @property webos
              +         * @type float
              +         * @static
              +         */
              +        webos: 0,
              +
              +        /**
              +         * Google Caja version number or 0.
              +         * @property caja
              +         * @type float
              +         */
              +        caja: nav && nav.cajaVersion,
              +
              +        /**
              +         * Set to true if the page appears to be in SSL
              +         * @property secure
              +         * @type boolean
              +         * @static
              +         */
              +        secure: false,
              +
              +        /**
              +         * The operating system.  Currently only detecting windows or macintosh
              +         * @property os
              +         * @type string
              +         * @static
              +         */
              +        os: null
              +
              +    },
              +
              +    ua = agent || (navigator && navigator.userAgent),
              +
              +    loc = window && window.location,
              +
              +    href = loc && loc.href,
              +
              +    m;
              +
              +    o.secure = href && (href.toLowerCase().indexOf("https") === 0);
              +
              +    if (ua) {
              +
              +        if ((/windows|win32/i).test(ua)) {
              +            o.os = 'windows';
              +        } else if ((/macintosh/i).test(ua)) {
              +            o.os = 'macintosh';
              +        } else if ((/rhino/i).test(ua)) {
              +            o.os = 'rhino';
              +        }
              +
              +        // Modern KHTML browsers should qualify as Safari X-Grade
              +        if ((/KHTML/).test(ua)) {
              +            o.webkit = 1;
              +        }
              +        // Modern WebKit browsers are at least X-Grade
              +        m = ua.match(/AppleWebKit\/([^\s]*)/);
              +        if (m && m[1]) {
              +            o.webkit = numberify(m[1]);
              +
              +            // Mobile browser check
              +            if (/ Mobile\//.test(ua)) {
              +                o.mobile = 'Apple'; // iPhone or iPod Touch
              +
              +                m = ua.match(/OS ([^\s]*)/);
              +                if (m && m[1]) {
              +                    m = numberify(m[1].replace('_', '.'));
              +                }
              +                o.ios = m;
              +                o.ipad = o.ipod = o.iphone = 0;
              +
              +                m = ua.match(/iPad|iPod|iPhone/);
              +                if (m && m[0]) {
              +                    o[m[0].toLowerCase()] = o.ios;
              +                }
              +            } else {
              +                m = ua.match(/NokiaN[^\/]*|Android \d\.\d|webOS\/\d\.\d/);
              +                if (m) {
              +                    // Nokia N-series, Android, webOS, ex: NokiaN95
              +                    o.mobile = m[0];
              +                }
              +                if (/webOS/.test(ua)) {
              +                    o.mobile = 'WebOS';
              +                    m = ua.match(/webOS\/([^\s]*);/);
              +                    if (m && m[1]) {
              +                        o.webos = numberify(m[1]);
              +                    }
              +                }
              +                if (/ Android/.test(ua)) {
              +                    o.mobile = 'Android';
              +                    m = ua.match(/Android ([^\s]*);/);
              +                    if (m && m[1]) {
              +                        o.android = numberify(m[1]);
              +                    }
              +
              +                }
              +            }
              +
              +            m = ua.match(/Chrome\/([^\s]*)/);
              +            if (m && m[1]) {
              +                o.chrome = numberify(m[1]); // Chrome
              +            } else {
              +                m = ua.match(/AdobeAIR\/([^\s]*)/);
              +                if (m) {
              +                    o.air = m[0]; // Adobe AIR 1.0 or better
              +                }
              +            }
              +        }
              +
              +        if (!o.webkit) { // not webkit
              +// @todo check Opera/8.01 (J2ME/MIDP; Opera Mini/2.0.4509/1316; fi; U; ssr)
              +            m = ua.match(/Opera[\s\/]([^\s]*)/);
              +            if (m && m[1]) {
              +                o.opera = numberify(m[1]);
              +                m = ua.match(/Version\/([^\s]*)/);
              +                if (m && m[1]) {
              +                    o.opera = numberify(m[1]); // opera 10+
              +                }
              +                m = ua.match(/Opera Mini[^;]*/);
              +                if (m) {
              +                    o.mobile = m[0]; // ex: Opera Mini/2.0.4509/1316
              +                }
              +            } else { // not opera or webkit
              +                m = ua.match(/MSIE\s([^;]*)/);
              +                if (m && m[1]) {
              +                    o.ie = numberify(m[1]);
              +                } else { // not opera, webkit, or ie
              +                    m = ua.match(/Gecko\/([^\s]*)/);
              +                    if (m) {
              +                        o.gecko = 1; // Gecko detected, look for revision
              +                        m = ua.match(/rv:([^\s\)]*)/);
              +                        if (m && m[1]) {
              +                            o.gecko = numberify(m[1]);
              +                        }
              +                    }
              +                }
              +            }
              +        }
              +    }
              +
              +    return o;
              +};
              +
              +YAHOO.env.ua = YAHOO.env.parseUA();
              +
              +/**
              + * Initializes the global by creating the default namespaces and applying
              + * any new configuration information that is detected.  This is the setup
              + * for env.
              + * @method init
              + * @static
              + * @private
              + */
              +(function() {
              +    YAHOO.namespace("util", "widget", "example");
              +    /*global YAHOO_config*/
              +    if ("undefined" !== typeof YAHOO_config) {
              +        var l=YAHOO_config.listener, ls=YAHOO.env.listeners,unique=true, i;
              +        if (l) {
              +            // if YAHOO is loaded multiple times we need to check to see if
              +            // this is a new config object.  If it is, add the new component
              +            // load listener to the stack
              +            for (i=0; i<ls.length; i++) {
              +                if (ls[i] == l) {
              +                    unique = false;
              +                    break;
              +                }
              +            }
              +
              +            if (unique) {
              +                ls.push(l);
              +            }
              +        }
              +    }
              +})();
              +/**
              + * Provides the language utilites and extensions used by the library
              + * @class YAHOO.lang
              + */
              +YAHOO.lang = YAHOO.lang || {};
              +
              +(function() {
              +
              +
              +var L = YAHOO.lang,
              +
              +    OP = Object.prototype,
              +    ARRAY_TOSTRING = '[object Array]',
              +    FUNCTION_TOSTRING = '[object Function]',
              +    OBJECT_TOSTRING = '[object Object]',
              +    NOTHING = [],
              +
              +    HTML_CHARS = {
              +        '&': '&amp;',
              +        '<': '&lt;',
              +        '>': '&gt;',
              +        '"': '&quot;',
              +        "'": '&#x27;',
              +        '/': '&#x2F;',
              +        '`': '&#x60;'
              +    },
              +
              +    // ADD = ["toString", "valueOf", "hasOwnProperty"],
              +    ADD = ["toString", "valueOf"],
              +
              +    OB = {
              +
              +    /**
              +     * Determines wheather or not the provided object is an array.
              +     * @method isArray
              +     * @param {any} o The object being testing
              +     * @return {boolean} the result
              +     */
              +    isArray: function(o) {
              +        return OP.toString.apply(o) === ARRAY_TOSTRING;
              +    },
              +
              +    /**
              +     * Determines whether or not the provided object is a boolean
              +     * @method isBoolean
              +     * @param {any} o The object being testing
              +     * @return {boolean} the result
              +     */
              +    isBoolean: function(o) {
              +        return typeof o === 'boolean';
              +    },
              +
              +    /**
              +     * Determines whether or not the provided object is a function.
              +     * Note: Internet Explorer thinks certain functions are objects:
              +     *
              +     * var obj = document.createElement("object");
              +     * YAHOO.lang.isFunction(obj.getAttribute) // reports false in IE
              +     *
              +     * var input = document.createElement("input"); // append to body
              +     * YAHOO.lang.isFunction(input.focus) // reports false in IE
              +     *
              +     * You will have to implement additional tests if these functions
              +     * matter to you.
              +     *
              +     * @method isFunction
              +     * @param {any} o The object being testing
              +     * @return {boolean} the result
              +     */
              +    isFunction: function(o) {
              +        return (typeof o === 'function') || OP.toString.apply(o) === FUNCTION_TOSTRING;
              +    },
              +
              +    /**
              +     * Determines whether or not the provided object is null
              +     * @method isNull
              +     * @param {any} o The object being testing
              +     * @return {boolean} the result
              +     */
              +    isNull: function(o) {
              +        return o === null;
              +    },
              +
              +    /**
              +     * Determines whether or not the provided object is a legal number
              +     * @method isNumber
              +     * @param {any} o The object being testing
              +     * @return {boolean} the result
              +     */
              +    isNumber: function(o) {
              +        return typeof o === 'number' && isFinite(o);
              +    },
              +
              +    /**
              +     * Determines whether or not the provided object is of type object
              +     * or function
              +     * @method isObject
              +     * @param {any} o The object being testing
              +     * @return {boolean} the result
              +     */
              +    isObject: function(o) {
              +return (o && (typeof o === 'object' || L.isFunction(o))) || false;
              +    },
              +
              +    /**
              +     * Determines whether or not the provided object is a string
              +     * @method isString
              +     * @param {any} o The object being testing
              +     * @return {boolean} the result
              +     */
              +    isString: function(o) {
              +        return typeof o === 'string';
              +    },
              +
              +    /**
              +     * Determines whether or not the provided object is undefined
              +     * @method isUndefined
              +     * @param {any} o The object being testing
              +     * @return {boolean} the result
              +     */
              +    isUndefined: function(o) {
              +        return typeof o === 'undefined';
              +    },
              +
              +
              +    /**
              +     * IE will not enumerate native functions in a derived object even if the
              +     * function was overridden.  This is a workaround for specific functions
              +     * we care about on the Object prototype.
              +     * @property _IEEnumFix
              +     * @param {Function} r  the object to receive the augmentation
              +     * @param {Function} s  the object that supplies the properties to augment
              +     * @static
              +     * @private
              +     */
              +    _IEEnumFix: (YAHOO.env.ua.ie) ? function(r, s) {
              +            var i, fname, f;
              +            for (i=0;i<ADD.length;i=i+1) {
              +
              +                fname = ADD[i];
              +                f = s[fname];
              +
              +                if (L.isFunction(f) && f!=OP[fname]) {
              +                    r[fname]=f;
              +                }
              +            }
              +    } : function(){},
              +
              +    /**
              +     * <p>
              +     * Returns a copy of the specified string with special HTML characters
              +     * escaped. The following characters will be converted to their
              +     * corresponding character entities:
              +     * <code>&amp; &lt; &gt; &quot; &#x27; &#x2F; &#x60;</code>
              +     * </p>
              +     *
              +     * <p>
              +     * This implementation is based on the
              +     * <a href="http://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet">OWASP
              +     * HTML escaping recommendations</a>. In addition to the characters
              +     * in the OWASP recommendation, we also escape the <code>&#x60;</code>
              +     * character, since IE interprets it as an attribute delimiter when used in
              +     * innerHTML.
              +     * </p>
              +     *
              +     * @method escapeHTML
              +     * @param {String} html String to escape.
              +     * @return {String} Escaped string.
              +     * @static
              +     * @since 2.9.0
              +     */
              +    escapeHTML: function (html) {
              +        return html.replace(/[&<>"'\/`]/g, function (match) {
              +            return HTML_CHARS[match];
              +        });
              +    },
              +
              +    /**
              +     * Utility to set up the prototype, constructor and superclass properties to
              +     * support an inheritance strategy that can chain constructors and methods.
              +     * Static members will not be inherited.
              +     *
              +     * @method extend
              +     * @static
              +     * @param {Function} subc   the object to modify
              +     * @param {Function} superc the object to inherit
              +     * @param {Object} overrides  additional properties/methods to add to the
              +     *                              subclass prototype.  These will override the
              +     *                              matching items obtained from the superclass
              +     *                              if present.
              +     */
              +    extend: function(subc, superc, overrides) {
              +        if (!superc||!subc) {
              +            throw new Error("extend failed, please check that " +
              +                            "all dependencies are included.");
              +        }
              +        var F = function() {}, i;
              +        F.prototype=superc.prototype;
              +        subc.prototype=new F();
              +        subc.prototype.constructor=subc;
              +        subc.superclass=superc.prototype;
              +        if (superc.prototype.constructor == OP.constructor) {
              +            superc.prototype.constructor=superc;
              +        }
              +
              +        if (overrides) {
              +            for (i in overrides) {
              +                if (L.hasOwnProperty(overrides, i)) {
              +                    subc.prototype[i]=overrides[i];
              +                }
              +            }
              +
              +            L._IEEnumFix(subc.prototype, overrides);
              +        }
              +    },
              +
              +    /**
              +     * Applies all properties in the supplier to the receiver if the
              +     * receiver does not have these properties yet.  Optionally, one or
              +     * more methods/properties can be specified (as additional
              +     * parameters).  This option will overwrite the property if receiver
              +     * has it already.  If true is passed as the third parameter, all
              +     * properties will be applied and _will_ overwrite properties in
              +     * the receiver.
              +     *
              +     * @method augmentObject
              +     * @static
              +     * @since 2.3.0
              +     * @param {Function} r  the object to receive the augmentation
              +     * @param {Function} s  the object that supplies the properties to augment
              +     * @param {String*|boolean}  arguments zero or more properties methods
              +     *        to augment the receiver with.  If none specified, everything
              +     *        in the supplier will be used unless it would
              +     *        overwrite an existing property in the receiver. If true
              +     *        is specified as the third parameter, all properties will
              +     *        be applied and will overwrite an existing property in
              +     *        the receiver
              +     */
              +    augmentObject: function(r, s) {
              +        if (!s||!r) {
              +            throw new Error("Absorb failed, verify dependencies.");
              +        }
              +        var a=arguments, i, p, overrideList=a[2];
              +        if (overrideList && overrideList!==true) { // only absorb the specified properties
              +            for (i=2; i<a.length; i=i+1) {
              +                r[a[i]] = s[a[i]];
              +            }
              +        } else { // take everything, overwriting only if the third parameter is true
              +            for (p in s) {
              +                if (overrideList || !(p in r)) {
              +                    r[p] = s[p];
              +                }
              +            }
              +
              +            L._IEEnumFix(r, s);
              +        }
              +
              +        return r;
              +    },
              +
              +    /**
              +     * Same as YAHOO.lang.augmentObject, except it only applies prototype properties
              +     * @see YAHOO.lang.augmentObject
              +     * @method augmentProto
              +     * @static
              +     * @param {Function} r  the object to receive the augmentation
              +     * @param {Function} s  the object that supplies the properties to augment
              +     * @param {String*|boolean}  arguments zero or more properties methods
              +     *        to augment the receiver with.  If none specified, everything
              +     *        in the supplier will be used unless it would overwrite an existing
              +     *        property in the receiver.  if true is specified as the third
              +     *        parameter, all properties will be applied and will overwrite an
              +     *        existing property in the receiver
              +     */
              +    augmentProto: function(r, s) {
              +        if (!s||!r) {
              +            throw new Error("Augment failed, verify dependencies.");
              +        }
              +        //var a=[].concat(arguments);
              +        var a=[r.prototype,s.prototype], i;
              +        for (i=2;i<arguments.length;i=i+1) {
              +            a.push(arguments[i]);
              +        }
              +        L.augmentObject.apply(this, a);
              +
              +        return r;
              +    },
              +
              +
              +    /**
              +     * Returns a simple string representation of the object or array.
              +     * Other types of objects will be returned unprocessed.  Arrays
              +     * are expected to be indexed.  Use object notation for
              +     * associative arrays.
              +     * @method dump
              +     * @since 2.3.0
              +     * @param o {Object} The object to dump
              +     * @param d {int} How deep to recurse child objects, default 3
              +     * @return {String} the dump result
              +     */
              +    dump: function(o, d) {
              +        var i,len,s=[],OBJ="{...}",FUN="f(){...}",
              +            COMMA=', ', ARROW=' => ';
              +
              +        // Cast non-objects to string
              +        // Skip dates because the std toString is what we want
              +        // Skip HTMLElement-like objects because trying to dump
              +        // an element will cause an unhandled exception in FF 2.x
              +        if (!L.isObject(o)) {
              +            return o + "";
              +        } else if (o instanceof Date || ("nodeType" in o && "tagName" in o)) {
              +            return o;
              +        } else if  (L.isFunction(o)) {
              +            return FUN;
              +        }
              +
              +        // dig into child objects the depth specifed. Default 3
              +        d = (L.isNumber(d)) ? d : 3;
              +
              +        // arrays [1, 2, 3]
              +        if (L.isArray(o)) {
              +            s.push("[");
              +            for (i=0,len=o.length;i<len;i=i+1) {
              +                if (L.isObject(o[i])) {
              +                    s.push((d > 0) ? L.dump(o[i], d-1) : OBJ);
              +                } else {
              +                    s.push(o[i]);
              +                }
              +                s.push(COMMA);
              +            }
              +            if (s.length > 1) {
              +                s.pop();
              +            }
              +            s.push("]");
              +        // objects {k1 => v1, k2 => v2}
              +        } else {
              +            s.push("{");
              +            for (i in o) {
              +                if (L.hasOwnProperty(o, i)) {
              +                    s.push(i + ARROW);
              +                    if (L.isObject(o[i])) {
              +                        s.push((d > 0) ? L.dump(o[i], d-1) : OBJ);
              +                    } else {
              +                        s.push(o[i]);
              +                    }
              +                    s.push(COMMA);
              +                }
              +            }
              +            if (s.length > 1) {
              +                s.pop();
              +            }
              +            s.push("}");
              +        }
              +
              +        return s.join("");
              +    },
              +
              +    /**
              +     * Does variable substitution on a string. It scans through the string
              +     * looking for expressions enclosed in { } braces. If an expression
              +     * is found, it is used a key on the object.  If there is a space in
              +     * the key, the first word is used for the key and the rest is provided
              +     * to an optional function to be used to programatically determine the
              +     * value (the extra information might be used for this decision). If
              +     * the value for the key in the object, or what is returned from the
              +     * function has a string value, number value, or object value, it is
              +     * substituted for the bracket expression and it repeats.  If this
              +     * value is an object, it uses the Object's toString() if this has
              +     * been overridden, otherwise it does a shallow dump of the key/value
              +     * pairs.
              +     *
              +     * By specifying the recurse option, the string is rescanned after
              +     * every replacement, allowing for nested template substitutions.
              +     * The side effect of this option is that curly braces in the
              +     * replacement content must be encoded.
              +     *
              +     * @method substitute
              +     * @since 2.3.0
              +     * @param s {String} The string that will be modified.
              +     * @param o {Object} An object containing the replacement values
              +     * @param f {Function} An optional function that can be used to
              +     *                     process each match.  It receives the key,
              +     *                     value, and any extra metadata included with
              +     *                     the key inside of the braces.
              +     * @param recurse {boolean} default true - if not false, the replaced
              +     * string will be rescanned so that nested substitutions are possible.
              +     * @return {String} the substituted string
              +     */
              +    substitute: function (s, o, f, recurse) {
              +        var i, j, k, key, v, meta, saved=[], token, lidx=s.length,
              +            DUMP='dump', SPACE=' ', LBRACE='{', RBRACE='}',
              +            dump, objstr;
              +
              +        for (;;) {
              +            i = s.lastIndexOf(LBRACE, lidx);
              +            if (i < 0) {
              +                break;
              +            }
              +            j = s.indexOf(RBRACE, i);
              +            if (i + 1 > j) {
              +                break;
              +            }
              +
              +            //Extract key and meta info
              +            token = s.substring(i + 1, j);
              +            key = token;
              +            meta = null;
              +            k = key.indexOf(SPACE);
              +            if (k > -1) {
              +                meta = key.substring(k + 1);
              +                key = key.substring(0, k);
              +            }
              +
              +            // lookup the value
              +            v = o[key];
              +
              +            // if a substitution function was provided, execute it
              +            if (f) {
              +                v = f(key, v, meta);
              +            }
              +
              +            if (L.isObject(v)) {
              +                if (L.isArray(v)) {
              +                    v = L.dump(v, parseInt(meta, 10));
              +                } else {
              +                    meta = meta || "";
              +
              +                    // look for the keyword 'dump', if found force obj dump
              +                    dump = meta.indexOf(DUMP);
              +                    if (dump > -1) {
              +                        meta = meta.substring(4);
              +                    }
              +
              +                    objstr = v.toString();
              +
              +                    // use the toString if it is not the Object toString
              +                    // and the 'dump' meta info was not found
              +                    if (objstr === OBJECT_TOSTRING || dump > -1) {
              +                        v = L.dump(v, parseInt(meta, 10));
              +                    } else {
              +                        v = objstr;
              +                    }
              +                }
              +            } else if (!L.isString(v) && !L.isNumber(v)) {
              +                // This {block} has no replace string. Save it for later.
              +                v = "~-" + saved.length + "-~";
              +                saved[saved.length] = token;
              +
              +                // break;
              +            }
              +
              +            s = s.substring(0, i) + v + s.substring(j + 1);
              +
              +            if (recurse === false) {
              +                lidx = i-1;
              +            }
              +
              +        }
              +
              +        // restore saved {block}s
              +        for (i=saved.length-1; i>=0; i=i-1) {
              +            s = s.replace(new RegExp("~-" + i + "-~"), "{"  + saved[i] + "}", "g");
              +        }
              +
              +        return s;
              +    },
              +
              +
              +    /**
              +     * Returns a string without any leading or trailing whitespace.  If
              +     * the input is not a string, the input will be returned untouched.
              +     * @method trim
              +     * @since 2.3.0
              +     * @param s {string} the string to trim
              +     * @return {string} the trimmed string
              +     */
              +    trim: function(s){
              +        try {
              +            return s.replace(/^\s+|\s+$/g, "");
              +        } catch(e) {
              +            return s;
              +        }
              +    },
              +
              +    /**
              +     * Returns a new object containing all of the properties of
              +     * all the supplied objects.  The properties from later objects
              +     * will overwrite those in earlier objects.
              +     * @method merge
              +     * @since 2.3.0
              +     * @param arguments {Object*} the objects to merge
              +     * @return the new merged object
              +     */
              +    merge: function() {
              +        var o={}, a=arguments, l=a.length, i;
              +        for (i=0; i<l; i=i+1) {
              +            L.augmentObject(o, a[i], true);
              +        }
              +        return o;
              +    },
              +
              +    /**
              +     * Executes the supplied function in the context of the supplied
              +     * object 'when' milliseconds later.  Executes the function a
              +     * single time unless periodic is set to true.
              +     * @method later
              +     * @since 2.4.0
              +     * @param when {int} the number of milliseconds to wait until the fn
              +     * is executed
              +     * @param o the context object
              +     * @param fn {Function|String} the function to execute or the name of
              +     * the method in the 'o' object to execute
              +     * @param data [Array] data that is provided to the function.  This accepts
              +     * either a single item or an array.  If an array is provided, the
              +     * function is executed with one parameter for each array item.  If
              +     * you need to pass a single array parameter, it needs to be wrapped in
              +     * an array [myarray]
              +     * @param periodic {boolean} if true, executes continuously at supplied
              +     * interval until canceled
              +     * @return a timer object. Call the cancel() method on this object to
              +     * stop the timer.
              +     */
              +    later: function(when, o, fn, data, periodic) {
              +        when = when || 0;
              +        o = o || {};
              +        var m=fn, d=data, f, r;
              +
              +        if (L.isString(fn)) {
              +            m = o[fn];
              +        }
              +
              +        if (!m) {
              +            throw new TypeError("method undefined");
              +        }
              +
              +        if (!L.isUndefined(data) && !L.isArray(d)) {
              +            d = [data];
              +        }
              +
              +        f = function() {
              +            m.apply(o, d || NOTHING);
              +        };
              +
              +        r = (periodic) ? setInterval(f, when) : setTimeout(f, when);
              +
              +        return {
              +            interval: periodic,
              +            cancel: function() {
              +                if (this.interval) {
              +                    clearInterval(r);
              +                } else {
              +                    clearTimeout(r);
              +                }
              +            }
              +        };
              +    },
              +
              +    /**
              +     * A convenience method for detecting a legitimate non-null value.
              +     * Returns false for null/undefined/NaN, true for other values,
              +     * including 0/false/''
              +     * @method isValue
              +     * @since 2.3.0
              +     * @param o {any} the item to test
              +     * @return {boolean} true if it is not null/undefined/NaN || false
              +     */
              +    isValue: function(o) {
              +        // return (o || o === false || o === 0 || o === ''); // Infinity fails
              +return (L.isObject(o) || L.isString(o) || L.isNumber(o) || L.isBoolean(o));
              +    }
              +
              +};
              +
              +/**
              + * Determines whether or not the property was added
              + * to the object instance.  Returns false if the property is not present
              + * in the object, or was inherited from the prototype.
              + * This abstraction is provided to enable hasOwnProperty for Safari 1.3.x.
              + * There is a discrepancy between YAHOO.lang.hasOwnProperty and
              + * Object.prototype.hasOwnProperty when the property is a primitive added to
              + * both the instance AND prototype with the same value:
              + * <pre>
              + * var A = function() {};
              + * A.prototype.foo = 'foo';
              + * var a = new A();
              + * a.foo = 'foo';
              + * alert(a.hasOwnProperty('foo')); // true
              + * alert(YAHOO.lang.hasOwnProperty(a, 'foo')); // false when using fallback
              + * </pre>
              + * @method hasOwnProperty
              + * @param {any} o The object being testing
              + * @param prop {string} the name of the property to test
              + * @return {boolean} the result
              + */
              +L.hasOwnProperty = (OP.hasOwnProperty) ?
              +    function(o, prop) {
              +        return o && o.hasOwnProperty && o.hasOwnProperty(prop);
              +    } : function(o, prop) {
              +        return !L.isUndefined(o[prop]) &&
              +                o.constructor.prototype[prop] !== o[prop];
              +    };
              +
              +// new lang wins
              +OB.augmentObject(L, OB, true);
              +
              +/**
              + * An alias for <a href="YAHOO.lang.html">YAHOO.lang</a>
              + * @class YAHOO.util.Lang
              + */
              +YAHOO.util.Lang = L;
              +
              +/**
              + * Same as YAHOO.lang.augmentObject, except it only applies prototype
              + * properties.  This is an alias for augmentProto.
              + * @see YAHOO.lang.augmentObject
              + * @method augment
              + * @static
              + * @param {Function} r  the object to receive the augmentation
              + * @param {Function} s  the object that supplies the properties to augment
              + * @param {String*|boolean}  arguments zero or more properties methods to
              + *        augment the receiver with.  If none specified, everything
              + *        in the supplier will be used unless it would
              + *        overwrite an existing property in the receiver.  if true
              + *        is specified as the third parameter, all properties will
              + *        be applied and will overwrite an existing property in
              + *        the receiver
              + */
              +L.augment = L.augmentProto;
              +
              +/**
              + * An alias for <a href="YAHOO.lang.html#augment">YAHOO.lang.augment</a>
              + * @for YAHOO
              + * @method augment
              + * @static
              + * @param {Function} r  the object to receive the augmentation
              + * @param {Function} s  the object that supplies the properties to augment
              + * @param {String*}  arguments zero or more properties methods to
              + *        augment the receiver with.  If none specified, everything
              + *        in the supplier will be used unless it would
              + *        overwrite an existing property in the receiver
              + */
              +YAHOO.augment = L.augmentProto;
              +
              +/**
              + * An alias for <a href="YAHOO.lang.html#extend">YAHOO.lang.extend</a>
              + * @method extend
              + * @static
              + * @param {Function} subc   the object to modify
              + * @param {Function} superc the object to inherit
              + * @param {Object} overrides  additional properties/methods to add to the
              + *        subclass prototype.  These will override the
              + *        matching items obtained from the superclass if present.
              + */
              +YAHOO.extend = L.extend;
              +
              +})();
              +YAHOO.register("yahoo", YAHOO, {version: "2.9.0", build: "2800"});
              diff --git a/src/js/lib/zip.js b/src/js/lib/zip.js
              new file mode 100755
              index 00000000..1f8ee76c
              --- /dev/null
              +++ b/src/js/lib/zip.js
              @@ -0,0 +1,37 @@
              +/* zlib.js 2012 - imaya [ https://github.com/imaya/zlib.js ] The MIT License */(function() {'use strict';var n=void 0,y=!0,aa=this;function G(e,b){var a=e.split("."),d=aa;!(a[0]in d)&&d.execScript&&d.execScript("var "+a[0]);for(var c;a.length&&(c=a.shift());)!a.length&&b!==n?d[c]=b:d=d[c]?d[c]:d[c]={}};var H="undefined"!==typeof Uint8Array&&"undefined"!==typeof Uint16Array&&"undefined"!==typeof Uint32Array&&"undefined"!==typeof DataView;function ba(e,b){this.index="number"===typeof b?b:0;this.f=0;this.buffer=e instanceof(H?Uint8Array:Array)?e:new (H?Uint8Array:Array)(32768);if(2*this.buffer.length<=this.index)throw Error("invalid index");this.buffer.length<=this.index&&ca(this)}function ca(e){var b=e.buffer,a,d=b.length,c=new (H?Uint8Array:Array)(d<<1);if(H)c.set(b);else for(a=0;a<d;++a)c[a]=b[a];return e.buffer=c}
              +ba.prototype.b=function(e,b,a){var d=this.buffer,c=this.index,f=this.f,l=d[c],p;a&&1<b&&(e=8<b?(L[e&255]<<24|L[e>>>8&255]<<16|L[e>>>16&255]<<8|L[e>>>24&255])>>32-b:L[e]>>8-b);if(8>b+f)l=l<<b|e,f+=b;else for(p=0;p<b;++p)l=l<<1|e>>b-p-1&1,8===++f&&(f=0,d[c++]=L[l],l=0,c===d.length&&(d=ca(this)));d[c]=l;this.buffer=d;this.f=f;this.index=c};ba.prototype.finish=function(){var e=this.buffer,b=this.index,a;0<this.f&&(e[b]<<=8-this.f,e[b]=L[e[b]],b++);H?a=e.subarray(0,b):(e.length=b,a=e);return a};
              +var da=new (H?Uint8Array:Array)(256),ha;for(ha=0;256>ha;++ha){for(var U=ha,ja=U,ka=7,U=U>>>1;U;U>>>=1)ja<<=1,ja|=U&1,--ka;da[ha]=(ja<<ka&255)>>>0}var L=da;function la(e){var b=n,a,d="number"===typeof b?b:b=0,c=e.length;a=-1;for(d=c&7;d--;++b)a=a>>>8^V[(a^e[b])&255];for(d=c>>3;d--;b+=8)a=a>>>8^V[(a^e[b])&255],a=a>>>8^V[(a^e[b+1])&255],a=a>>>8^V[(a^e[b+2])&255],a=a>>>8^V[(a^e[b+3])&255],a=a>>>8^V[(a^e[b+4])&255],a=a>>>8^V[(a^e[b+5])&255],a=a>>>8^V[(a^e[b+6])&255],a=a>>>8^V[(a^e[b+7])&255];return(a^4294967295)>>>0}
              +var ma=[0,1996959894,3993919788,2567524794,124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,3686517206,2898065728,853044451,1172266101,3705015759,
              +2882616665,651767980,1373503546,3369554304,3218104598,565507253,1454621731,3485111705,3099436303,671266974,1594198024,3322730930,2970347812,795835527,1483230225,3244367275,3060149565,1994146192,31158534,2563907772,4023717930,1907459465,112637215,2680153253,3904427059,2013776290,251722036,2517215374,3775830040,2137656763,141376813,2439277719,3865271297,1802195444,476864866,2238001368,4066508878,1812370925,453092731,2181625025,4111451223,1706088902,314042704,2344532202,4240017532,1658658271,366619977,
              +2362670323,4224994405,1303535960,984961486,2747007092,3569037538,1256170817,1037604311,2765210733,3554079995,1131014506,879679996,2909243462,3663771856,1141124467,855842277,2852801631,3708648649,1342533948,654459306,3188396048,3373015174,1466479909,544179635,3110523913,3462522015,1591671054,702138776,2966460450,3352799412,1504918807,783551873,3082640443,3233442989,3988292384,2596254646,62317068,1957810842,3939845945,2647816111,81470997,1943803523,3814918930,2489596804,225274430,2053790376,3826175755,
              +2466906013,167816743,2097651377,4027552580,2265490386,503444072,1762050814,4150417245,2154129355,426522225,1852507879,4275313526,2312317920,282753626,1742555852,4189708143,2394877945,397917763,1622183637,3604390888,2714866558,953729732,1340076626,3518719985,2797360999,1068828381,1219638859,3624741850,2936675148,906185462,1090812512,3747672003,2825379669,829329135,1181335161,3412177804,3160834842,628085408,1382605366,3423369109,3138078467,570562233,1426400815,3317316542,2998733608,733239954,1555261956,
              +3268935591,3050360625,752459403,1541320221,2607071920,3965973030,1969922972,40735498,2617837225,3943577151,1913087877,83908371,2512341634,3803740692,2075208622,213261112,2463272603,3855990285,2094854071,198958881,2262029012,4057260610,1759359992,534414190,2176718541,4139329115,1873836001,414664567,2282248934,4279200368,1711684554,285281116,2405801727,4167216745,1634467795,376229701,2685067896,3608007406,1308918612,956543938,2808555105,3495958263,1231636301,1047427035,2932959818,3654703836,1088359270,
              +936918E3,2847714899,3736837829,1202900863,817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117],V=H?new Uint32Array(ma):ma;function na(e){this.buffer=new (H?Uint16Array:Array)(2*e);this.length=0}na.prototype.getParent=function(e){return 2*((e-2)/4|0)};na.prototype.push=function(e,b){var a,d,c=this.buffer,f;a=this.length;c[this.length++]=b;for(c[this.length++]=e;0<a;)if(d=this.getParent(a),c[a]>c[d])f=c[a],c[a]=c[d],c[d]=f,f=c[a+1],c[a+1]=c[d+1],c[d+1]=f,a=d;else break;return this.length};
              +na.prototype.pop=function(){var e,b,a=this.buffer,d,c,f;b=a[0];e=a[1];this.length-=2;a[0]=a[this.length];a[1]=a[this.length+1];for(f=0;;){c=2*f+2;if(c>=this.length)break;c+2<this.length&&a[c+2]>a[c]&&(c+=2);if(a[c]>a[f])d=a[f],a[f]=a[c],a[c]=d,d=a[f+1],a[f+1]=a[c+1],a[c+1]=d;else break;f=c}return{index:e,value:b,length:this.length}};function pa(e,b){this.k=qa;this.l=0;this.input=H&&e instanceof Array?new Uint8Array(e):e;this.e=0;b&&(b.lazy&&(this.l=b.lazy),"number"===typeof b.compressionType&&(this.k=b.compressionType),b.outputBuffer&&(this.c=H&&b.outputBuffer instanceof Array?new Uint8Array(b.outputBuffer):b.outputBuffer),"number"===typeof b.outputIndex&&(this.e=b.outputIndex));this.c||(this.c=new (H?Uint8Array:Array)(32768))}var qa=2,sa=[],Y;
              +for(Y=0;288>Y;Y++)switch(y){case 143>=Y:sa.push([Y+48,8]);break;case 255>=Y:sa.push([Y-144+400,9]);break;case 279>=Y:sa.push([Y-256+0,7]);break;case 287>=Y:sa.push([Y-280+192,8]);break;default:throw"invalid literal: "+Y;}
              +pa.prototype.g=function(){var e,b,a,d,c=this.input;switch(this.k){case 0:a=0;for(d=c.length;a<d;){b=H?c.subarray(a,a+65535):c.slice(a,a+65535);a+=b.length;var f=b,l=a===d,p=n,k=n,q=n,w=n,u=n,m=this.c,h=this.e;if(H){for(m=new Uint8Array(this.c.buffer);m.length<=h+f.length+5;)m=new Uint8Array(m.length<<1);m.set(this.c)}p=l?1:0;m[h++]=p|0;k=f.length;q=~k+65536&65535;m[h++]=k&255;m[h++]=k>>>8&255;m[h++]=q&255;m[h++]=q>>>8&255;if(H)m.set(f,h),h+=f.length,m=m.subarray(0,h);else{w=0;for(u=f.length;w<u;++w)m[h++]=
              +f[w];m.length=h}this.e=h;this.c=m}break;case 1:var s=new ba(H?new Uint8Array(this.c.buffer):this.c,this.e);s.b(1,1,y);s.b(1,2,y);var t=ta(this,c),r,Q,z;r=0;for(Q=t.length;r<Q;r++)if(z=t[r],ba.prototype.b.apply(s,sa[z]),256<z)s.b(t[++r],t[++r],y),s.b(t[++r],5),s.b(t[++r],t[++r],y);else if(256===z)break;this.c=s.finish();this.e=this.c.length;break;case qa:var A=new ba(H?new Uint8Array(this.c.buffer):this.c,this.e),F,I,N,B,C,g=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],J,ea,O,W,X,oa=Array(19),
              +ya,Z,ia,D,za;F=qa;A.b(1,1,y);A.b(F,2,y);I=ta(this,c);J=ua(this.p,15);ea=va(J);O=ua(this.o,7);W=va(O);for(N=286;257<N&&0===J[N-1];N--);for(B=30;1<B&&0===O[B-1];B--);var Aa=N,Ba=B,P=new (H?Uint32Array:Array)(Aa+Ba),v,R,x,fa,M=new (H?Uint32Array:Array)(316),K,E,S=new (H?Uint8Array:Array)(19);for(v=R=0;v<Aa;v++)P[R++]=J[v];for(v=0;v<Ba;v++)P[R++]=O[v];if(!H){v=0;for(fa=S.length;v<fa;++v)S[v]=0}v=K=0;for(fa=P.length;v<fa;v+=R){for(R=1;v+R<fa&&P[v+R]===P[v];++R);x=R;if(0===P[v])if(3>x)for(;0<x--;)M[K++]=
              +0,S[0]++;else for(;0<x;)E=138>x?x:138,E>x-3&&E<x&&(E=x-3),10>=E?(M[K++]=17,M[K++]=E-3,S[17]++):(M[K++]=18,M[K++]=E-11,S[18]++),x-=E;else if(M[K++]=P[v],S[P[v]]++,x--,3>x)for(;0<x--;)M[K++]=P[v],S[P[v]]++;else for(;0<x;)E=6>x?x:6,E>x-3&&E<x&&(E=x-3),M[K++]=16,M[K++]=E-3,S[16]++,x-=E}e=H?M.subarray(0,K):M.slice(0,K);X=ua(S,7);for(D=0;19>D;D++)oa[D]=X[g[D]];for(C=19;4<C&&0===oa[C-1];C--);ya=va(X);A.b(N-257,5,y);A.b(B-1,5,y);A.b(C-4,4,y);for(D=0;D<C;D++)A.b(oa[D],3,y);D=0;for(za=e.length;D<za;D++)if(Z=
              +e[D],A.b(ya[Z],X[Z],y),16<=Z){D++;switch(Z){case 16:ia=2;break;case 17:ia=3;break;case 18:ia=7;break;default:throw"invalid code: "+Z;}A.b(e[D],ia,y)}var Ca=[ea,J],Da=[W,O],T,Ea,ga,ra,Fa,Ga,Ha,Ia;Fa=Ca[0];Ga=Ca[1];Ha=Da[0];Ia=Da[1];T=0;for(Ea=I.length;T<Ea;++T)if(ga=I[T],A.b(Fa[ga],Ga[ga],y),256<ga)A.b(I[++T],I[++T],y),ra=I[++T],A.b(Ha[ra],Ia[ra],y),A.b(I[++T],I[++T],y);else if(256===ga)break;this.c=A.finish();this.e=this.c.length;break;default:throw"invalid compression type";}return this.c};
              +function wa(e,b){this.length=e;this.n=b}
              +var xa=function(){function e(a){switch(y){case 3===a:return[257,a-3,0];case 4===a:return[258,a-4,0];case 5===a:return[259,a-5,0];case 6===a:return[260,a-6,0];case 7===a:return[261,a-7,0];case 8===a:return[262,a-8,0];case 9===a:return[263,a-9,0];case 10===a:return[264,a-10,0];case 12>=a:return[265,a-11,1];case 14>=a:return[266,a-13,1];case 16>=a:return[267,a-15,1];case 18>=a:return[268,a-17,1];case 22>=a:return[269,a-19,2];case 26>=a:return[270,a-23,2];case 30>=a:return[271,a-27,2];case 34>=a:return[272,
              +a-31,2];case 42>=a:return[273,a-35,3];case 50>=a:return[274,a-43,3];case 58>=a:return[275,a-51,3];case 66>=a:return[276,a-59,3];case 82>=a:return[277,a-67,4];case 98>=a:return[278,a-83,4];case 114>=a:return[279,a-99,4];case 130>=a:return[280,a-115,4];case 162>=a:return[281,a-131,5];case 194>=a:return[282,a-163,5];case 226>=a:return[283,a-195,5];case 257>=a:return[284,a-227,5];case 258===a:return[285,a-258,0];default:throw"invalid length: "+a;}}var b=[],a,d;for(a=3;258>=a;a++)d=e(a),b[a]=d[2]<<24|
              +d[1]<<16|d[0];return b}(),Ja=H?new Uint32Array(xa):xa;
              +function ta(e,b){function a(a,c){var b=a.n,d=[],e=0,f;f=Ja[a.length];d[e++]=f&65535;d[e++]=f>>16&255;d[e++]=f>>24;var g;switch(y){case 1===b:g=[0,b-1,0];break;case 2===b:g=[1,b-2,0];break;case 3===b:g=[2,b-3,0];break;case 4===b:g=[3,b-4,0];break;case 6>=b:g=[4,b-5,1];break;case 8>=b:g=[5,b-7,1];break;case 12>=b:g=[6,b-9,2];break;case 16>=b:g=[7,b-13,2];break;case 24>=b:g=[8,b-17,3];break;case 32>=b:g=[9,b-25,3];break;case 48>=b:g=[10,b-33,4];break;case 64>=b:g=[11,b-49,4];break;case 96>=b:g=[12,b-
              +65,5];break;case 128>=b:g=[13,b-97,5];break;case 192>=b:g=[14,b-129,6];break;case 256>=b:g=[15,b-193,6];break;case 384>=b:g=[16,b-257,7];break;case 512>=b:g=[17,b-385,7];break;case 768>=b:g=[18,b-513,8];break;case 1024>=b:g=[19,b-769,8];break;case 1536>=b:g=[20,b-1025,9];break;case 2048>=b:g=[21,b-1537,9];break;case 3072>=b:g=[22,b-2049,10];break;case 4096>=b:g=[23,b-3073,10];break;case 6144>=b:g=[24,b-4097,11];break;case 8192>=b:g=[25,b-6145,11];break;case 12288>=b:g=[26,b-8193,12];break;case 16384>=
              +b:g=[27,b-12289,12];break;case 24576>=b:g=[28,b-16385,13];break;case 32768>=b:g=[29,b-24577,13];break;default:throw"invalid distance";}f=g;d[e++]=f[0];d[e++]=f[1];d[e++]=f[2];var k,l;k=0;for(l=d.length;k<l;++k)m[h++]=d[k];t[d[0]]++;r[d[3]]++;s=a.length+c-1;u=null}var d,c,f,l,p,k={},q,w,u,m=H?new Uint16Array(2*b.length):[],h=0,s=0,t=new (H?Uint32Array:Array)(286),r=new (H?Uint32Array:Array)(30),Q=e.l,z;if(!H){for(f=0;285>=f;)t[f++]=0;for(f=0;29>=f;)r[f++]=0}t[256]=1;d=0;for(c=b.length;d<c;++d){f=p=
              +0;for(l=3;f<l&&d+f!==c;++f)p=p<<8|b[d+f];k[p]===n&&(k[p]=[]);q=k[p];if(!(0<s--)){for(;0<q.length&&32768<d-q[0];)q.shift();if(d+3>=c){u&&a(u,-1);f=0;for(l=c-d;f<l;++f)z=b[d+f],m[h++]=z,++t[z];break}0<q.length?(w=Ka(b,d,q),u?u.length<w.length?(z=b[d-1],m[h++]=z,++t[z],a(w,0)):a(u,-1):w.length<Q?u=w:a(w,0)):u?a(u,-1):(z=b[d],m[h++]=z,++t[z])}q.push(d)}m[h++]=256;t[256]++;e.p=t;e.o=r;return H?m.subarray(0,h):m}
              +function Ka(e,b,a){var d,c,f=0,l,p,k,q,w=e.length;p=0;q=a.length;a:for(;p<q;p++){d=a[q-p-1];l=3;if(3<f){for(k=f;3<k;k--)if(e[d+k-1]!==e[b+k-1])continue a;l=f}for(;258>l&&b+l<w&&e[d+l]===e[b+l];)++l;l>f&&(c=d,f=l);if(258===l)break}return new wa(f,b-c)}
              +function ua(e,b){var a=e.length,d=new na(572),c=new (H?Uint8Array:Array)(a),f,l,p,k,q;if(!H)for(k=0;k<a;k++)c[k]=0;for(k=0;k<a;++k)0<e[k]&&d.push(k,e[k]);f=Array(d.length/2);l=new (H?Uint32Array:Array)(d.length/2);if(1===f.length)return c[d.pop().index]=1,c;k=0;for(q=d.length/2;k<q;++k)f[k]=d.pop(),l[k]=f[k].value;p=La(l,l.length,b);k=0;for(q=f.length;k<q;++k)c[f[k].index]=p[k];return c}
              +function La(e,b,a){function d(a){var c=k[a][q[a]];c===b?(d(a+1),d(a+1)):--l[c];++q[a]}var c=new (H?Uint16Array:Array)(a),f=new (H?Uint8Array:Array)(a),l=new (H?Uint8Array:Array)(b),p=Array(a),k=Array(a),q=Array(a),w=(1<<a)-b,u=1<<a-1,m,h,s,t,r;c[a-1]=b;for(h=0;h<a;++h)w<u?f[h]=0:(f[h]=1,w-=u),w<<=1,c[a-2-h]=(c[a-1-h]/2|0)+b;c[0]=f[0];p[0]=Array(c[0]);k[0]=Array(c[0]);for(h=1;h<a;++h)c[h]>2*c[h-1]+f[h]&&(c[h]=2*c[h-1]+f[h]),p[h]=Array(c[h]),k[h]=Array(c[h]);for(m=0;m<b;++m)l[m]=a;for(s=0;s<c[a-1];++s)p[a-
              +1][s]=e[s],k[a-1][s]=s;for(m=0;m<a;++m)q[m]=0;1===f[a-1]&&(--l[0],++q[a-1]);for(h=a-2;0<=h;--h){t=m=0;r=q[h+1];for(s=0;s<c[h];s++)t=p[h+1][r]+p[h+1][r+1],t>e[m]?(p[h][s]=t,k[h][s]=b,r+=2):(p[h][s]=e[m],k[h][s]=m,++m);q[h]=0;1===f[h]&&d(h)}return l}
              +function va(e){var b=new (H?Uint16Array:Array)(e.length),a=[],d=[],c=0,f,l,p,k;f=0;for(l=e.length;f<l;f++)a[e[f]]=(a[e[f]]|0)+1;f=1;for(l=16;f<=l;f++)d[f]=c,c+=a[f]|0,c<<=1;f=0;for(l=e.length;f<l;f++){c=d[e[f]];d[e[f]]+=1;p=b[f]=0;for(k=e[f];p<k;p++)b[f]=b[f]<<1|c&1,c>>>=1}return b};function $(e){e=e||{};this.files=[];this.d=e.comment}var Ma=[80,75,1,2],Na=[80,75,3,4],Oa=[80,75,5,6];$.prototype.m=function(e,b){b=b||{};var a,d=e.length,c=0;H&&e instanceof Array&&(e=new Uint8Array(e));"number"!==typeof b.compressionMethod&&(b.compressionMethod=8);if(b.compress)switch(b.compressionMethod){case 0:break;case 8:c=la(e);e=(new pa(e,b.deflateOption)).g();a=y;break;default:throw Error("unknown compression method:"+b.compressionMethod);}this.files.push({buffer:e,a:b,j:a,r:!1,size:d,h:c})};
              +$.prototype.q=function(e){this.i=e};
              +$.prototype.g=function(){var e=this.files,b,a,d,c,f,l=0,p=0,k,q,w,u,m,h,s,t,r,Q,z,A,F,I,N,B,C,g,J;B=0;for(C=e.length;B<C;++B){b=e[B];t=b.a.filename?b.a.filename.length:0;r=b.a.comment?b.a.comment.length:0;if(!b.j)switch(b.h=la(b.buffer),b.a.compressionMethod){case 0:break;case 8:b.buffer=(new pa(b.buffer,b.a.deflateOption)).g();b.j=y;break;default:throw Error("unknown compression method:"+b.a.compressionMethod);}if(b.a.password!==n||this.i!==n){var ea=b.a.password||this.i,O=[305419896,591751049,878082192],
              +W=n,X=n;H&&(O=new Uint32Array(O));W=0;for(X=ea.length;W<X;++W)Pa(O,ea[W]&255);N=O;F=b.buffer;H?(I=new Uint8Array(F.length+12),I.set(F,12),F=I):F.unshift(0,0,0,0,0,0,0,0,0,0,0,0);for(g=0;12>g;++g)F[g]=Qa(N,11===B?b.h&255:256*Math.random()|0);for(J=F.length;g<J;++g)F[g]=Qa(N,F[g]);b.buffer=F}l+=30+t+b.buffer.length;p+=46+t+r}a=new (H?Uint8Array:Array)(l+p+(46+(this.d?this.d.length:0)));d=0;c=l;f=c+p;B=0;for(C=e.length;B<C;++B){b=e[B];t=b.a.filename?b.a.filename.length:0;r=b.a.comment?b.a.comment.length:
              +0;k=d;a[d++]=Na[0];a[d++]=Na[1];a[d++]=Na[2];a[d++]=Na[3];a[c++]=Ma[0];a[c++]=Ma[1];a[c++]=Ma[2];a[c++]=Ma[3];a[c++]=20;a[c++]=b.a.os||0;a[d++]=a[c++]=20;q=a[d++]=a[c++]=0;if(b.a.password||this.i)q|=1;a[d++]=a[c++]=q&255;a[d++]=a[c++]=q>>8&255;w=b.a.compressionMethod;a[d++]=a[c++]=w&255;a[d++]=a[c++]=w>>8&255;u=b.a.date||new Date;a[d++]=a[c++]=(u.getMinutes()&7)<<5|u.getSeconds()/2|0;a[d++]=a[c++]=u.getHours()<<3|u.getMinutes()>>3;a[d++]=a[c++]=(u.getMonth()+1&7)<<5|u.getDate();a[d++]=a[c++]=(u.getFullYear()-
              +1980&127)<<1|u.getMonth()+1>>3;m=b.h;a[d++]=a[c++]=m&255;a[d++]=a[c++]=m>>8&255;a[d++]=a[c++]=m>>16&255;a[d++]=a[c++]=m>>24&255;h=b.buffer.length;a[d++]=a[c++]=h&255;a[d++]=a[c++]=h>>8&255;a[d++]=a[c++]=h>>16&255;a[d++]=a[c++]=h>>24&255;s=b.size;a[d++]=a[c++]=s&255;a[d++]=a[c++]=s>>8&255;a[d++]=a[c++]=s>>16&255;a[d++]=a[c++]=s>>24&255;a[d++]=a[c++]=t&255;a[d++]=a[c++]=t>>8&255;a[d++]=a[c++]=0;a[d++]=a[c++]=0;a[c++]=r&255;a[c++]=r>>8&255;a[c++]=0;a[c++]=0;a[c++]=0;a[c++]=0;a[c++]=0;a[c++]=0;a[c++]=
              +0;a[c++]=0;a[c++]=k&255;a[c++]=k>>8&255;a[c++]=k>>16&255;a[c++]=k>>24&255;if(Q=b.a.filename)if(H)a.set(Q,d),a.set(Q,c),d+=t,c+=t;else for(g=0;g<t;++g)a[d++]=a[c++]=Q[g];if(z=b.a.extraField)if(H)a.set(z,d),a.set(z,c),d+=0,c+=0;else for(g=0;g<r;++g)a[d++]=a[c++]=z[g];if(A=b.a.comment)if(H)a.set(A,c),c+=r;else for(g=0;g<r;++g)a[c++]=A[g];if(H)a.set(b.buffer,d),d+=b.buffer.length;else{g=0;for(J=b.buffer.length;g<J;++g)a[d++]=b.buffer[g]}}a[f++]=Oa[0];a[f++]=Oa[1];a[f++]=Oa[2];a[f++]=Oa[3];a[f++]=0;a[f++]=
              +0;a[f++]=0;a[f++]=0;a[f++]=C&255;a[f++]=C>>8&255;a[f++]=C&255;a[f++]=C>>8&255;a[f++]=p&255;a[f++]=p>>8&255;a[f++]=p>>16&255;a[f++]=p>>24&255;a[f++]=l&255;a[f++]=l>>8&255;a[f++]=l>>16&255;a[f++]=l>>24&255;r=this.d?this.d.length:0;a[f++]=r&255;a[f++]=r>>8&255;if(this.d)if(H)a.set(this.d,f);else{g=0;for(J=r;g<J;++g)a[f++]=this.d[g]}return a};function Qa(e,b){var a,d=e[2]&65535|2;a=d*(d^1)>>8&255;Pa(e,b);return a^b}
              +function Pa(e,b){e[0]=(V[(e[0]^b)&255]^e[0]>>>8)>>>0;e[1]=(6681*(20173*(e[1]+(e[0]&255))>>>0)>>>0)+1>>>0;e[2]=(V[(e[2]^e[1]>>>24)&255]^e[2]>>>8)>>>0};function Ra(e,b){var a,d,c,f;if(Object.keys)a=Object.keys(b);else for(d in a=[],c=0,b)a[c++]=d;c=0;for(f=a.length;c<f;++c)d=a[c],G(e+"."+d,b[d])};G("Zlib.Zip",$);G("Zlib.Zip.prototype.addFile",$.prototype.m);G("Zlib.Zip.prototype.compress",$.prototype.g);G("Zlib.Zip.prototype.setPassword",$.prototype.q);Ra("Zlib.Zip.CompressionMethod",{STORE:0,DEFLATE:8});Ra("Zlib.Zip.OperatingSystem",{MSDOS:0,UNIX:3,MACINTOSH:7});}).call(this);
              diff --git a/src/js/lib/zlib_and_gzip.js b/src/js/lib/zlib_and_gzip.js
              new file mode 100755
              index 00000000..70840ec8
              --- /dev/null
              +++ b/src/js/lib/zlib_and_gzip.js
              @@ -0,0 +1,55 @@
              +/** @license
              +========================================================================
              +  zlib.js 2012 - imaya [ https://github.com/imaya/zlib.js ] The MIT License
              +*/
              +(function() {'use strict';function q(b){throw b;}var t=void 0,u=!0,aa=this;function A(b,a){var c=b.split("."),d=aa;!(c[0]in d)&&d.execScript&&d.execScript("var "+c[0]);for(var e;c.length&&(e=c.shift());)!c.length&&a!==t?d[e]=a:d=d[e]?d[e]:d[e]={}};var B="undefined"!==typeof Uint8Array&&"undefined"!==typeof Uint16Array&&"undefined"!==typeof Uint32Array&&"undefined"!==typeof DataView;function F(b,a){this.index="number"===typeof a?a:0;this.m=0;this.buffer=b instanceof(B?Uint8Array:Array)?b:new (B?Uint8Array:Array)(32768);2*this.buffer.length<=this.index&&q(Error("invalid index"));this.buffer.length<=this.index&&this.f()}F.prototype.f=function(){var b=this.buffer,a,c=b.length,d=new (B?Uint8Array:Array)(c<<1);if(B)d.set(b);else for(a=0;a<c;++a)d[a]=b[a];return this.buffer=d};
              +F.prototype.d=function(b,a,c){var d=this.buffer,e=this.index,f=this.m,g=d[e],k;c&&1<a&&(b=8<a?(H[b&255]<<24|H[b>>>8&255]<<16|H[b>>>16&255]<<8|H[b>>>24&255])>>32-a:H[b]>>8-a);if(8>a+f)g=g<<a|b,f+=a;else for(k=0;k<a;++k)g=g<<1|b>>a-k-1&1,8===++f&&(f=0,d[e++]=H[g],g=0,e===d.length&&(d=this.f()));d[e]=g;this.buffer=d;this.m=f;this.index=e};F.prototype.finish=function(){var b=this.buffer,a=this.index,c;0<this.m&&(b[a]<<=8-this.m,b[a]=H[b[a]],a++);B?c=b.subarray(0,a):(b.length=a,c=b);return c};
              +var ba=new (B?Uint8Array:Array)(256),ca;for(ca=0;256>ca;++ca){for(var K=ca,da=K,ea=7,K=K>>>1;K;K>>>=1)da<<=1,da|=K&1,--ea;ba[ca]=(da<<ea&255)>>>0}var H=ba;function ja(b,a,c){var d,e="number"===typeof a?a:a=0,f="number"===typeof c?c:b.length;d=-1;for(e=f&7;e--;++a)d=d>>>8^O[(d^b[a])&255];for(e=f>>3;e--;a+=8)d=d>>>8^O[(d^b[a])&255],d=d>>>8^O[(d^b[a+1])&255],d=d>>>8^O[(d^b[a+2])&255],d=d>>>8^O[(d^b[a+3])&255],d=d>>>8^O[(d^b[a+4])&255],d=d>>>8^O[(d^b[a+5])&255],d=d>>>8^O[(d^b[a+6])&255],d=d>>>8^O[(d^b[a+7])&255];return(d^4294967295)>>>0}
              +var ka=[0,1996959894,3993919788,2567524794,124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,3686517206,2898065728,853044451,1172266101,3705015759,
              +2882616665,651767980,1373503546,3369554304,3218104598,565507253,1454621731,3485111705,3099436303,671266974,1594198024,3322730930,2970347812,795835527,1483230225,3244367275,3060149565,1994146192,31158534,2563907772,4023717930,1907459465,112637215,2680153253,3904427059,2013776290,251722036,2517215374,3775830040,2137656763,141376813,2439277719,3865271297,1802195444,476864866,2238001368,4066508878,1812370925,453092731,2181625025,4111451223,1706088902,314042704,2344532202,4240017532,1658658271,366619977,
              +2362670323,4224994405,1303535960,984961486,2747007092,3569037538,1256170817,1037604311,2765210733,3554079995,1131014506,879679996,2909243462,3663771856,1141124467,855842277,2852801631,3708648649,1342533948,654459306,3188396048,3373015174,1466479909,544179635,3110523913,3462522015,1591671054,702138776,2966460450,3352799412,1504918807,783551873,3082640443,3233442989,3988292384,2596254646,62317068,1957810842,3939845945,2647816111,81470997,1943803523,3814918930,2489596804,225274430,2053790376,3826175755,
              +2466906013,167816743,2097651377,4027552580,2265490386,503444072,1762050814,4150417245,2154129355,426522225,1852507879,4275313526,2312317920,282753626,1742555852,4189708143,2394877945,397917763,1622183637,3604390888,2714866558,953729732,1340076626,3518719985,2797360999,1068828381,1219638859,3624741850,2936675148,906185462,1090812512,3747672003,2825379669,829329135,1181335161,3412177804,3160834842,628085408,1382605366,3423369109,3138078467,570562233,1426400815,3317316542,2998733608,733239954,1555261956,
              +3268935591,3050360625,752459403,1541320221,2607071920,3965973030,1969922972,40735498,2617837225,3943577151,1913087877,83908371,2512341634,3803740692,2075208622,213261112,2463272603,3855990285,2094854071,198958881,2262029012,4057260610,1759359992,534414190,2176718541,4139329115,1873836001,414664567,2282248934,4279200368,1711684554,285281116,2405801727,4167216745,1634467795,376229701,2685067896,3608007406,1308918612,956543938,2808555105,3495958263,1231636301,1047427035,2932959818,3654703836,1088359270,
              +936918E3,2847714899,3736837829,1202900863,817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117],O=B?new Uint32Array(ka):ka;function P(){}P.prototype.getName=function(){return this.name};P.prototype.getData=function(){return this.data};P.prototype.Y=function(){return this.Z};A("Zlib.GunzipMember",P);A("Zlib.GunzipMember.prototype.getName",P.prototype.getName);A("Zlib.GunzipMember.prototype.getData",P.prototype.getData);A("Zlib.GunzipMember.prototype.getMtime",P.prototype.Y);function la(b){this.buffer=new (B?Uint16Array:Array)(2*b);this.length=0}la.prototype.getParent=function(b){return 2*((b-2)/4|0)};la.prototype.push=function(b,a){var c,d,e=this.buffer,f;c=this.length;e[this.length++]=a;for(e[this.length++]=b;0<c;)if(d=this.getParent(c),e[c]>e[d])f=e[c],e[c]=e[d],e[d]=f,f=e[c+1],e[c+1]=e[d+1],e[d+1]=f,c=d;else break;return this.length};
              +la.prototype.pop=function(){var b,a,c=this.buffer,d,e,f;a=c[0];b=c[1];this.length-=2;c[0]=c[this.length];c[1]=c[this.length+1];for(f=0;;){e=2*f+2;if(e>=this.length)break;e+2<this.length&&c[e+2]>c[e]&&(e+=2);if(c[e]>c[f])d=c[f],c[f]=c[e],c[e]=d,d=c[f+1],c[f+1]=c[e+1],c[e+1]=d;else break;f=e}return{index:b,value:a,length:this.length}};function ma(b){var a=b.length,c=0,d=Number.POSITIVE_INFINITY,e,f,g,k,h,l,s,p,m,n;for(p=0;p<a;++p)b[p]>c&&(c=b[p]),b[p]<d&&(d=b[p]);e=1<<c;f=new (B?Uint32Array:Array)(e);g=1;k=0;for(h=2;g<=c;){for(p=0;p<a;++p)if(b[p]===g){l=0;s=k;for(m=0;m<g;++m)l=l<<1|s&1,s>>=1;n=g<<16|p;for(m=l;m<e;m+=h)f[m]=n;++k}++g;k<<=1;h<<=1}return[f,c,d]};function na(b,a){this.k=qa;this.I=0;this.input=B&&b instanceof Array?new Uint8Array(b):b;this.b=0;a&&(a.lazy&&(this.I=a.lazy),"number"===typeof a.compressionType&&(this.k=a.compressionType),a.outputBuffer&&(this.a=B&&a.outputBuffer instanceof Array?new Uint8Array(a.outputBuffer):a.outputBuffer),"number"===typeof a.outputIndex&&(this.b=a.outputIndex));this.a||(this.a=new (B?Uint8Array:Array)(32768))}var qa=2,ra={NONE:0,v:1,o:qa,ba:3},sa=[],S;
              +for(S=0;288>S;S++)switch(u){case 143>=S:sa.push([S+48,8]);break;case 255>=S:sa.push([S-144+400,9]);break;case 279>=S:sa.push([S-256+0,7]);break;case 287>=S:sa.push([S-280+192,8]);break;default:q("invalid literal: "+S)}
              +na.prototype.g=function(){var b,a,c,d,e=this.input;switch(this.k){case 0:c=0;for(d=e.length;c<d;){a=B?e.subarray(c,c+65535):e.slice(c,c+65535);c+=a.length;var f=a,g=c===d,k=t,h=t,l=t,s=t,p=t,m=this.a,n=this.b;if(B){for(m=new Uint8Array(this.a.buffer);m.length<=n+f.length+5;)m=new Uint8Array(m.length<<1);m.set(this.a)}k=g?1:0;m[n++]=k|0;h=f.length;l=~h+65536&65535;m[n++]=h&255;m[n++]=h>>>8&255;m[n++]=l&255;m[n++]=l>>>8&255;if(B)m.set(f,n),n+=f.length,m=m.subarray(0,n);else{s=0;for(p=f.length;s<p;++s)m[n++]=
              +f[s];m.length=n}this.b=n;this.a=m}break;case 1:var r=new F(B?new Uint8Array(this.a.buffer):this.a,this.b);r.d(1,1,u);r.d(1,2,u);var v=ta(this,e),x,Q,y;x=0;for(Q=v.length;x<Q;x++)if(y=v[x],F.prototype.d.apply(r,sa[y]),256<y)r.d(v[++x],v[++x],u),r.d(v[++x],5),r.d(v[++x],v[++x],u);else if(256===y)break;this.a=r.finish();this.b=this.a.length;break;case qa:var E=new F(B?new Uint8Array(this.a.buffer):this.a,this.b),Ka,R,X,Y,Z,pb=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],fa,La,ga,Ma,oa,wa=Array(19),
              +Na,$,pa,C,Oa;Ka=qa;E.d(1,1,u);E.d(Ka,2,u);R=ta(this,e);fa=ua(this.W,15);La=va(fa);ga=ua(this.V,7);Ma=va(ga);for(X=286;257<X&&0===fa[X-1];X--);for(Y=30;1<Y&&0===ga[Y-1];Y--);var Pa=X,Qa=Y,J=new (B?Uint32Array:Array)(Pa+Qa),w,L,z,ha,I=new (B?Uint32Array:Array)(316),G,D,M=new (B?Uint8Array:Array)(19);for(w=L=0;w<Pa;w++)J[L++]=fa[w];for(w=0;w<Qa;w++)J[L++]=ga[w];if(!B){w=0;for(ha=M.length;w<ha;++w)M[w]=0}w=G=0;for(ha=J.length;w<ha;w+=L){for(L=1;w+L<ha&&J[w+L]===J[w];++L);z=L;if(0===J[w])if(3>z)for(;0<
              +z--;)I[G++]=0,M[0]++;else for(;0<z;)D=138>z?z:138,D>z-3&&D<z&&(D=z-3),10>=D?(I[G++]=17,I[G++]=D-3,M[17]++):(I[G++]=18,I[G++]=D-11,M[18]++),z-=D;else if(I[G++]=J[w],M[J[w]]++,z--,3>z)for(;0<z--;)I[G++]=J[w],M[J[w]]++;else for(;0<z;)D=6>z?z:6,D>z-3&&D<z&&(D=z-3),I[G++]=16,I[G++]=D-3,M[16]++,z-=D}b=B?I.subarray(0,G):I.slice(0,G);oa=ua(M,7);for(C=0;19>C;C++)wa[C]=oa[pb[C]];for(Z=19;4<Z&&0===wa[Z-1];Z--);Na=va(oa);E.d(X-257,5,u);E.d(Y-1,5,u);E.d(Z-4,4,u);for(C=0;C<Z;C++)E.d(wa[C],3,u);C=0;for(Oa=b.length;C<
              +Oa;C++)if($=b[C],E.d(Na[$],oa[$],u),16<=$){C++;switch($){case 16:pa=2;break;case 17:pa=3;break;case 18:pa=7;break;default:q("invalid code: "+$)}E.d(b[C],pa,u)}var Ra=[La,fa],Sa=[Ma,ga],N,Ta,ia,za,Ua,Va,Wa,Xa;Ua=Ra[0];Va=Ra[1];Wa=Sa[0];Xa=Sa[1];N=0;for(Ta=R.length;N<Ta;++N)if(ia=R[N],E.d(Ua[ia],Va[ia],u),256<ia)E.d(R[++N],R[++N],u),za=R[++N],E.d(Wa[za],Xa[za],u),E.d(R[++N],R[++N],u);else if(256===ia)break;this.a=E.finish();this.b=this.a.length;break;default:q("invalid compression type")}return this.a};
              +function xa(b,a){this.length=b;this.Q=a}
              +var ya=function(){function b(a){switch(u){case 3===a:return[257,a-3,0];case 4===a:return[258,a-4,0];case 5===a:return[259,a-5,0];case 6===a:return[260,a-6,0];case 7===a:return[261,a-7,0];case 8===a:return[262,a-8,0];case 9===a:return[263,a-9,0];case 10===a:return[264,a-10,0];case 12>=a:return[265,a-11,1];case 14>=a:return[266,a-13,1];case 16>=a:return[267,a-15,1];case 18>=a:return[268,a-17,1];case 22>=a:return[269,a-19,2];case 26>=a:return[270,a-23,2];case 30>=a:return[271,a-27,2];case 34>=a:return[272,
              +a-31,2];case 42>=a:return[273,a-35,3];case 50>=a:return[274,a-43,3];case 58>=a:return[275,a-51,3];case 66>=a:return[276,a-59,3];case 82>=a:return[277,a-67,4];case 98>=a:return[278,a-83,4];case 114>=a:return[279,a-99,4];case 130>=a:return[280,a-115,4];case 162>=a:return[281,a-131,5];case 194>=a:return[282,a-163,5];case 226>=a:return[283,a-195,5];case 257>=a:return[284,a-227,5];case 258===a:return[285,a-258,0];default:q("invalid length: "+a)}}var a=[],c,d;for(c=3;258>=c;c++)d=b(c),a[c]=d[2]<<24|d[1]<<
              +16|d[0];return a}(),Aa=B?new Uint32Array(ya):ya;
              +function ta(b,a){function c(a,c){var b=a.Q,d=[],e=0,f;f=Aa[a.length];d[e++]=f&65535;d[e++]=f>>16&255;d[e++]=f>>24;var g;switch(u){case 1===b:g=[0,b-1,0];break;case 2===b:g=[1,b-2,0];break;case 3===b:g=[2,b-3,0];break;case 4===b:g=[3,b-4,0];break;case 6>=b:g=[4,b-5,1];break;case 8>=b:g=[5,b-7,1];break;case 12>=b:g=[6,b-9,2];break;case 16>=b:g=[7,b-13,2];break;case 24>=b:g=[8,b-17,3];break;case 32>=b:g=[9,b-25,3];break;case 48>=b:g=[10,b-33,4];break;case 64>=b:g=[11,b-49,4];break;case 96>=b:g=[12,b-
              +65,5];break;case 128>=b:g=[13,b-97,5];break;case 192>=b:g=[14,b-129,6];break;case 256>=b:g=[15,b-193,6];break;case 384>=b:g=[16,b-257,7];break;case 512>=b:g=[17,b-385,7];break;case 768>=b:g=[18,b-513,8];break;case 1024>=b:g=[19,b-769,8];break;case 1536>=b:g=[20,b-1025,9];break;case 2048>=b:g=[21,b-1537,9];break;case 3072>=b:g=[22,b-2049,10];break;case 4096>=b:g=[23,b-3073,10];break;case 6144>=b:g=[24,b-4097,11];break;case 8192>=b:g=[25,b-6145,11];break;case 12288>=b:g=[26,b-8193,12];break;case 16384>=
              +b:g=[27,b-12289,12];break;case 24576>=b:g=[28,b-16385,13];break;case 32768>=b:g=[29,b-24577,13];break;default:q("invalid distance")}f=g;d[e++]=f[0];d[e++]=f[1];d[e++]=f[2];var h,k;h=0;for(k=d.length;h<k;++h)m[n++]=d[h];v[d[0]]++;x[d[3]]++;r=a.length+c-1;p=null}var d,e,f,g,k,h={},l,s,p,m=B?new Uint16Array(2*a.length):[],n=0,r=0,v=new (B?Uint32Array:Array)(286),x=new (B?Uint32Array:Array)(30),Q=b.I,y;if(!B){for(f=0;285>=f;)v[f++]=0;for(f=0;29>=f;)x[f++]=0}v[256]=1;d=0;for(e=a.length;d<e;++d){f=k=0;
              +for(g=3;f<g&&d+f!==e;++f)k=k<<8|a[d+f];h[k]===t&&(h[k]=[]);l=h[k];if(!(0<r--)){for(;0<l.length&&32768<d-l[0];)l.shift();if(d+3>=e){p&&c(p,-1);f=0;for(g=e-d;f<g;++f)y=a[d+f],m[n++]=y,++v[y];break}0<l.length?(s=Ba(a,d,l),p?p.length<s.length?(y=a[d-1],m[n++]=y,++v[y],c(s,0)):c(p,-1):s.length<Q?p=s:c(s,0)):p?c(p,-1):(y=a[d],m[n++]=y,++v[y])}l.push(d)}m[n++]=256;v[256]++;b.W=v;b.V=x;return B?m.subarray(0,n):m}
              +function Ba(b,a,c){var d,e,f=0,g,k,h,l,s=b.length;k=0;l=c.length;a:for(;k<l;k++){d=c[l-k-1];g=3;if(3<f){for(h=f;3<h;h--)if(b[d+h-1]!==b[a+h-1])continue a;g=f}for(;258>g&&a+g<s&&b[d+g]===b[a+g];)++g;g>f&&(e=d,f=g);if(258===g)break}return new xa(f,a-e)}
              +function ua(b,a){var c=b.length,d=new la(572),e=new (B?Uint8Array:Array)(c),f,g,k,h,l;if(!B)for(h=0;h<c;h++)e[h]=0;for(h=0;h<c;++h)0<b[h]&&d.push(h,b[h]);f=Array(d.length/2);g=new (B?Uint32Array:Array)(d.length/2);if(1===f.length)return e[d.pop().index]=1,e;h=0;for(l=d.length/2;h<l;++h)f[h]=d.pop(),g[h]=f[h].value;k=Ca(g,g.length,a);h=0;for(l=f.length;h<l;++h)e[f[h].index]=k[h];return e}
              +function Ca(b,a,c){function d(b){var c=h[b][l[b]];c===a?(d(b+1),d(b+1)):--g[c];++l[b]}var e=new (B?Uint16Array:Array)(c),f=new (B?Uint8Array:Array)(c),g=new (B?Uint8Array:Array)(a),k=Array(c),h=Array(c),l=Array(c),s=(1<<c)-a,p=1<<c-1,m,n,r,v,x;e[c-1]=a;for(n=0;n<c;++n)s<p?f[n]=0:(f[n]=1,s-=p),s<<=1,e[c-2-n]=(e[c-1-n]/2|0)+a;e[0]=f[0];k[0]=Array(e[0]);h[0]=Array(e[0]);for(n=1;n<c;++n)e[n]>2*e[n-1]+f[n]&&(e[n]=2*e[n-1]+f[n]),k[n]=Array(e[n]),h[n]=Array(e[n]);for(m=0;m<a;++m)g[m]=c;for(r=0;r<e[c-1];++r)k[c-
              +1][r]=b[r],h[c-1][r]=r;for(m=0;m<c;++m)l[m]=0;1===f[c-1]&&(--g[0],++l[c-1]);for(n=c-2;0<=n;--n){v=m=0;x=l[n+1];for(r=0;r<e[n];r++)v=k[n+1][x]+k[n+1][x+1],v>b[m]?(k[n][r]=v,h[n][r]=a,x+=2):(k[n][r]=b[m],h[n][r]=m,++m);l[n]=0;1===f[n]&&d(n)}return g}
              +function va(b){var a=new (B?Uint16Array:Array)(b.length),c=[],d=[],e=0,f,g,k,h;f=0;for(g=b.length;f<g;f++)c[b[f]]=(c[b[f]]|0)+1;f=1;for(g=16;f<=g;f++)d[f]=e,e+=c[f]|0,e<<=1;f=0;for(g=b.length;f<g;f++){e=d[b[f]];d[b[f]]+=1;k=a[f]=0;for(h=b[f];k<h;k++)a[f]=a[f]<<1|e&1,e>>>=1}return a};function Da(b,a){this.input=b;this.b=this.c=0;this.i={};a&&(a.flags&&(this.i=a.flags),"string"===typeof a.filename&&(this.filename=a.filename),"string"===typeof a.comment&&(this.A=a.comment),a.deflateOptions&&(this.l=a.deflateOptions));this.l||(this.l={})}
              +Da.prototype.g=function(){var b,a,c,d,e,f,g,k,h=new (B?Uint8Array:Array)(32768),l=0,s=this.input,p=this.c,m=this.filename,n=this.A;h[l++]=31;h[l++]=139;h[l++]=8;b=0;this.i.fname&&(b|=Ea);this.i.fcomment&&(b|=Fa);this.i.fhcrc&&(b|=Ga);h[l++]=b;a=(Date.now?Date.now():+new Date)/1E3|0;h[l++]=a&255;h[l++]=a>>>8&255;h[l++]=a>>>16&255;h[l++]=a>>>24&255;h[l++]=0;h[l++]=Ha;if(this.i.fname!==t){g=0;for(k=m.length;g<k;++g)f=m.charCodeAt(g),255<f&&(h[l++]=f>>>8&255),h[l++]=f&255;h[l++]=0}if(this.i.comment){g=
              +0;for(k=n.length;g<k;++g)f=n.charCodeAt(g),255<f&&(h[l++]=f>>>8&255),h[l++]=f&255;h[l++]=0}this.i.fhcrc&&(c=ja(h,0,l)&65535,h[l++]=c&255,h[l++]=c>>>8&255);this.l.outputBuffer=h;this.l.outputIndex=l;e=new na(s,this.l);h=e.g();l=e.b;B&&(l+8>h.buffer.byteLength?(this.a=new Uint8Array(l+8),this.a.set(new Uint8Array(h.buffer)),h=this.a):h=new Uint8Array(h.buffer));d=ja(s,t,t);h[l++]=d&255;h[l++]=d>>>8&255;h[l++]=d>>>16&255;h[l++]=d>>>24&255;k=s.length;h[l++]=k&255;h[l++]=k>>>8&255;h[l++]=k>>>16&255;h[l++]=
              +k>>>24&255;this.c=p;B&&l<h.length&&(this.a=h=h.subarray(0,l));return h};var Ha=255,Ga=2,Ea=8,Fa=16;A("Zlib.Gzip",Da);A("Zlib.Gzip.prototype.compress",Da.prototype.g);function T(b,a){this.p=[];this.q=32768;this.e=this.j=this.c=this.u=0;this.input=B?new Uint8Array(b):b;this.w=!1;this.r=Ia;this.M=!1;if(a||!(a={}))a.index&&(this.c=a.index),a.bufferSize&&(this.q=a.bufferSize),a.bufferType&&(this.r=a.bufferType),a.resize&&(this.M=a.resize);switch(this.r){case Ja:this.b=32768;this.a=new (B?Uint8Array:Array)(32768+this.q+258);break;case Ia:this.b=0;this.a=new (B?Uint8Array:Array)(this.q);this.f=this.U;this.B=this.R;this.s=this.T;break;default:q(Error("invalid inflate mode"))}}
              +var Ja=0,Ia=1,Ya={O:Ja,N:Ia};
              +T.prototype.h=function(){for(;!this.w;){var b=U(this,3);b&1&&(this.w=u);b>>>=1;switch(b){case 0:var a=this.input,c=this.c,d=this.a,e=this.b,f=a.length,g=t,k=t,h=d.length,l=t;this.e=this.j=0;c+1>=f&&q(Error("invalid uncompressed block header: LEN"));g=a[c++]|a[c++]<<8;c+1>=f&&q(Error("invalid uncompressed block header: NLEN"));k=a[c++]|a[c++]<<8;g===~k&&q(Error("invalid uncompressed block header: length verify"));c+g>a.length&&q(Error("input buffer is broken"));switch(this.r){case Ja:for(;e+g>d.length;){l=
              +h-e;g-=l;if(B)d.set(a.subarray(c,c+l),e),e+=l,c+=l;else for(;l--;)d[e++]=a[c++];this.b=e;d=this.f();e=this.b}break;case Ia:for(;e+g>d.length;)d=this.f({F:2});break;default:q(Error("invalid inflate mode"))}if(B)d.set(a.subarray(c,c+g),e),e+=g,c+=g;else for(;g--;)d[e++]=a[c++];this.c=c;this.b=e;this.a=d;break;case 1:this.s(Za,$a);break;case 2:ab(this);break;default:q(Error("unknown BTYPE: "+b))}}return this.B()};
              +var bb=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],cb=B?new Uint16Array(bb):bb,db=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,258,258],eb=B?new Uint16Array(db):db,fb=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0],gb=B?new Uint8Array(fb):fb,hb=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577],ib=B?new Uint16Array(hb):hb,jb=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,
              +10,11,11,12,12,13,13],kb=B?new Uint8Array(jb):jb,lb=new (B?Uint8Array:Array)(288),V,mb;V=0;for(mb=lb.length;V<mb;++V)lb[V]=143>=V?8:255>=V?9:279>=V?7:8;var Za=ma(lb),nb=new (B?Uint8Array:Array)(30),ob,qb;ob=0;for(qb=nb.length;ob<qb;++ob)nb[ob]=5;var $a=ma(nb);function U(b,a){for(var c=b.j,d=b.e,e=b.input,f=b.c,g=e.length,k;d<a;)f>=g&&q(Error("input buffer is broken")),c|=e[f++]<<d,d+=8;k=c&(1<<a)-1;b.j=c>>>a;b.e=d-a;b.c=f;return k}
              +function rb(b,a){for(var c=b.j,d=b.e,e=b.input,f=b.c,g=e.length,k=a[0],h=a[1],l,s;d<h&&!(f>=g);)c|=e[f++]<<d,d+=8;l=k[c&(1<<h)-1];s=l>>>16;b.j=c>>s;b.e=d-s;b.c=f;return l&65535}
              +function ab(b){function a(a,b,c){var d,e=this.J,f,g;for(g=0;g<a;)switch(d=rb(this,b),d){case 16:for(f=3+U(this,2);f--;)c[g++]=e;break;case 17:for(f=3+U(this,3);f--;)c[g++]=0;e=0;break;case 18:for(f=11+U(this,7);f--;)c[g++]=0;e=0;break;default:e=c[g++]=d}this.J=e;return c}var c=U(b,5)+257,d=U(b,5)+1,e=U(b,4)+4,f=new (B?Uint8Array:Array)(cb.length),g,k,h,l;for(l=0;l<e;++l)f[cb[l]]=U(b,3);if(!B){l=e;for(e=f.length;l<e;++l)f[cb[l]]=0}g=ma(f);k=new (B?Uint8Array:Array)(c);h=new (B?Uint8Array:Array)(d);
              +b.J=0;b.s(ma(a.call(b,c,g,k)),ma(a.call(b,d,g,h)))}T.prototype.s=function(b,a){var c=this.a,d=this.b;this.C=b;for(var e=c.length-258,f,g,k,h;256!==(f=rb(this,b));)if(256>f)d>=e&&(this.b=d,c=this.f(),d=this.b),c[d++]=f;else{g=f-257;h=eb[g];0<gb[g]&&(h+=U(this,gb[g]));f=rb(this,a);k=ib[f];0<kb[f]&&(k+=U(this,kb[f]));d>=e&&(this.b=d,c=this.f(),d=this.b);for(;h--;)c[d]=c[d++-k]}for(;8<=this.e;)this.e-=8,this.c--;this.b=d};
              +T.prototype.T=function(b,a){var c=this.a,d=this.b;this.C=b;for(var e=c.length,f,g,k,h;256!==(f=rb(this,b));)if(256>f)d>=e&&(c=this.f(),e=c.length),c[d++]=f;else{g=f-257;h=eb[g];0<gb[g]&&(h+=U(this,gb[g]));f=rb(this,a);k=ib[f];0<kb[f]&&(k+=U(this,kb[f]));d+h>e&&(c=this.f(),e=c.length);for(;h--;)c[d]=c[d++-k]}for(;8<=this.e;)this.e-=8,this.c--;this.b=d};
              +T.prototype.f=function(){var b=new (B?Uint8Array:Array)(this.b-32768),a=this.b-32768,c,d,e=this.a;if(B)b.set(e.subarray(32768,b.length));else{c=0;for(d=b.length;c<d;++c)b[c]=e[c+32768]}this.p.push(b);this.u+=b.length;if(B)e.set(e.subarray(a,a+32768));else for(c=0;32768>c;++c)e[c]=e[a+c];this.b=32768;return e};
              +T.prototype.U=function(b){var a,c=this.input.length/this.c+1|0,d,e,f,g=this.input,k=this.a;b&&("number"===typeof b.F&&(c=b.F),"number"===typeof b.P&&(c+=b.P));2>c?(d=(g.length-this.c)/this.C[2],f=258*(d/2)|0,e=f<k.length?k.length+f:k.length<<1):e=k.length*c;B?(a=new Uint8Array(e),a.set(k)):a=k;return this.a=a};
              +T.prototype.B=function(){var b=0,a=this.a,c=this.p,d,e=new (B?Uint8Array:Array)(this.u+(this.b-32768)),f,g,k,h;if(0===c.length)return B?this.a.subarray(32768,this.b):this.a.slice(32768,this.b);f=0;for(g=c.length;f<g;++f){d=c[f];k=0;for(h=d.length;k<h;++k)e[b++]=d[k]}f=32768;for(g=this.b;f<g;++f)e[b++]=a[f];this.p=[];return this.buffer=e};
              +T.prototype.R=function(){var b,a=this.b;B?this.M?(b=new Uint8Array(a),b.set(this.a.subarray(0,a))):b=this.a.subarray(0,a):(this.a.length>a&&(this.a.length=a),b=this.a);return this.buffer=b};function sb(b){this.input=b;this.c=0;this.t=[];this.D=!1}sb.prototype.X=function(){this.D||this.h();return this.t.slice()};
              +sb.prototype.h=function(){for(var b=this.input.length;this.c<b;){var a=new P,c=t,d=t,e=t,f=t,g=t,k=t,h=t,l=t,s=t,p=this.input,m=this.c;a.G=p[m++];a.H=p[m++];(31!==a.G||139!==a.H)&&q(Error("invalid file signature:"+a.G+","+a.H));a.z=p[m++];switch(a.z){case 8:break;default:q(Error("unknown compression method: "+a.z))}a.n=p[m++];l=p[m++]|p[m++]<<8|p[m++]<<16|p[m++]<<24;a.Z=new Date(1E3*l);a.fa=p[m++];a.ea=p[m++];0<(a.n&4)&&(a.aa=p[m++]|p[m++]<<8,m+=a.aa);if(0<(a.n&Ea)){h=[];for(k=0;0<(g=p[m++]);)h[k++]=
              +String.fromCharCode(g);a.name=h.join("")}if(0<(a.n&Fa)){h=[];for(k=0;0<(g=p[m++]);)h[k++]=String.fromCharCode(g);a.A=h.join("")}0<(a.n&Ga)&&(a.S=ja(p,0,m)&65535,a.S!==(p[m++]|p[m++]<<8)&&q(Error("invalid header crc16")));c=p[p.length-4]|p[p.length-3]<<8|p[p.length-2]<<16|p[p.length-1]<<24;p.length-m-4-4<512*c&&(f=c);d=new T(p,{index:m,bufferSize:f});a.data=e=d.h();m=d.c;a.ca=s=(p[m++]|p[m++]<<8|p[m++]<<16|p[m++]<<24)>>>0;ja(e,t,t)!==s&&q(Error("invalid CRC-32 checksum: 0x"+ja(e,t,t).toString(16)+
              +" / 0x"+s.toString(16)));a.da=c=(p[m++]|p[m++]<<8|p[m++]<<16|p[m++]<<24)>>>0;(e.length&4294967295)!==c&&q(Error("invalid input size: "+(e.length&4294967295)+" / "+c));this.t.push(a);this.c=m}this.D=u;var n=this.t,r,v,x=0,Q=0,y;r=0;for(v=n.length;r<v;++r)Q+=n[r].data.length;if(B){y=new Uint8Array(Q);for(r=0;r<v;++r)y.set(n[r].data,x),x+=n[r].data.length}else{y=[];for(r=0;r<v;++r)y[r]=n[r].data;y=Array.prototype.concat.apply([],y)}return y};A("Zlib.Gunzip",sb);A("Zlib.Gunzip.prototype.decompress",sb.prototype.h);A("Zlib.Gunzip.prototype.getMembers",sb.prototype.X);function tb(b){if("string"===typeof b){var a=b.split(""),c,d;c=0;for(d=a.length;c<d;c++)a[c]=(a[c].charCodeAt(0)&255)>>>0;b=a}for(var e=1,f=0,g=b.length,k,h=0;0<g;){k=1024<g?1024:g;g-=k;do e+=b[h++],f+=e;while(--k);e%=65521;f%=65521}return(f<<16|e)>>>0};function ub(b,a){var c,d;this.input=b;this.c=0;if(a||!(a={}))a.index&&(this.c=a.index),a.verify&&(this.$=a.verify);c=b[this.c++];d=b[this.c++];switch(c&15){case vb:this.method=vb;break;default:q(Error("unsupported compression method"))}0!==((c<<8)+d)%31&&q(Error("invalid fcheck flag:"+((c<<8)+d)%31));d&32&&q(Error("fdict flag is not supported"));this.L=new T(b,{index:this.c,bufferSize:a.bufferSize,bufferType:a.bufferType,resize:a.resize})}
              +ub.prototype.h=function(){var b=this.input,a,c;a=this.L.h();this.c=this.L.c;this.$&&(c=(b[this.c++]<<24|b[this.c++]<<16|b[this.c++]<<8|b[this.c++])>>>0,c!==tb(a)&&q(Error("invalid adler-32 checksum")));return a};var vb=8;function wb(b,a){this.input=b;this.a=new (B?Uint8Array:Array)(32768);this.k=W.o;var c={},d;if((a||!(a={}))&&"number"===typeof a.compressionType)this.k=a.compressionType;for(d in a)c[d]=a[d];c.outputBuffer=this.a;this.K=new na(this.input,c)}var W=ra;
              +wb.prototype.g=function(){var b,a,c,d,e,f,g,k=0;g=this.a;b=vb;switch(b){case vb:a=Math.LOG2E*Math.log(32768)-8;break;default:q(Error("invalid compression method"))}c=a<<4|b;g[k++]=c;switch(b){case vb:switch(this.k){case W.NONE:e=0;break;case W.v:e=1;break;case W.o:e=2;break;default:q(Error("unsupported compression type"))}break;default:q(Error("invalid compression method"))}d=e<<6|0;g[k++]=d|31-(256*c+d)%31;f=tb(this.input);this.K.b=k;g=this.K.g();k=g.length;B&&(g=new Uint8Array(g.buffer),g.length<=
              +k+4&&(this.a=new Uint8Array(g.length+4),this.a.set(g),g=this.a),g=g.subarray(0,k+4));g[k++]=f>>24&255;g[k++]=f>>16&255;g[k++]=f>>8&255;g[k++]=f&255;return g};function xb(b,a){var c,d,e,f;if(Object.keys)c=Object.keys(a);else for(d in c=[],e=0,a)c[e++]=d;e=0;for(f=c.length;e<f;++e)d=c[e],A(b+"."+d,a[d])};A("Zlib.Inflate",ub);A("Zlib.Inflate.prototype.decompress",ub.prototype.h);xb("Zlib.Inflate.BufferType",{ADAPTIVE:Ya.N,BLOCK:Ya.O});A("Zlib.Deflate",wb);A("Zlib.Deflate.compress",function(b,a){return(new wb(b,a)).g()});A("Zlib.Deflate.prototype.compress",wb.prototype.g);xb("Zlib.Deflate.CompressionType",{NONE:W.NONE,FIXED:W.v,DYNAMIC:W.o});}).call(this);
              \ No newline at end of file
              diff --git a/src/js/operations/Base.js b/src/js/operations/Base.js
              new file mode 100755
              index 00000000..2cd4dea7
              --- /dev/null
              +++ b/src/js/operations/Base.js
              @@ -0,0 +1,52 @@
              +/**
              + * Numerical base operations.
              + *
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @namespace
              + */
              +var Base = {
              +
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    DEFAULT_RADIX: 36,
              +    
              +    /**
              +     * To Base operation.
              +     *
              +     * @param {number} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_to: function(input, args) {
              +        if (!input) {
              +            throw ("Error: Input must be a number");
              +        }
              +        var radix = args[0] || Base.DEFAULT_RADIX;
              +        if (radix < 2 || radix > 36) {
              +            throw "Error: Radix argument must be between 2 and 36";
              +        }
              +        return input.toString(radix);
              +    },
              +    
              +    
              +    /**
              +     * From Base operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {number}
              +     */
              +    run_from: function(input, args) {
              +        var radix = args[0] || Base.DEFAULT_RADIX;
              +        if (radix < 2 || radix > 36) {
              +            throw "Error: Radix argument must be between 2 and 36";
              +        }
              +        return parseInt(input.replace(/\s/g, ""), radix);
              +    },
              +    
              +};
              diff --git a/src/js/operations/Base64.js b/src/js/operations/Base64.js
              new file mode 100755
              index 00000000..b475f2c1
              --- /dev/null
              +++ b/src/js/operations/Base64.js
              @@ -0,0 +1,341 @@
              +/**
              + * Base64 operations.
              + *
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @namespace
              + */
              +var Base64 = {
              +
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    ALPHABET: "A-Za-z0-9+/=",
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    ALPHABET_OPTIONS: [
              +        {name: "Standard: A-Za-z0-9+/=", value: "A-Za-z0-9+/="},
              +        {name: "URL safe: A-Za-z0-9-_", value: "A-Za-z0-9-_"},
              +        {name: "Filename safe: A-Za-z0-9+-=", value: "A-Za-z0-9+\\-="},
              +        {name: "itoa64: ./0-9A-Za-z=", value: "./0-9A-Za-z="},
              +        {name: "XML: A-Za-z0-9_.", value: "A-Za-z0-9_."},
              +        {name: "y64: A-Za-z0-9._-", value: "A-Za-z0-9._-"},
              +        {name: "z64: 0-9a-zA-Z+/=", value: "0-9a-zA-Z+/="},
              +        {name: "Radix-64: 0-9A-Za-z+/=", value: "0-9A-Za-z+/="},
              +        {name: "Uuencoding: [space]-_", value: " -_"},
              +        {name: "Xxencoding: +-0-9A-Za-z", value: "+\\-0-9A-Za-z"},
              +        {name: "BinHex: !-,-0-689@A-NP-VX-Z[`a-fh-mp-r", value: "!-,-0-689@A-NP-VX-Z[`a-fh-mp-r"},
              +        {name: "ROT13: N-ZA-Mn-za-m0-9+/=", value: "N-ZA-Mn-za-m0-9+/="},
              +    ],
              +
              +    /**
              +     * To Base64 operation.
              +     *
              +     * @param {byte_array} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_to: function(input, args) {
              +        var alphabet = args[0] || Base64.ALPHABET;
              +        return Utils.to_base64(input, alphabet);
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    REMOVE_NON_ALPH_CHARS: true,
              +    
              +    /**
              +     * From Base64 operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {byte_array}
              +     */
              +    run_from: function(input, args) {
              +        var alphabet = args[0] || Base64.ALPHABET,
              +            remove_non_alph_chars = args[1];
              +        
              +        return Utils.from_base64(input, alphabet, "byte_array", remove_non_alph_chars);
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    BASE32_ALPHABET: "A-Z2-7=",
              +    
              +    /**
              +     * To Base32 operation.
              +     *
              +     * @param {byte_array} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_to_32: function(input, args) {
              +        if (!input) return "";
              +        
              +        var alphabet = args[0] ?
              +                Utils.expand_alph_range(args[0]).join("") : "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=",
              +            output = "",
              +            chr1, chr2, chr3, chr4, chr5,
              +            enc1, enc2, enc3, enc4, enc5, enc6, enc7, enc8,
              +            i = 0;
              +
              +        while (i < input.length) {
              +            chr1 = input[i++];
              +            chr2 = input[i++];
              +            chr3 = input[i++];
              +            chr4 = input[i++];
              +            chr5 = input[i++];
              +
              +            enc1 = chr1 >> 3;
              +            enc2 = ((chr1 & 7) << 2) | (chr2 >> 6);
              +            enc3 = (chr2 >> 1) & 31;
              +            enc4 = ((chr2 & 1) << 4) | (chr3 >> 4);
              +            enc5 = ((chr3 & 15) << 1) | (chr4 >> 7);
              +            enc6 = (chr4 >> 2) & 63;
              +            enc7 = ((chr4 & 3) << 3) | (chr5 >> 5);
              +            enc8 = chr5 & 31;
              +
              +            if (isNaN(chr2)) {
              +                enc3 = enc4 = enc5 = enc6 = enc7 = enc8 = 32;
              +            } else if (isNaN(chr3)) {
              +                enc5 = enc6 = enc7 = enc8 = 32;
              +            } else if (isNaN(chr4)) {
              +                enc6 = enc7 = enc8 = 32;
              +            } else if (isNaN(chr5)) {
              +                enc8 = 32;
              +            }
              +            
              +            output += alphabet.charAt(enc1) + alphabet.charAt(enc2) + alphabet.charAt(enc3) +
              +                alphabet.charAt(enc4) + alphabet.charAt(enc5) + alphabet.charAt(enc6) +
              +                alphabet.charAt(enc7) + alphabet.charAt(enc8);
              +        }
              +        
              +        return output;
              +    },
              +    
              +    
              +    /**
              +     * From Base32 operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {byte_array}
              +     */
              +    run_from_32: function(input, args) {
              +        if (!input) return [];
              +        
              +        var alphabet = args[0] ?
              +                Utils.expand_alph_range(args[0]).join("") : "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=",
              +            remove_non_alph_chars = args[0];
              +        
              +        var output = [],
              +            chr1, chr2, chr3, chr4, chr5,
              +            enc1, enc2, enc3, enc4, enc5, enc6, enc7, enc8,
              +            i = 0;
              +        
              +        if (remove_non_alph_chars) {
              +            var re = new RegExp("[^" + alphabet.replace(/[\]\\\-^]/g, "\\$&") + "]", "g");
              +            input = input.replace(re, "");
              +        }
              +
              +        while (i < input.length) {
              +            enc1 = alphabet.indexOf(input.charAt(i++));
              +            enc2 = alphabet.indexOf(input.charAt(i++) || "=");
              +            enc3 = alphabet.indexOf(input.charAt(i++) || "=");
              +            enc4 = alphabet.indexOf(input.charAt(i++) || "=");
              +            enc5 = alphabet.indexOf(input.charAt(i++) || "=");
              +            enc6 = alphabet.indexOf(input.charAt(i++) || "=");
              +            enc7 = alphabet.indexOf(input.charAt(i++) || "=");
              +            enc8 = alphabet.indexOf(input.charAt(i++) || "=");
              +
              +            chr1 = (enc1 << 3) | (enc2 >> 2);
              +            chr2 = ((enc2 & 3) << 6) | (enc3 << 1) | (enc4 >> 4);
              +            chr3 = ((enc4 & 15) << 4) | (enc5 >> 1);
              +            chr4 = ((enc5 & 1) << 7) | (enc6 << 2) | (enc7 >> 3);
              +            chr5 = ((enc7 & 7) << 5) | enc8;
              +
              +            output.push(chr1);
              +            if (enc2 & 3 !== 0 || enc3 !== 32) output.push(chr2);
              +            if (enc4 & 15 !== 0 || enc5 !== 32) output.push(chr3);
              +            if (enc5 & 1 !== 0 || enc6 !== 32) output.push(chr4);
              +            if (enc7 & 7 !== 0 || enc8 !== 32) output.push(chr5);
              +        }
              +        
              +        return output;
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    SHOW_IN_BINARY: false,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    OFFSETS_SHOW_VARIABLE: true,
              +    
              +    /**
              +     * Show Base64 offsets operation.
              +     *
              +     * @param {byte_array} input
              +     * @param {Object[]} args
              +     * @returns {html}
              +     */
              +    run_offsets: function(input, args) {
              +        var alphabet = args[0] || Base64.ALPHABET,
              +            show_variable = args[1],
              +            offset0 = Utils.to_base64(input, alphabet),
              +            offset1 = Utils.to_base64([0].concat(input), alphabet),
              +            offset2 = Utils.to_base64([0, 0].concat(input), alphabet),
              +            len0 = offset0.indexOf("="),
              +            len1 = offset1.indexOf("="),
              +            len2 = offset2.indexOf("="),
              +            script = "<script type='application/javascript'>$('[data-toggle=\"tooltip\"]').tooltip()</script>",
              +            static_section = "",
              +            padding = "";
              +        
              +        if (input.length < 1) {
              +            return "Please enter a string.";
              +        }
              +        
              +        // Highlight offset 0
              +        if (len0 % 4 == 2) {
              +            static_section = offset0.slice(0, -3);
              +            offset0 = "<span data-toggle='tooltip' data-placement='top' title='" + 
              +                Utils.from_base64(static_section, alphabet).slice(0, -2) + "'>" +
              +                static_section + "</span>" +
              +                "<span class='hlgreen'>" + offset0.substr(offset0.length - 3, 1) + "</span>" +
              +                "<span class='hlred'>" + offset0.substr(offset0.length - 2) + "</span>";
              +        } else if (len0 % 4 == 3) {
              +            static_section = offset0.slice(0, -2);
              +            offset0 = "<span data-toggle='tooltip' data-placement='top' title='" + 
              +                Utils.from_base64(static_section, alphabet).slice(0, -1) + "'>" +
              +                static_section + "</span>" +
              +                "<span class='hlgreen'>" + offset0.substr(offset0.length - 2, 1) + "</span>" +
              +                "<span class='hlred'>" + offset0.substr(offset0.length - 1) + "</span>";
              +        } else {
              +            static_section = offset0;
              +            offset0 = "<span data-toggle='tooltip' data-placement='top' title='" + 
              +                Utils.from_base64(static_section, alphabet) + "'>" +
              +                static_section + "</span>";
              +        }
              +        
              +        if (!show_variable) {
              +            offset0 = static_section;
              +        }
              +        
              +        
              +        // Highlight offset 1
              +        padding = "<span class='hlred'>" + offset1.substr(0, 1) + "</span>" +
              +            "<span class='hlgreen'>" + offset1.substr(1, 1) + "</span>";
              +        offset1 = offset1.substr(2);
              +        if (len1 % 4 == 2) {
              +            static_section = offset1.slice(0, -3);
              +            offset1 = padding + "<span data-toggle='tooltip' data-placement='top' title='" + 
              +                Utils.from_base64("AA" + static_section, alphabet).slice(1, -2) + "'>" +
              +                static_section + "</span>" +
              +                "<span class='hlgreen'>" + offset1.substr(offset1.length - 3, 1) + "</span>" +
              +                "<span class='hlred'>" + offset1.substr(offset1.length - 2) + "</span>";
              +        } else if (len1 % 4 == 3) {
              +            static_section = offset1.slice(0, -2);
              +             offset1 = padding + "<span data-toggle='tooltip' data-placement='top' title='" + 
              +                Utils.from_base64("AA" + static_section, alphabet).slice(1, -1) + "'>" +
              +                static_section + "</span>" +
              +                "<span class='hlgreen'>" + offset1.substr(offset1.length - 2, 1) + "</span>" +
              +                "<span class='hlred'>" + offset1.substr(offset1.length - 1) + "</span>";
              +        } else {
              +            static_section = offset1;
              +            offset1 = padding +  "<span data-toggle='tooltip' data-placement='top' title='" + 
              +                Utils.from_base64("AA" + static_section, alphabet).slice(1) + "'>" +
              +                static_section + "</span>";
              +        }
              +        
              +        if (!show_variable) {
              +            offset1 = static_section;
              +        }
              +        
              +        // Highlight offset 2
              +        padding = "<span class='hlred'>" + offset2.substr(0, 2) + "</span>" +
              +            "<span class='hlgreen'>" + offset2.substr(2, 1) + "</span>";
              +        offset2 = offset2.substr(3);
              +        if (len2 % 4 == 2) {
              +            static_section = offset2.slice(0, -3);
              +            offset2 = padding + "<span data-toggle='tooltip' data-placement='top' title='" + 
              +                Utils.from_base64("AAA" + static_section, alphabet).slice(2, -2) + "'>" +
              +                static_section + "</span>" +
              +                "<span class='hlgreen'>" + offset2.substr(offset2.length - 3, 1) + "</span>" +
              +                "<span class='hlred'>" + offset2.substr(offset2.length - 2) + "</span>";
              +        } else if (len2 % 4 == 3) {
              +            static_section = offset2.slice(0, -2);
              +            offset2 = padding + "<span data-toggle='tooltip' data-placement='top' title='" + 
              +                Utils.from_base64("AAA" + static_section, alphabet).slice(2, -2) + "'>" +
              +                static_section + "</span>" +
              +                "<span class='hlgreen'>" + offset2.substr(offset2.length - 2, 1) + "</span>" +
              +                "<span class='hlred'>" + offset2.substr(offset2.length - 1) + "</span>";
              +        } else {
              +            static_section = offset2;
              +            offset2 = padding +  "<span data-toggle='tooltip' data-placement='top' title='" + 
              +                Utils.from_base64("AAA" + static_section, alphabet).slice(2) + "'>" +
              +                static_section + "</span>";
              +        }
              +        
              +        if (!show_variable) {
              +            offset2 = static_section;
              +        }
              +        
              +        return (show_variable ? "Characters highlighted in <span class='hlgreen'>green</span> could change if the input is surrounded by more data." +
              +            "\nCharacters highlighted in <span class='hlred'>red</span> are for padding purposes only." +
              +            "\nUnhighlighted characters are <span data-toggle='tooltip' data-placement='top' title='Tooltip on left'>static</span>." +
              +            "\nHover over the static sections to see what they decode to on their own.\n" +
              +            "\nOffset 0: " + offset0 +
              +            "\nOffset 1: " + offset1 +
              +            "\nOffset 2: " + offset2 +
              +            script :
              +            offset0 + "\n" + offset1 + "\n" + offset2);
              +    },
              +    
              +    
              +    /**
              +     * Highlight to Base64
              +     *
              +     * @param {Object[]} pos
              +     * @param {number} pos[].start
              +     * @param {number} pos[].end
              +     * @param {Object[]} args
              +     * @returns {Object[]} pos
              +     */
              +    highlight_to: function(pos, args) {
              +        pos[0].start = Math.floor(pos[0].start / 3 * 4);
              +        pos[0].end = Math.ceil(pos[0].end / 3 * 4);
              +        return pos;
              +    },
              +    
              +    /**
              +     * Highlight from Base64
              +     *
              +     * @param {Object[]} pos
              +     * @param {number} pos[].start
              +     * @param {number} pos[].end
              +     * @param {Object[]} args
              +     * @returns {Object[]} pos
              +     */
              +    highlight_from: function(pos, args) {
              +        pos[0].start = Math.ceil(pos[0].start / 4 * 3);
              +        pos[0].end = Math.floor(pos[0].end / 4 * 3);
              +        return pos;
              +    },
              +    
              +};
              diff --git a/src/js/operations/BitwiseOp.js b/src/js/operations/BitwiseOp.js
              new file mode 100755
              index 00000000..1e4e5a1e
              --- /dev/null
              +++ b/src/js/operations/BitwiseOp.js
              @@ -0,0 +1,299 @@
              +/* globals CryptoJS */
              +
              +/**
              + * Bitwise operations.
              + *
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @namespace
              + */
              +var BitwiseOp = {
              +
              +    /**
              +     * Runs bitwise operations across the input data.
              +     *
              +     * @private
              +     * @param {byte_array} input
              +     * @param {byte_array} key
              +     * @param {function} func - The bitwise calculation to carry out
              +     * @param {boolean} null_preserving
              +     * @param {boolean} differential
              +     * @returns {byte_array}
              +     */
              +    _bit_op: function (input, key, func, null_preserving, differential) {
              +        if (!key || !key.length) key = [0];
              +        var result = [],
              +            x = null,
              +            k = null,
              +            o = null;
              +        
              +        for (var i = 0; i < input.length; i++) {
              +            k = key[i % key.length];
              +            o = input[i];
              +            x = null_preserving && (o === 0 || o == k) ? o : func(o, k);
              +            result.push(x);
              +            if (differential && !(null_preserving && (o === 0 || o == k))) {
              +                key[i % key.length] = x;
              +            }
              +        }
              +        
              +        return result;
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    XOR_PRESERVE_NULLS: false,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    XOR_DIFFERENTIAL: false,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    KEY_FORMAT: ["Hex", "Base64", "UTF8", "UTF16", "UTF16LE", "UTF16BE", "Latin1"],
              +    
              +    /**
              +     * XOR operation.
              +     *
              +     * @param {byte_array} input
              +     * @param {Object[]} args
              +     * @returns {byte_array}
              +     */
              +    run_xor: function (input, args) {
              +        var key = Utils.format[args[0].option].parse(args[0].string || ""),
              +            null_preserving = args[1],
              +            differential = args[2];
              +        
              +        key = Utils.word_array_to_byte_array(key);
              +            
              +        return BitwiseOp._bit_op(input, key, BitwiseOp._xor, null_preserving, differential);
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    XOR_BRUTE_KEY_LENGTH: ["1", "2"],
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    XOR_BRUTE_SAMPLE_LENGTH: 100,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    XOR_BRUTE_SAMPLE_OFFSET: 0,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    XOR_BRUTE_PRINT_KEY: true,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    XOR_BRUTE_OUTPUT_HEX: false,
              +    
              +    /**
              +     * XOR Brute Force operation.
              +     *
              +     * @param {byte_array} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_xor_brute: function (input, args) {
              +        var key_length = parseInt(args[0], 10),
              +            sample_length = args[1],
              +            sample_offset = args[2],
              +            null_preserving = args[3],
              +            differential = args[4],
              +            crib = args[5],
              +            print_key = args[6],
              +            output_hex = args[7],
              +            regex;
              +        
              +        var output = "",
              +            result,
              +            result_utf8;
              +        
              +        input = input.slice(sample_offset, sample_offset + sample_length);
              +        
              +        if (crib !== "") {
              +            regex = new RegExp(crib, "im");
              +        }
              +        
              +        
              +        for (var key = 1, l = Math.pow(256, key_length); key < l; key++) {
              +            result = BitwiseOp._bit_op(input, Utils.hex_to_byte_array(key.toString(16)), BitwiseOp._xor, null_preserving, differential);
              +            result_utf8 = Utils.byte_array_to_utf8(result);
              +            if (crib !== "" && result_utf8.search(regex) === -1) continue;
              +            if (print_key) output += "Key = " + Utils.hex(key, (2*key_length)) + ": ";
              +            if (output_hex)
              +                output += Utils.byte_array_to_hex(result) + "\n";
              +            else
              +                output += Utils.printable(result_utf8, false) + "\n";
              +            if (print_key) output += "\n";
              +        }
              +        return output;
              +    },
              +    
              +    
              +    /**
              +     * NOT operation.
              +     *
              +     * @param {byte_array} input
              +     * @param {Object[]} args
              +     * @returns {byte_array}
              +     */
              +    run_not: function (input, args) {
              +        return BitwiseOp._bit_op(input, null, BitwiseOp._not);
              +    },
              +    
              +    
              +    /**
              +     * AND operation.
              +     *
              +     * @param {byte_array} input
              +     * @param {Object[]} args
              +     * @returns {byte_array}
              +     */
              +    run_and: function (input, args) {
              +        var key = Utils.format[args[0].option].parse(args[0].string || "");
              +        key = Utils.word_array_to_byte_array(key);
              +        
              +        return BitwiseOp._bit_op(input, key, BitwiseOp._and);
              +    },
              +    
              +    
              +    /**
              +     * OR operation.
              +     *
              +     * @param {byte_array} input
              +     * @param {Object[]} args
              +     * @returns {byte_array}
              +     */
              +    run_or: function (input, args) {
              +        var key = Utils.format[args[0].option].parse(args[0].string || "");
              +        key = Utils.word_array_to_byte_array(key);
              +        
              +        return BitwiseOp._bit_op(input, key, BitwiseOp._or);
              +    },
              +    
              +    
              +    /**
              +     * ADD operation.
              +     *
              +     * @param {byte_array} input
              +     * @param {Object[]} args
              +     * @returns {byte_array}
              +     */
              +    run_add: function (input, args) {
              +        var key = Utils.format[args[0].option].parse(args[0].string || "");
              +        key = Utils.word_array_to_byte_array(key);
              +        
              +        return BitwiseOp._bit_op(input, key, BitwiseOp._add);
              +    },
              +    
              +    
              +    /**
              +     * SUB operation.
              +     *
              +     * @param {byte_array} input
              +     * @param {Object[]} args
              +     * @returns {byte_array}
              +     */
              +    run_sub: function (input, args) {
              +        var key = Utils.format[args[0].option].parse(args[0].string || "");
              +        key = Utils.word_array_to_byte_array(key);
              +        
              +        return BitwiseOp._bit_op(input, key, BitwiseOp._sub);
              +    },
              +    
              +    
              +    /**
              +     * XOR bitwise calculation.
              +     *
              +     * @private
              +     * @param {number} operand
              +     * @param {number} key
              +     * @returns {number}
              +     */
              +    _xor: function (operand, key) {
              +        return operand ^ key;
              +    },
              +    
              +    
              +    /**
              +     * NOT bitwise calculation.
              +     *
              +     * @private
              +     * @param {number} operand
              +     * @returns {number}
              +     */
              +    _not: function (operand, _) {
              +        return ~operand & 0xff;
              +    },
              +    
              +    
              +    /**
              +     * AND bitwise calculation.
              +     *
              +     * @private
              +     * @param {number} operand
              +     * @param {number} key
              +     * @returns {number}
              +     */
              +    _and: function (operand, key) {
              +        return operand & key;
              +    },
              +    
              +    
              +    /**
              +     * OR bitwise calculation.
              +     *
              +     * @private
              +     * @param {number} operand
              +     * @param {number} key
              +     * @returns {number}
              +     */
              +    _or: function (operand, key) {
              +        return operand | key;
              +    },
              +
              +    
              +    /**
              +     * ADD bitwise calculation.
              +     *
              +     * @private
              +     * @param {number} operand
              +     * @param {number} key
              +     * @returns {number}
              +     */
              +    _add: function (operand, key) {
              +        return (operand + key) % 256;
              +    },
              +
              +    
              +    /**
              +     * SUB bitwise calculation.
              +     *
              +     * @private
              +     * @param {number} operand
              +     * @param {number} key
              +     * @returns {number}
              +     */
              +    _sub: function (operand, key) {
              +        var result = operand - key;
              +        return (result < 0) ? 256 + result : result;
              +    },
              +
              +};
              diff --git a/src/js/operations/ByteRepr.js b/src/js/operations/ByteRepr.js
              new file mode 100755
              index 00000000..13a4b8a7
              --- /dev/null
              +++ b/src/js/operations/ByteRepr.js
              @@ -0,0 +1,394 @@
              +/* globals app */
              +
              +/**
              + * Byte representation operations.
              + *
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @namespace
              + */
              +var ByteRepr = {
              +
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    DELIM_OPTIONS: ["Space", "Comma", "Semi-colon", "Colon", "Line feed", "CRLF"],
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    HEX_DELIM_OPTIONS: ["Space", "Comma", "Semi-colon", "Colon", "Line feed", "CRLF", "0x", "\\x", "None"],
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    BIN_DELIM_OPTIONS: ["Space", "Comma", "Semi-colon", "Colon", "Line feed", "CRLF", "None"],
              +    
              +    /**
              +     * To Hex operation.
              +     *
              +     * @param {byte_array} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_to_hex: function(input, args) {
              +        var delim = Utils.char_rep[args[0] || "Space"];
              +        return Utils.to_hex(input, delim, 2);
              +    },
              +    
              +    
              +    /**
              +     * From Hex operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {byte_array}
              +     */
              +    run_from_hex: function(input, args) {
              +        var delim = args[0] || "Space";
              +        return Utils.from_hex(input, delim, 2);
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    CHARCODE_BASE: 16,
              +    
              +    /**
              +     * To Charcode operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_to_charcode: function(input, args) {
              +        var delim = Utils.char_rep[args[0] || "Space"],
              +            base = args[1],
              +            output = "",
              +            padding = 2,
              +            ordinal;
              +            
              +        if (base < 2 || base > 36) {
              +            throw "Error: Base argument must be between 2 and 36";
              +        }
              +            
              +        for (var i = 0; i < input.length; i++) {
              +            ordinal = Utils.ord(input[i]);
              +            
              +            if (base == 16) {
              +                if (ordinal < 256) padding = 2;
              +                else if (ordinal < 65536) padding = 4;
              +                else if (ordinal < 16777216) padding = 6;
              +                else if (ordinal < 4294967296) padding = 8;
              +                else padding = 2;
              +                
              +                if (padding > 2) app.options.attempt_highlight = false;
              +                
              +                output += Utils.hex(ordinal, padding) + delim;
              +            } else {
              +                app.options.attempt_highlight = false;
              +                output += ordinal.toString(base) + delim;
              +            }
              +        }
              +        
              +        return output.slice(0, -delim.length);
              +    },
              +    
              +    
              +    /**
              +     * From Charcode operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {byte_array}
              +     */
              +    run_from_charcode: function(input, args) {
              +        var delim = Utils.char_rep[args[0] || "Space"],
              +            base = args[1],
              +            bites = input.split(delim),
              +            i = 0;
              +            
              +        if (base < 2 || base > 36) {
              +            throw "Error: Base argument must be between 2 and 36";
              +        }
              +        
              +        if (base != 16) {
              +            app.options.attempt_highlight = false;
              +        }
              +        
              +        // Split into groups of 2 if the whole string is concatenated and 
              +        // too long to be a single character
              +        if (bites.length == 1 && input.length > 17) {
              +            bites = [];
              +            for (i = 0; i < input.length; i += 2) {
              +                bites.push(input.slice(i, i+2));
              +            }
              +        }
              +        
              +        var latin1 = "";
              +        for (i = 0; i < bites.length; i++) {
              +            latin1 += Utils.chr(parseInt(bites[i], base));
              +        }
              +        return Utils.str_to_byte_array(latin1);
              +    },
              +    
              +    
              +    /**
              +     * Highlight to hex
              +     *
              +     * @param {Object[]} pos
              +     * @param {number} pos[].start
              +     * @param {number} pos[].end
              +     * @param {Object[]} args
              +     * @returns {Object[]} pos
              +     */
              +    highlight_to: function(pos, args) {
              +        var delim = Utils.char_rep[args[0] || "Space"],
              +            len = delim == "\r\n" ? 1 : delim.length;
              +            
              +        pos[0].start = pos[0].start * (2 + len);
              +        pos[0].end = pos[0].end * (2 + len) - len;
              +        
              +        // 0x and \x are added to the beginning if they are selected, so increment the positions accordingly
              +        if (delim == "0x" || delim == "\\x") {
              +            pos[0].start += 2;
              +            pos[0].end   += 2;
              +        }
              +        return pos;
              +    },
              +    
              +    
              +    /**
              +     * Highlight to hex
              +     *
              +     * @param {Object[]} pos
              +     * @param {number} pos[].start
              +     * @param {number} pos[].end
              +     * @param {Object[]} args
              +     * @returns {Object[]} pos
              +     */
              +    highlight_from: function(pos, args) {
              +        var delim = Utils.char_rep[args[0] || "Space"],
              +            len = delim == "\r\n" ? 1 : delim.length,
              +            width = len + 2;
              +        
              +        // 0x and \x are added to the beginning if they are selected, so increment the positions accordingly
              +        if (delim == "0x" || delim == "\\x") {
              +            if (pos[0].start > 1) pos[0].start -= 2;
              +            else pos[0].start = 0;
              +            if (pos[0].end > 1) pos[0].end -= 2;
              +            else pos[0].end = 0;
              +        }
              +        
              +        pos[0].start = pos[0].start === 0 ? 0 : Math.round(pos[0].start / width);
              +        pos[0].end = pos[0].end === 0 ? 0 : Math.ceil(pos[0].end / width);
              +        return pos;
              +    },
              +    
              +    
              +    /**
              +     * To Decimal operation.
              +     *
              +     * @param {byte_array} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_to_decimal: function(input, args) {
              +        var delim = Utils.char_rep[args[0]];
              +        return input.join(delim);
              +    },
              +    
              +    
              +    /**
              +     * From Decimal operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {byte_array}
              +     */
              +    run_from_decimal: function(input, args) {
              +        var delim = Utils.char_rep[args[0]];
              +        var byte_str = input.split(delim), output = [];
              +        if (byte_str[byte_str.length-1] === "")
              +            byte_str = byte_str.slice(0, byte_str.length-1);
              +        
              +        for (var i = 0; i < byte_str.length; i++) {
              +            output[i] = parseInt(byte_str[i]);
              +        }
              +        return output;
              +    },
              +    
              +    
              +    /**
              +     * To Binary operation.
              +     *
              +     * @param {byte_array} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_to_binary: function(input, args) {
              +        var delim = Utils.char_rep[args[0] || "Space"],
              +            output = "",
              +            padding = 8;
              +            
              +        for (var i = 0; i < input.length; i++) {
              +            output += Utils.pad(input[i].toString(2), padding) + delim;
              +        }
              +        
              +        if (delim.length) {
              +            return output.slice(0, -delim.length);
              +        } else {
              +            return output;
              +        }
              +    },
              +    
              +    
              +    /**
              +     * From Binary operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {byte_array}
              +     */
              +    run_from_binary: function(input, args) {
              +        if (args[0] != "None") {
              +            var delim_regex = Utils.regex_rep[args[0] || "Space"];
              +            input = input.replace(delim_regex, '');
              +        }
              +        
              +        var output = [];
              +        var byte_len = 8;
              +        for (var i = 0; i < input.length; i += byte_len) {
              +            output.push(parseInt(input.substr(i, byte_len), 2));
              +        }
              +        return output;
              +    },
              +    
              +    
              +    /**
              +     * Highlight to binary
              +     *
              +     * @param {Object[]} pos
              +     * @param {number} pos[].start
              +     * @param {number} pos[].end
              +     * @param {Object[]} args
              +     * @returns {Object[]} pos
              +     */
              +    highlight_to_binary: function(pos, args) {
              +        var delim = Utils.char_rep[args[0] || "Space"];
              +        pos[0].start = pos[0].start * (8 + delim.length);
              +        pos[0].end = pos[0].end * (8 + delim.length) - delim.length;
              +        return pos;
              +    },
              +    
              +    
              +    /**
              +     * Highlight from binary
              +     *
              +     * @param {Object[]} pos
              +     * @param {number} pos[].start
              +     * @param {number} pos[].end
              +     * @param {Object[]} args
              +     * @returns {Object[]} pos
              +     */
              +    highlight_from_binary: function(pos, args) {
              +        var delim = Utils.char_rep[args[0] || "Space"];
              +        pos[0].start = pos[0].start === 0 ? 0 : Math.floor(pos[0].start / (8 + delim.length));
              +        pos[0].end = pos[0].end === 0 ? 0 : Math.ceil(pos[0].end / (8 + delim.length));
              +        return pos;
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    HEX_CONTENT_CONVERT_WHICH: ["Only special chars", "Only special chars including spaces", "All chars"],
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    HEX_CONTENT_SPACES_BETWEEN_BYTES: false,
              +    
              +    /**
              +     * To Hex Content operation.
              +     *
              +     * @param {byte_array} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_to_hex_content: function(input, args) {
              +        var convert = args[0];
              +        var spaces = args[1];
              +        if (convert == "All chars") {
              +            var result = "|" + Utils.to_hex(input) + "|";
              +            if (!spaces) result = result.replace(/ /g, "");
              +            return result;
              +        }
              +        
              +        var output = "",
              +            in_hex = false,
              +            convert_spaces = convert == "Only special chars including spaces",
              +            b;
              +        for (var i = 0; i < input.length; i++) {
              +            b = input[i];
              +            if ((b == 32 && convert_spaces) || (b < 48 && b != 32) || (b > 57 && b < 65) || (b > 90 && b < 97) || b > 122) {
              +                if (!in_hex) {
              +                    output += "|";
              +                    in_hex = true;
              +                } else if (spaces) output += " ";
              +                output += Utils.to_hex([b]);
              +            } else {
              +                if (in_hex) {
              +                    output += "|";
              +                    in_hex = false;
              +                }
              +                output += Utils.chr(input[i]);
              +            }
              +        }
              +        if (in_hex) output += "|";
              +        return output;
              +    },
              +    
              +    
              +    /**
              +     * From Hex Content operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {byte_array}
              +     */
              +    run_from_hex_content: function(input, args) {
              +        var regex = /\|([a-f\d ]{2,})\|/gi;
              +        var output = [], m, i = 0;
              +        while (!!(m = regex.exec(input))) {
              +            // Add up to match
              +            for (; i < m.index;)
              +                output.push(Utils.ord(input[i++]));
              +            
              +            // Add match
              +            var bytes = Utils.from_hex(m[1]);
              +            if (bytes) {
              +                for (var a = 0; a < bytes.length;)
              +                    output.push(bytes[a++]);
              +            } else {
              +                // Not valid hex, print as normal
              +                for (; i < regex.lastIndex;)
              +                    output.push(Utils.ord(input[i++]));
              +            }
              +            
              +            i = regex.lastIndex;
              +        }
              +        // Add all after final match
              +        for (; i < input.length;)
              +            output.push(Utils.ord(input[i++]));
              +        
              +        return output;
              +    },
              +
              +};
              diff --git a/src/js/operations/CharEnc.js b/src/js/operations/CharEnc.js
              new file mode 100755
              index 00000000..6085d19a
              --- /dev/null
              +++ b/src/js/operations/CharEnc.js
              @@ -0,0 +1,46 @@
              +/* globals CryptoJS */
              +
              +/**
              + * Character encoding operations.
              + *
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @namespace
              + */
              +var CharEnc = {
              +
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    IO_FORMAT: ["UTF8", "UTF16", "UTF16LE", "UTF16BE", "Latin1", "Windows-1251", "Hex", "Base64"],
              +    
              +    /**
              +     * Text encoding operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run: function(input, args) {
              +        var input_format = args[0],
              +            output_format = args[1];
              +            
              +        if (input_format == "Windows-1251") {
              +            input = Utils.win1251_to_unicode(input);
              +            input = CryptoJS.enc.Utf8.parse(input);
              +        } else {
              +            input = Utils.format[input_format].parse(input);
              +        }
              +        
              +        if (output_format == "Windows-1251") {
              +            input = CryptoJS.enc.Utf8.stringify(input);
              +            return Utils.unicode_to_win1251(input);
              +        } else {
              +            return Utils.format[output_format].stringify(input);
              +        }
              +    },
              +    
              +};
              diff --git a/src/js/operations/Checksum.js b/src/js/operations/Checksum.js
              new file mode 100755
              index 00000000..f0069bad
              --- /dev/null
              +++ b/src/js/operations/Checksum.js
              @@ -0,0 +1,130 @@
              +/**
              + * Checksum operations.
              + *
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @namespace
              + */
              +var Checksum = {
              +
              +    /**
              +     * Fletcher-16 Checksum operation.
              +     *
              +     * @param {byte_array} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_fletcher16: function(input, args) {
              +        var a = 0,
              +            b = 0;
              +        
              +        for (var i = 0; i < input.length; i++) {
              +            a = (a + input[i]) % 0xff;
              +            b = (b + a) % 0xff;
              +        }
              +        
              +        return Utils.hex(((b << 8) | a) >>> 0, 4);
              +    },
              +    
              +    
              +    /**
              +     * Adler-32 Checksum operation.
              +     *
              +     * @param {byte_array} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_adler32: function(input, args) {
              +        var MOD_ADLER = 65521,
              +            a = 1,
              +            b = 0;
              +        
              +        for (var i = 0; i < input.length; i++) {
              +            a += input[i];
              +            b += a;
              +        }
              +        
              +        a %= MOD_ADLER;
              +        b %= MOD_ADLER;
              +        
              +        return Utils.hex(((b << 16) | a) >>> 0, 8);
              +    },
              +    
              +    
              +    /**
              +     * CRC-32 Checksum operation.
              +     *
              +     * @param {byte_array} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_crc32: function(input, args) {
              +        var crc_table = window.crc_table || (window.crc_table = Checksum._gen_crc_table()),
              +            crc = 0 ^ (-1);
              +        
              +        for (var i = 0; i < input.length; i++) {
              +            crc = (crc >>> 8) ^ crc_table[(crc ^ input[i]) & 0xff];
              +        }
              +        
              +        return Utils.hex((crc ^ (-1)) >>> 0);
              +    },
              +    
              +    
              +    /**
              +     * TCP/IP Checksum operation.
              +     *
              +     * @author GCHQ Contributor [1]
              +     * @param {byte_array} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     *
              +     * @example
              +     * // returns '3f2c'
              +     * Checksum.run_tcp_ip([0x45,0x00,0x00,0x87,0xa3,0x1b,0x40,0x00,0x40,0x06,
              +     *                      0x00,0x00,0xac,0x11,0x00,0x04,0xac,0x11,0x00,0x03])
              +     *
              +     * // returns 'a249'
              +     * Checksum.run_tcp_ip([0x45,0x00,0x01,0x11,0x3f,0x74,0x40,0x00,0x40,0x06,
              +     *                      0x00,0x00,0xac,0x11,0x00,0x03,0xac,0x11,0x00,0x04])
              +     */
              +    run_tcp_ip: function(input, args) {
              +        var csum = 0;
              +        
              +        for (var i = 0; i < input.length; i++) {
              +            if(i % 2 === 0) {
              +                csum += (input[i] << 8);
              +            } else {
              +                csum += input[i];
              +            }
              +        }
              +
              +        csum = (csum >> 16) + (csum & 0xffff);
              +
              +        return Utils.hex(0xffff - csum);
              +    },
              +    
              +    
              +    /**
              +     * Generates a CRC table for use with CRC checksums.
              +     *
              +     * @private
              +     * @returns {array}
              +     */
              +    _gen_crc_table: function() {
              +        var c,
              +            crc_table = [];
              +        
              +        for (var n = 0; n < 256; n++) {
              +            c = n;
              +            for (var k = 0; k < 8; k++) {
              +                c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));
              +            }
              +            crc_table[n] = c;
              +        }
              +        
              +        return crc_table;
              +    },
              +
              +};
              diff --git a/src/js/operations/Cipher.js b/src/js/operations/Cipher.js
              new file mode 100755
              index 00000000..94193546
              --- /dev/null
              +++ b/src/js/operations/Cipher.js
              @@ -0,0 +1,429 @@
              +/* globals CryptoJS, blowfish */
              +
              +/**
              + * Cipher operations.
              + *
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @namespace
              + */
              +var Cipher = {
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    IO_FORMAT1: ["Hex", "Base64", "UTF8", "UTF16", "UTF16LE", "UTF16BE", "Latin1"],
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    IO_FORMAT2: ["UTF8", "UTF16", "UTF16LE", "UTF16BE", "Latin1", "Hex", "Base64"],
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    IO_FORMAT3: ["Hex", "Base64", "UTF16", "UTF16LE", "UTF16BE", "Latin1"],
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    IO_FORMAT4: ["Latin1", "UTF8", "UTF16", "UTF16LE", "UTF16BE", "Hex", "Base64"],
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    MODES: ["CBC", "CFB", "CTR", "OFB", "ECB"],
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    PADDING: ["Pkcs7", "Iso97971", "AnsiX923", "Iso10126", "ZeroPadding", "NoPadding"],
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    RESULT_TYPE: ["Show all", "Ciphertext", "Key", "IV", "Salt"],
              +    
              +    
              +    /**
              +     * Runs encryption operations using the CryptoJS framework.
              +     *
              +     * @private
              +     * @param {function} algo - The CryptoJS algorithm to use
              +     * @param {byte_array} input
              +     * @param {function} args
              +     * @returns {string}
              +     */
              +    _enc: function (algo, input, args) {
              +        var key = Utils.format[args[0].option].parse(args[0].string || ""),
              +            iv = Utils.format[args[1].option].parse(args[1].string || ""),
              +            salt = Utils.format[args[2].option].parse(args[2].string || ""),
              +            mode = CryptoJS.mode[args[3]],
              +            padding = CryptoJS.pad[args[4]],
              +            result_option = args[5].toLowerCase(),
              +            output_format = args[6];
              +        
              +        if (iv.sigBytes === 0) {
              +            // Use passphrase rather than key. Need to convert it to a string.
              +            key = key.toString(CryptoJS.enc.Latin1);
              +        }
              +        
              +        var encrypted = algo.encrypt(input, key, {
              +            salt: salt.sigBytes > 0 ? salt : false,
              +            iv: iv.sigBytes > 0 ? iv : null,
              +            mode: mode,
              +            padding: padding
              +        });
              +        
              +        var result = "";
              +        if (result_option == "show all") {
              +            result += "Key:  " + encrypted.key.toString(Utils.format[output_format]);
              +            result += "\nIV:   " + encrypted.iv.toString(Utils.format[output_format]);
              +            if (encrypted.salt) result += "\nSalt: " + encrypted.salt.toString(Utils.format[output_format]);
              +            result += "\n\nCiphertext: " + encrypted.ciphertext.toString(Utils.format[output_format]);
              +        } else {
              +            result = encrypted[result_option].toString(Utils.format[output_format]);
              +        }
              +        
              +        return result;
              +    },
              +    
              +    
              +    /**
              +     * Runs decryption operations using the CryptoJS framework.
              +     *
              +     * @private
              +     * @param {function} algo - The CryptoJS algorithm to use
              +     * @param {byte_array} input
              +     * @param {function} args
              +     * @returns {string}
              +     */
              +    _dec: function (algo, input, args) {
              +        var key = Utils.format[args[0].option].parse(args[0].string || ""),
              +            iv = Utils.format[args[1].option].parse(args[1].string || ""),
              +            salt = Utils.format[args[2].option].parse(args[2].string || ""),
              +            mode = CryptoJS.mode[args[3]],
              +            padding = CryptoJS.pad[args[4]],
              +            input_format = args[5],
              +            output_format = args[6];
              +        
              +        // The ZeroPadding option causes a crash when the input length is 0
              +        if (!input.length) {
              +            return "No input";
              +        } 
              +        
              +        var ciphertext = Utils.format[input_format].parse(input);
              +        
              +        if (iv.sigBytes === 0) {
              +            // Use passphrase rather than key. Need to convert it to a string.
              +            key = key.toString(CryptoJS.enc.Latin1);
              +        }
              +        
              +        var decrypted = algo.decrypt({
              +                ciphertext: ciphertext,
              +                salt: salt.sigBytes > 0 ? salt : false
              +            }, key, {
              +                iv: iv.sigBytes > 0 ? iv : null,
              +                mode: mode,
              +                padding: padding
              +            });
              +        
              +        var result;
              +        try {
              +            result = decrypted.toString(Utils.format[output_format]);
              +        } catch (err) {
              +            result = "Decrypt error: " + err.message;
              +        }
              +        
              +        return result;
              +    },
              +    
              +    
              +    /**
              +     * AES Encrypt operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_aes_enc: function (input, args) {
              +        return Cipher._enc(CryptoJS.AES, input, args);
              +    },
              +    
              +    
              +    /**
              +     * AES Decrypt operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_aes_dec: function (input, args) {
              +        return Cipher._dec(CryptoJS.AES, input, args);
              +    },
              +    
              +    
              +    /**
              +     * DES Encrypt operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_des_enc: function (input, args) {
              +        return Cipher._enc(CryptoJS.DES, input, args);
              +    },
              +    
              +    
              +    /**
              +     * DES Decrypt operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_des_dec: function (input, args) {
              +        return Cipher._dec(CryptoJS.DES, input, args);
              +    },
              +    
              +    
              +    /**
              +     * Triple DES Encrypt operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_triple_des_enc: function (input, args) {
              +        return Cipher._enc(CryptoJS.TripleDES, input, args);
              +    },
              +    
              +    
              +    /**
              +     * Triple DES Decrypt operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_triple_des_dec: function (input, args) {
              +        return Cipher._dec(CryptoJS.TripleDES, input, args);
              +    },
              +    
              +    
              +    /**
              +     * Rabbit Encrypt operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_rabbit_enc: function (input, args) {
              +        return Cipher._enc(CryptoJS.Rabbit, input, args);
              +    },
              +    
              +    
              +    /**
              +     * Rabbit Decrypt operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_rabbit_dec: function (input, args) {
              +        return Cipher._dec(CryptoJS.Rabbit, input, args);
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    BLOWFISH_MODES: ["ECB", "CBC", "PCBC", "CFB", "OFB", "CTR"],
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    BLOWFISH_OUTPUT_TYPES: ["Base64", "Hex", "String", "Raw"],
              +    
              +    /**
              +     * Blowfish Encrypt operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_blowfish_enc: function (input, args) {
              +        var key = Utils.format[args[0].option].parse(args[0].string).toString(Utils.format.Latin1),
              +            mode = args[1],
              +            output_format = args[2];
              +            
              +        if (key.length === 0) return "Enter a key";
              +        
              +        var enc_hex = blowfish.encrypt(input, key, {
              +                outputType: 1,
              +                cipherMode: Cipher.BLOWFISH_MODES.indexOf(mode)
              +            }),
              +            enc = CryptoJS.enc.Hex.parse(enc_hex);
              +            
              +        return enc.toString(Utils.format[output_format]);
              +    },
              +    
              +    
              +    /**
              +     * Blowfish Decrypt operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_blowfish_dec: function (input, args) {
              +        var key = Utils.format[args[0].option].parse(args[0].string).toString(Utils.format.Latin1),
              +            mode = args[1],
              +            input_format = args[2];
              +            
              +        if (key.length === 0) return "Enter a key";
              +        
              +        input = Utils.format[input_format].parse(input);
              +        
              +        return blowfish.decrypt(input.toString(CryptoJS.enc.Base64), key, {
              +            outputType: 0, // This actually means inputType. The library is weird.
              +            cipherMode: Cipher.BLOWFISH_MODES.indexOf(mode)
              +        });
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    KDF_KEY_SIZE: 256,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    KDF_ITERATIONS: 1,
              +    
              +    /**
              +     * Derive PBKDF2 key operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_pbkdf2: function (input, args) {
              +        var key_size = args[0] / 32,
              +            iterations = args[1],
              +            salt = CryptoJS.enc.Hex.parse(args[2] || ""),
              +            input_format = args[3],
              +            output_format = args[4],
              +            passphrase = Utils.format[input_format].parse(input),
              +            key = CryptoJS.PBKDF2(passphrase, salt, { keySize: key_size, iterations: iterations });
              +        
              +        return key.toString(Utils.format[output_format]);
              +    },
              +    
              +    
              +    /**
              +     * Derive EVP key operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_evpkdf: function (input, args) {
              +        var key_size = args[0] / 32,
              +            iterations = args[1],
              +            salt = CryptoJS.enc.Hex.parse(args[2] || ""),
              +            input_format = args[3],
              +            output_format = args[4],
              +            passphrase = Utils.format[input_format].parse(input),
              +            key = CryptoJS.EvpKDF(passphrase, salt, { keySize: key_size, iterations: iterations });
              +        
              +        return key.toString(Utils.format[output_format]);
              +    },
              +    
              +    
              +    /**
              +     * RC4 operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_rc4: function (input, args) {
              +        var message = Utils.format[args[1]].parse(input),
              +            passphrase = Utils.format[args[0].option].parse(args[0].string),
              +            encrypted = CryptoJS.RC4.encrypt(message, passphrase);
              +            
              +        return encrypted.ciphertext.toString(Utils.format[args[2]]);
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    RC4DROP_BYTES: 768,
              +    
              +    /**
              +     * RC4 Drop operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_rc4drop: function (input, args) {
              +        var message = Utils.format[args[1]].parse(input),
              +            passphrase = Utils.format[args[0].option].parse(args[0].string),
              +            drop = args[3],
              +            encrypted = CryptoJS.RC4Drop.encrypt(message, passphrase, { drop: drop });
              +            
              +        return encrypted.ciphertext.toString(Utils.format[args[2]]);
              +    },
              +    
              +};
              +
              +
              +/**
              + * Overwriting the CryptoJS OpenSSL key derivation function so that it is possible to not pass a
              + * salt in.
              + 
              + * @param {string} password - The password to derive from.
              + * @param {number} keySize - The size in words of the key to generate.
              + * @param {number} ivSize - The size in words of the IV to generate.
              + * @param {WordArray|string} salt (Optional) A 64-bit salt to use. If omitted, a salt will be
              + *                 generated randomly. If set to false, no salt will be added.
              + *
              + * @returns {CipherParams} A cipher params object with the key, IV, and salt.
              + *
              + * @static
              + *
              + * @example
              + * // Randomly generates a salt
              + * var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32);
              + * // Uses the salt 'saltsalt'
              + * var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32, 'saltsalt');
              + * // Does not use a salt
              + * var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32, false);
              + */
              +CryptoJS.kdf.OpenSSL.execute = function (password, keySize, ivSize, salt) {
              +    // Generate random salt if no salt specified and not set to false
              +    // This line changed from `if (!salt) {` to the following
              +    if (salt === undefined || salt === null) {
              +        salt = CryptoJS.lib.WordArray.random(64/8);
              +    }
              +
              +    // Derive key and IV
              +    var key = CryptoJS.algo.EvpKDF.create({ keySize: keySize + ivSize }).compute(password, salt);
              +
              +    // Separate key and IV
              +    var iv = CryptoJS.lib.WordArray.create(key.words.slice(keySize), ivSize * 4);
              +    key.sigBytes = keySize * 4;
              +
              +    // Return params
              +    return CryptoJS.lib.CipherParams.create({ key: key, iv: iv, salt: salt });
              +};
              diff --git a/src/js/operations/Code.js b/src/js/operations/Code.js
              new file mode 100755
              index 00000000..3b59a9bc
              --- /dev/null
              +++ b/src/js/operations/Code.js
              @@ -0,0 +1,305 @@
              +/* globals prettyPrintOne, vkbeautify */
              +
              +/**
              + * Code operations.
              + *
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @namespace
              + */
              +var Code = {
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    LANGUAGES: ["default-code", "default-markup", "bash", "bsh", "c", "cc", "coffee", "cpp", "cs", "csh", "cv", "cxx", "cyc", "htm", "html", "in.tag", "java", "javascript", "js", "json", "m", "mxml", "perl", "pl", "pm", "py", "python", "rb", "rc", "rs", "ruby", "rust", "sh", "uq.val", "xhtml", "xml", "xsl"],
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    LINE_NUMS: false,
              +    
              +    /**
              +     * Syntax highlighter operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {html}
              +     */
              +    run_syntax_highlight: function(input, args) {
              +        var language = args[0],
              +            line_nums = args[1];
              +        return "<code class='prettyprint'>" + prettyPrintOne(Utils.escape_html(input), language, line_nums) + "</code>";
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    BEAUTIFY_INDENT: "\\t",
              +    
              +    /**
              +     * XML Beautify operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_xml_beautify: function(input, args) {
              +        var indent_str = args[0];
              +        return vkbeautify.xml(input, indent_str);
              +    },
              +    
              +    
              +    /**
              +     * JSON Beautify operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_json_beautify: function(input, args) {
              +        var indent_str = args[0];
              +        return vkbeautify.json(input, indent_str);
              +    },
              +    
              +    
              +    /**
              +     * CSS Beautify operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_css_beautify: function(input, args) {
              +        var indent_str = args[0];
              +        return vkbeautify.css(input, indent_str);
              +    },
              +    
              +    
              +    /**
              +     * SQL Beautify operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_sql_beautify: function(input, args) {
              +        var indent_str = args[0];
              +        return vkbeautify.sql(input, indent_str);
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    PRESERVE_COMMENTS: false,
              +    
              +    /**
              +     * XML Minify operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_xml_minify: function(input, args) {
              +        var preserve_comments = args[0];
              +        return vkbeautify.xmlmin(input, preserve_comments);
              +    },
              +    
              +    
              +    /**
              +     * JSON Minify operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_json_minify: function(input, args) {
              +        return vkbeautify.jsonmin(input);
              +    },
              +    
              +    
              +    /**
              +     * CSS Minify operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_css_minify: function(input, args) {
              +        var preserve_comments = args[0];
              +        return vkbeautify.cssmin(input, preserve_comments);
              +    },
              +    
              +    
              +    /**
              +     * SQL Minify operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_sql_minify: function(input, args) {
              +        return vkbeautify.sqlmin(input);
              +    },
              +    
              +    
              +    /**
              +     * Generic Code Beautify operation.
              +     *
              +     * Yeeeaaah...
              +     *
              +     * I'm not proud of this code, but seriously, try writing a generic lexer and parser that
              +     * correctly generates an AST for multiple different languages. I have tried, and I can tell
              +     * you it's pretty much impossible.
              +     * 
              +     * This basically works. That'll have to be good enough. It's not meant to produce working code,
              +     * just slightly more readable code.
              +     * 
              +     * Things that don't work:
              +     *  - For loop formatting
              +     *  - Do-While loop formatting
              +     *  - Switch/Case indentation
              +     *  - Bit shift operators
              +     *
              +     * @author n1474335 [n1474335@gmail.com]
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_generic_beautify: function(input, args) {
              +        var code = input,
              +            t = 0,
              +            preserved_tokens = [],
              +            m;
              +        
              +        // Remove strings
              +        var sstrings = /'([^'\\]|\\.)*'/g;
              +        while (!!(m = sstrings.exec(code))) {
              +            code = preserve_token(code, m, t++);
              +            sstrings.lastIndex = m.index;
              +        }
              +            
              +        var dstrings = /"([^"\\]|\\.)*"/g;
              +        while (!!(m = dstrings.exec(code))) {
              +            code = preserve_token(code, m, t++);
              +            dstrings.lastIndex = m.index;
              +        }
              +        
              +        // Remove comments
              +        var scomments = /\/\/[^\n\r]*/g;
              +        while (!!(m = scomments.exec(code))) {
              +            code = preserve_token(code, m, t++);
              +            scomments.lastIndex = m.index;
              +        }
              +            
              +        var mcomments = /\/\*[\s\S]*?\*\//gm;
              +        while (!!(m = mcomments.exec(code))) {
              +            code = preserve_token(code, m, t++);
              +            mcomments.lastIndex = m.index;
              +        }
              +        
              +        var hcomments = /(^|\n)#[^\n\r#]+/g;
              +        while (!!(m = hcomments.exec(code))) {
              +            code = preserve_token(code, m, t++);
              +            hcomments.lastIndex = m.index;
              +        }
              +            
              +        // Remove regexes
              +        var regexes = /\/.*?[^\\]\/[gim]{0,3}/gi;
              +        while (!!(m = regexes.exec(code))) {
              +            code = preserve_token(code, m, t++);
              +            regexes.lastIndex = m.index;
              +        }
              +        
              +        // Create newlines after ;
              +        code = code.replace(/;/g, ";\n");
              +        
              +        // Create newlines after { and around }
              +        code = code.replace(/{/g, "{\n");
              +        code = code.replace(/}/g, "\n}\n");
              +        
              +        // Remove carriage returns
              +        code = code.replace(/\r/g, "");
              +        
              +        // Remove all indentation
              +        code = code.replace(/^\s+/g, "");
              +        code = code.replace(/\n\s+/g, "\n");
              +        
              +        // Remove trailing spaces
              +        code = code.replace(/\s*$/g, "");
              +        
              +        // Remove newlines before {
              +        code = code.replace(/\n{/g, "{");
              +        
              +        // Indent
              +        var i = 0,
              +            level = 0;
              +        while (i < code.length) {
              +            switch(code[i]) {
              +                case "{":
              +                    level++;
              +                    break;
              +                case "\n":
              +                    if (i+1 >= code.length) break;
              +                    
              +                    if (code[i+1] == "}") level--;
              +                    var indent = (level >= 0) ? Array(level*4+1).join(" ") : "";
              +                        
              +                    code = code.substring(0, i+1) + indent + code.substring(i+1);
              +                    if (level > 0) i += level*4;
              +                    break;
              +            }
              +            i++;
              +        }
              +
              +        // Add strategic spaces
              +        code = code.replace(/\s*([!<>=+-/*]?)=\s*/g, " $1= ");
              +        code = code.replace(/\s*<([=]?)\s*/g, " <$1 ");
              +        code = code.replace(/\s*>([=]?)\s*/g, " >$1 ");
              +        code = code.replace(/([^+])\+([^+=])/g, "$1 + $2");
              +        code = code.replace(/([^-])-([^-=])/g, "$1 - $2");
              +        code = code.replace(/([^*])\*([^*=])/g, "$1 * $2");
              +        code = code.replace(/([^/])\/([^/=])/g, "$1 / $2");
              +        code = code.replace(/\s*,\s*/g, ", ");
              +        code = code.replace(/\s*{/g, " {");
              +        code = code.replace(/}\n/g, "}\n\n");
              +        
              +        // Just... don't look at this
              +        code = code.replace(/(if|for|while|with|elif|elseif)\s*\(([^\n]*)\)\s*\n([^{])/gim, "$1 ($2)\n    $3");
              +        code = code.replace(/(if|for|while|with|elif|elseif)\s*\(([^\n]*)\)([^{])/gim, "$1 ($2) $3");
              +        code = code.replace(/else\s*\n([^{])/gim, "else\n    $1");
              +        code = code.replace(/else\s+([^{])/gim, "else $1");
              +        
              +        // Remove strategic spaces
              +        code = code.replace(/\s+;/g, ";");
              +        code = code.replace(/\{\s+\}/g, "{}");
              +        code = code.replace(/\[\s+\]/g, "[]");
              +        code = code.replace(/}\s*(else|catch|except|finally|elif|elseif|else if)/gi, "} $1");
              +        
              +        
              +        // Replace preserved tokens
              +        var ptokens = /###preserved_token(\d+)###/g;
              +        while (!!(m = ptokens.exec(code))) {
              +            var ti = parseInt(m[1]);
              +            code = code.substring(0, m.index) + preserved_tokens[ti] + code.substring(m.index + m[0].length);
              +            ptokens.lastIndex = m.index;
              +        }
              +
              +        return code;
              +        
              +        function preserve_token(str, match, t) {
              +            preserved_tokens[t] = match[0];
              +            return str.substring(0, match.index) +
              +                "###preserved_token" + t + "###" +
              +                str.substring(match.index + match[0].length);
              +        }
              +    },
              +
              +};
              diff --git a/src/js/operations/Compress.js b/src/js/operations/Compress.js
              new file mode 100755
              index 00000000..b5d5de0f
              --- /dev/null
              +++ b/src/js/operations/Compress.js
              @@ -0,0 +1,349 @@
              +/* globals Zlib, bzip2 */
              +
              +/**
              + * Compression operations.
              + *
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @namespace
              + */
              +var Compress = {
              +
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    COMPRESSION_TYPE: ["Dynamic Huffman Coding", "Fixed Huffman Coding", "None (Store)"],
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    INFLATE_BUFFER_TYPE: ["Adaptive", "Block"],
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    COMPRESSION_METHOD: ["Deflate", "None (Store)"],
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    OS: ["MSDOS", "Unix", "Macintosh"],
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    RAW_COMPRESSION_TYPE_LOOKUP: {
              +        "Fixed Huffman Coding"   : Zlib.RawDeflate.CompressionType.FIXED,
              +        "Dynamic Huffman Coding" : Zlib.RawDeflate.CompressionType.DYNAMIC,
              +        "None (Store)"           : Zlib.RawDeflate.CompressionType.NONE,
              +    },
              +    
              +    /**
              +     * Raw Deflate operation.
              +     *
              +     * @param {byte_array} input
              +     * @param {Object[]} args
              +     * @returns {byte_array}
              +     */
              +    run_raw_deflate: function(input, args) {
              +        var deflate = new Zlib.RawDeflate(input, {
              +            compressionType: Compress.RAW_COMPRESSION_TYPE_LOOKUP[args[0]]
              +        });
              +        return Array.prototype.slice.call(deflate.compress());
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    INFLATE_INDEX: 0,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    INFLATE_BUFFER_SIZE: 0,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    INFLATE_RESIZE: false,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    INFLATE_VERIFY: false,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    RAW_BUFFER_TYPE_LOOKUP: {
              +        "Adaptive"  : Zlib.RawInflate.BufferType.ADAPTIVE,
              +        "Block"     : Zlib.RawInflate.BufferType.BLOCK,
              +    },
              +    
              +    /**
              +     * Raw Inflate operation.
              +     *
              +     * @param {byte_array} input
              +     * @param {Object[]} args
              +     * @returns {byte_array}
              +     */
              +    run_raw_inflate: function(input, args) {
              +        // Deal with character encoding issues
              +        input = Utils.str_to_byte_array(Utils.byte_array_to_utf8(input));
              +        var inflate = new Zlib.RawInflate(input, {
              +                index: args[0],
              +                bufferSize: args[1],
              +                bufferType: Compress.RAW_BUFFER_TYPE_LOOKUP[args[2]],
              +                resize: args[3],
              +                verify: args[4]
              +            }),
              +            result = Array.prototype.slice.call(inflate.decompress());
              +        
              +        // Raw Inflate somethimes messes up and returns nonsense like this:
              +        // ]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]...
              +        // e.g. Input data of [8b, 1d, dc, 44]
              +        // Look for the first two square brackets:
              +        if (result.length > 158 && result[0] == 93 && result[5] == 93) {
              +            // If the first two square brackets are there, check that the others
              +            // are also there. If they are, throw an error. If not, continue.
              +            var valid = false;
              +            for (var i = 0; i < 155; i += 5) {
              +                if (result[i] != 93) {
              +                    valid = true;
              +                }
              +            }
              +            
              +            if (!valid) {
              +                throw "Error: Unable to inflate data";
              +            }
              +        }
              +        // Trust me, this is the easiest way...
              +        return result;
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    ZLIB_COMPRESSION_TYPE_LOOKUP: {
              +        "Fixed Huffman Coding"   : Zlib.Deflate.CompressionType.FIXED,
              +        "Dynamic Huffman Coding" : Zlib.Deflate.CompressionType.DYNAMIC,
              +        "None (Store)"           : Zlib.Deflate.CompressionType.NONE,
              +    },
              +    
              +    /**
              +     * Zlib Deflate operation.
              +     *
              +     * @param {byte_array} input
              +     * @param {Object[]} args
              +     * @returns {byte_array}
              +     */
              +    run_zlib_deflate: function(input, args) {
              +        var deflate = new Zlib.Deflate(input, {
              +            compressionType: Compress.ZLIB_COMPRESSION_TYPE_LOOKUP[args[0]]
              +        });
              +        return Array.prototype.slice.call(deflate.compress());
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    ZLIB_BUFFER_TYPE_LOOKUP: {
              +        "Adaptive" : Zlib.Inflate.BufferType.ADAPTIVE,
              +        "Block"    : Zlib.Inflate.BufferType.BLOCK,
              +    },
              +    
              +    /**
              +     * Zlib Inflate operation.
              +     *
              +     * @param {byte_array} input
              +     * @param {Object[]} args
              +     * @returns {byte_array}
              +     */
              +    run_zlib_inflate: function(input, args) {
              +        // Deal with character encoding issues
              +        input = Utils.str_to_byte_array(Utils.byte_array_to_utf8(input));
              +        var inflate = new Zlib.Inflate(input, {
              +                index: args[0],
              +                bufferSize: args[1],
              +                bufferType: Compress.ZLIB_BUFFER_TYPE_LOOKUP[args[2]],
              +                resize: args[3],
              +                verify: args[4]
              +            });
              +        return Array.prototype.slice.call(inflate.decompress());
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    GZIP_CHECKSUM: false,
              +    
              +    /**
              +     * Gzip operation.
              +     *
              +     * @param {byte_array} input
              +     * @param {Object[]} args
              +     * @returns {byte_array}
              +     */
              +    run_gzip: function(input, args) {
              +        var filename = args[1],
              +            comment = args[2],
              +            options = {
              +                deflateOptions: {
              +                    compressionType: Compress.ZLIB_COMPRESSION_TYPE_LOOKUP[args[0]]
              +                },
              +                flags: {
              +                    fhcrc: args[3]
              +                }
              +            };
              +        
              +        if (filename.length) {
              +            options.flags.fname = true;
              +            options.filename = filename;
              +        }
              +        if (comment.length) {
              +            options.flags.fcommenct = true;
              +            options.comment = comment;
              +        }
              +        
              +        var gzip = new Zlib.Gzip(input, options);
              +        return Array.prototype.slice.call(gzip.compress());
              +    },
              +    
              +    
              +    /**
              +     * Gunzip operation.
              +     *
              +     * @param {byte_array} input
              +     * @param {Object[]} args
              +     * @returns {byte_array}
              +     */
              +    run_gunzip: function(input, args) {
              +        // Deal with character encoding issues
              +        input = Utils.str_to_byte_array(Utils.byte_array_to_utf8(input));
              +        var gunzip = new Zlib.Gunzip(input);
              +        return Array.prototype.slice.call(gunzip.decompress());
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    PKZIP_FILENAME: "file.txt",
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    ZIP_COMPRESSION_METHOD_LOOKUP: {
              +        "Deflate"      : Zlib.Zip.CompressionMethod.DEFLATE,
              +        "None (Store)" : Zlib.Zip.CompressionMethod.STORE
              +    },
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    ZIP_OS_LOOKUP: {
              +        "MSDOS"     : Zlib.Zip.OperatingSystem.MSDOS,
              +        "Unix"      : Zlib.Zip.OperatingSystem.UNIX,
              +        "Macintosh" : Zlib.Zip.OperatingSystem.MACINTOSH
              +    },
              +    
              +    /**
              +     * Zip operation.
              +     *
              +     * @param {byte_array} input
              +     * @param {Object[]} args
              +     * @returns {byte_array}
              +     */
              +    run_pkzip: function(input, args) {
              +        var password = Utils.str_to_byte_array(args[2]),
              +            options = {
              +                filename: Utils.str_to_byte_array(args[0]),
              +                comment: Utils.str_to_byte_array(args[1]),
              +                compressionMethod: Compress.ZIP_COMPRESSION_METHOD_LOOKUP[args[3]],
              +                os: Compress.ZIP_OS_LOOKUP[args[4]],
              +                deflateOption: {
              +                    compressionType: Compress.ZLIB_COMPRESSION_TYPE_LOOKUP[args[5]]
              +                },
              +            },
              +            zip = new Zlib.Zip();
              +            
              +        if (password.length)
              +            zip.setPassword(password);
              +        zip.addFile(input, options);
              +        return Array.prototype.slice.call(zip.compress());
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    PKUNZIP_VERIFY: false,
              +    
              +    /**
              +     * Unzip operation.
              +     *
              +     * @param {byte_array} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_pkunzip: function(input, args) {
              +        var options = {
              +                password: Utils.str_to_byte_array(args[0]),
              +                verify: args[1]
              +            },
              +            file = "",
              +            unzip = new Zlib.Unzip(input, options),
              +            filenames = unzip.getFilenames(),
              +            output = "<div style='padding: 5px;'>" + filenames.length + " file(s) found</div>\n";
              +            
              +        output += "<div class='panel-group' id='zip-accordion' role='tablist' aria-multiselectable='true'>";
              +        
              +        window.uzip = unzip;
              +        for (var i = 0; i < filenames.length; i++) {
              +            file = Utils.byte_array_to_utf8(unzip.decompress(filenames[i]));
              +            output += "<div class='panel panel-default'>" +
              +                "<div class='panel-heading' role='tab' id='heading" + i + "'>" +
              +                "<h4 class='panel-title'>" +
              +                "<a class='collapsed' role='button' data-toggle='collapse' data-parent='#zip-accordion' href='#collapse" + i +
              +                "' aria-expanded='true' aria-controls='collapse" + i + "'>" +
              +                filenames[i] + "<span class='pull-right'>" + file.length.toLocaleString() + " bytes</span></a></h4></div>" +
              +                "<div id='collapse" + i + "' class='panel-collapse collapse' role='tabpanel' aria-labelledby='heading" + i + "'>" +
              +                "<div class='panel-body'>" +
              +                Utils.escape_html(file) + "</div></div></div>";
              +        }
              +        
              +        return output + "</div>";
              +    },
              +    
              +    
              +    /**
              +     * Bzip2 Decompress operation.
              +     *
              +     * @param {byte_array} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_bzip2_decompress: function(input, args) {
              +        var compressed = new Uint8Array(input),
              +            bzip2_reader,
              +            plain = "";
              +            
              +        bzip2_reader = bzip2.array(compressed);
              +        plain = bzip2.simple(bzip2_reader);
              +        return plain;
              +    },
              +    
              +};
              diff --git a/src/js/operations/Convert.js b/src/js/operations/Convert.js
              new file mode 100755
              index 00000000..e47ca684
              --- /dev/null
              +++ b/src/js/operations/Convert.js
              @@ -0,0 +1,412 @@
              +/**
              + * Unit conversion operations.
              + *
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @namespace
              + */
              +var Convert = {
              +
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    DISTANCE_UNITS: [
              +        "[Metric]", "Nanometres (nm)", "Micrometres (µm)", "Millimetres (mm)", "Centimetres (cm)", "Metres (m)", "Kilometers (km)", "[/Metric]",
              +        "[Imperial]", "Thou (th)", "Inches (in)", "Feet (ft)", "Yards (yd)", "Chains (ch)", "Furlongs (fur)", "Miles (mi)", "Leagues (lea)", "[/Imperial]",
              +        "[Maritime]", "Fathoms (ftm)", "Cables", "Nautical miles", "[/Maritime]",
              +        "[Comparisons]", "Cars (4m)", "Buses (8.4m)", "American football fields (91m)", "Football pitches (105m)", "[/Comparisons]",
              +        "[Astronomical]", "Earth-to-Moons", "Earth's equators", "Astronomical units (au)", "Light-years (ly)", "Parsecs (pc)", "[/Astronomical]",
              +    ],
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    DISTANCE_FACTOR: { // Multiples of a metre
              +        "Nanometres (nm)"   : 1e-9,
              +        "Micrometres (µm)"  : 1e-6,
              +        "Millimetres (mm)"  : 1e-3,
              +        "Centimetres (cm)"  : 1e-2,
              +        "Metres (m)"        : 1,
              +        "Kilometers (km)"   : 1e3,
              +        
              +        "Thou (th)"         : 0.0000254,
              +        "Inches (in)"       : 0.0254,
              +        "Feet (ft)"         : 0.3048,
              +        "Yards (yd)"        : 0.9144,
              +        "Chains (ch)"       : 20.1168,
              +        "Furlongs (fur)"    : 201.168,
              +        "Miles (mi)"        : 1609.344,
              +        "Leagues (lea)"     : 4828.032,
              +        
              +        "Fathoms (ftm)"     : 1.853184,
              +        "Cables"            : 185.3184,
              +        "Nautical miles"    : 1853.184,
              +        
              +        "Cars (4m)"         : 4,
              +        "Buses (8.4m)"      : 8.4,
              +        "American football fields (91m)": 91,
              +        "Football pitches (105m)": 105,
              +        
              +        "Earth-to-Moons"    : 380000000, 
              +        "Earth's equators"  : 40075016.686,
              +        "Astronomical units (au)": 149597870700,
              +        "Light-years (ly)"  : 9460730472580800,
              +        "Parsecs (pc)"      : 3.0856776e16
              +    },
              +    
              +    /**
              +     * Convert distance operation.
              +     *
              +     * @param {number} input
              +     * @param {Object[]} args
              +     * @returns {number}
              +     */
              +    run_distance: function (input, args) {
              +        var input_units = args[0],
              +            output_units = args[1];
              +            
              +        input = input * Convert.DISTANCE_FACTOR[input_units];
              +        return input / Convert.DISTANCE_FACTOR[output_units];
              +        // TODO Remove rounding errors (e.g. 1.000000000001)
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    DATA_UNITS: [
              +        "Bits (b)", "Nibbles", "Octets", "Bytes (B)",
              +        "[Binary bits (2^n)]", "Kibibits (Kib)", "Mebibits (Mib)", "Gibibits (Gib)", "Tebibits (Tib)", "Pebibits (Pib)", "Exbibits (Eib)", "Zebibits (Zib)", "Yobibits (Yib)", "[/Binary bits (2^n)]",
              +        "[Decimal bits (10^n)]", "Decabits", "Hectobits", "Kilobits (kb)", "Megabits (Mb)", "Gigabits (Gb)", "Terabits (Tb)", "Petabits (Pb)", "Exabits (Eb)", "Zettabits (Zb)", "Yottabits (Yb)", "[/Decimal bits (10^n)]",
              +        "[Binary bytes (8 x 2^n)]", "Kibibytes (KiB)", "Mebibytes (MiB)", "Gibibytes (GiB)", "Tebibytes (TiB)", "Pebibytes (PiB)", "Exbibytes (EiB)", "Zebibytes (ZiB)", "Yobibytes (YiB)", "[/Binary bytes (8 x 2^n)]",
              +        "[Decimal bytes (8 x 10^n)]", "Kilobytes (KB)", "Megabytes (MB)", "Gigabytes (GB)", "Terabytes (TB)", "Petabytes (PB)", "Exabytes (EB)", "Zettabytes (ZB)", "Yottabytes (YB)", "[/Decimal bytes (8 x 10^n)]"
              +    ],
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    DATA_FACTOR: { // Multiples of a bit
              +        "Bits (b)"        : 1,
              +        "Nibbles"         : 4,
              +        "Octets"          : 8,
              +        "Bytes (B)"       : 8,
              +        
              +        // Binary bits (2^n)
              +        "Kibibits (Kib)"  : 1024,
              +        "Mebibits (Mib)"  : 1048576,
              +        "Gibibits (Gib)"  : 1073741824,
              +        "Tebibits (Tib)"  : 1099511627776,
              +        "Pebibits (Pib)"  : 1125899906842624,
              +        "Exbibits (Eib)"  : 1152921504606846976,
              +        "Zebibits (Zib)"  : 1180591620717411303424,
              +        "Yobibits (Yib)"  : 1208925819614629174706176,
              +        
              +        // Decimal bits (10^n)
              +        "Decabits"        : 10,
              +        "Hectobits"       : 100,
              +        "Kilobits (Kb)"   : 1e3,
              +        "Megabits (Mb)"   : 1e6,
              +        "Gigabits (Gb)"   : 1e9,
              +        "Terabits (Tb)"   : 1e12,
              +        "Petabits (Pb)"   : 1e15,
              +        "Exabits (Eb)"    : 1e18,
              +        "Zettabits (Zb)"  : 1e21,
              +        "Yottabits (Yb)"  : 1e24,
              +        
              +        // Binary bytes (8 x 2^n)
              +        "Kibibytes (KiB)" : 8192,
              +        "Mebibytes (MiB)" : 8388608,
              +        "Gibibytes (GiB)" : 8589934592,
              +        "Tebibytes (TiB)" : 8796093022208,
              +        "Pebibytes (PiB)" : 9007199254740992,
              +        "Exbibytes (EiB)" : 9223372036854775808,
              +        "Zebibytes (ZiB)" : 9444732965739290427392,
              +        "Yobibytes (YiB)" : 9671406556917033397649408,
              +        
              +        // Decimal bytes (8 x 10^n)
              +        "Kilobytes (KB)"  : 8e3,
              +        "Megabytes (MB)"  : 8e6,
              +        "Gigabytes (GB)"  : 8e9,
              +        "Terabytes (TB)"  : 8e12,
              +        "Petabytes (PB)"  : 8e15,
              +        "Exabytes (EB)"   : 8e18,
              +        "Zettabytes (ZB)" : 8e21,
              +        "Yottabytes (YB)" : 8e24,
              +    },
              +    
              +    /**
              +     * Convert data units operation.
              +     *
              +     * @param {number} input
              +     * @param {Object[]} args
              +     * @returns {number}
              +     */
              +    run_data_size: function (input, args) {
              +        var input_units = args[0],
              +            output_units = args[1];
              +            
              +        input = input * Convert.DATA_FACTOR[input_units];
              +        return input / Convert.DATA_FACTOR[output_units];
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    AREA_UNITS: [
              +        "[Metric]", "Square metre (sq m)", "Square kilometre (sq km)", "Centiare (ca)", "Deciare (da)", "Are (a)", "Decare (daa)", "Hectare (ha)", "[/Metric]",
              +        "[Imperial]", "Square inch (sq in)", "Square foot (sq ft)", "Square yard (sq yd)", "Square mile (sq mi)", "Perch (sq per)", "Rood (ro)", "International acre (ac)", "[/Imperial]",
              +        "[US customary units]", "US survey acre (ac)", "US survey square mile (sq mi)", "US survey township", "[/US customary units]",
              +        "[Nuclear physics]", "Yoctobarn (yb)", "Zeptobarn (zb)", "Attobarn (ab)", "Femtobarn (fb)", "Picobarn (pb)", "Nanobarn (nb)", "Microbarn (μb)", "Millibarn (mb)", "Barn (b)", "Kilobarn (kb)", "Megabarn (Mb)", "Outhouse", "Shed", "Planck area", "[/Nuclear physics]",
              +        "[Comparisons]", "Washington D.C.", "Isle of Wight", "Wales", "Texas", "[/Comparisons]",
              +    ],
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    AREA_FACTOR: { // Multiples of a square metre
              +        // Metric
              +        "Square metre (sq m)"       : 1,
              +        "Square kilometre (sq km)"  : 1e6,
              +        
              +        "Centiare (ca)"             : 1,
              +        "Deciare (da)"              : 10,
              +        "Are (a)"                   : 100,
              +        "Decare (daa)"              : 1e3,
              +        "Hectare (ha)"              : 1e4,
              +        
              +        // Imperial
              +        "Square inch (sq in)"       : 0.00064516,
              +        "Square foot (sq ft)"       : 0.09290304,
              +        "Square yard (sq yd)"       : 0.83612736,
              +        "Square mile (sq mi)"       : 2589988.110336,
              +        "Perch (sq per)"            : 42.21,
              +        "Rood (ro)"                 : 1011,
              +        "International acre (ac)"   : 4046.8564224,
              +        
              +        // US customary units
              +        "US survey acre (ac)"       : 4046.87261,
              +        "US survey square mile (sq mi)" : 2589998.470305239,
              +        "US survey township"        : 93239944.9309886,
              +        
              +        // Nuclear physics
              +        "Yoctobarn (yb)"            : 1e-52,
              +        "Zeptobarn (zb)"            : 1e-49,
              +        "Attobarn (ab)"             : 1e-46,
              +        "Femtobarn (fb)"            : 1e-43,
              +        "Picobarn (pb)"             : 1e-40,
              +        "Nanobarn (nb)"             : 1e-37,
              +        "Microbarn (μb)"            : 1e-34,
              +        "Millibarn (mb)"            : 1e-31,
              +        "Barn (b)"                  : 1e-28,
              +        "Kilobarn (kb)"             : 1e-25,
              +        "Megabarn (Mb)"             : 1e-22,
              +        
              +        "Planck area"               : 2.6e-70,
              +        "Shed"                      : 1e-52,
              +        "Outhouse"                  : 1e-34,
              +        
              +        // Comparisons
              +        "Washington D.C."           : 176119191.502848,
              +        "Isle of Wight"             : 380000000,
              +        "Wales"                     : 20779000000,
              +        "Texas"                     : 696241000000,
              +    },
              +    
              +    /**
              +     * Convert area operation.
              +     *
              +     * @param {number} input
              +     * @param {Object[]} args
              +     * @returns {number}
              +     */
              +    run_area: function (input, args) {
              +        var input_units = args[0],
              +            output_units = args[1];
              +            
              +        input = input * Convert.AREA_FACTOR[input_units];
              +        return input / Convert.AREA_FACTOR[output_units];
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    MASS_UNITS: [
              +        "[Metric]", "Yoctogram (yg)", "Zeptogram (zg)", "Attogram (ag)", "Femtogram (fg)", "Picogram (pg)", "Nanogram (ng)", "Microgram (μg)", "Milligram (mg)", "Centigram (cg)", "Decigram (dg)", "Gram (g)", "Decagram (dag)", "Hectogram (hg)", "Kilogram (kg)", "Megagram (Mg)", "Tonne (t)", "Gigagram (Gg)", "Teragram (Tg)", "Petagram (Pg)", "Exagram (Eg)", "Zettagram (Zg)", "Yottagram (Yg)", "[/Metric]",
              +        "[Imperial Avoirdupois]", "Grain (gr)", "Dram (dr)", "Ounce (oz)", "Pound (lb)", "Nail", "Stone (st)", "Quarter (gr)", "Tod", "US hundredweight (cwt)", "Imperial hundredweight (cwt)", "US ton (t)", "Imperial ton (t)", "[/Imperial Avoirdupois]",
              +        "[Imperial Troy]", "Grain (gr)", "Pennyweight (dwt)", "Troy dram (dr t)", "Troy ounce (oz t)", "Troy pound (lb t)", "Mark", "[/Imperial Troy]",
              +        "[Archaic]", "Wey", "Wool wey", "Suffolk wey", "Wool sack", "Coal sack", "Load", "Last", "Flax or feather last", "Gunpowder last", "Picul", "Rice last", "[/Archaic]",
              +        "[Comparisons]", "Big Ben (14 tonnes)", "Blue whale (180 tonnes)", "International Space Station (417 tonnes)", "Space Shuttle (2,041 tonnes)", "RMS Titanic (52,000 tonnes)", "Great Pyramid of Giza (6,000,000 tonnes)", "Earth's oceans (1.4 yottagrams)", "[/Comparisons]",
              +        "[Astronomical]", "A teaspoon of neutron star (5,500 million tonnes)", "Lunar mass (ML)", "Earth mass (M⊕)", "Jupiter mass (MJ)", "Solar mass (M☉)", "Sagittarius A* (7.5 x 10^36 kgs-ish)", "Milky Way galaxy (1.2 x 10^42 kgs)", "The observable universe (1.45 x 10^53 kgs)", "[/Astronomical]",
              +    ],
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    MASS_FACTOR: { // Multiples of a gram
              +        // Metric
              +        "Yoctogram (yg)"    : 1e-24,
              +        "Zeptogram (zg)"    : 1e-21,
              +        "Attogram (ag)"     : 1e-18,
              +        "Femtogram (fg)"    : 1e-15,
              +        "Picogram (pg)"     : 1e-12,
              +        "Nanogram (ng)"     : 1e-9,
              +        "Microgram (μg)"    : 1e-6,
              +        "Milligram (mg)"    : 1e-3,
              +        "Centigram (cg)"    : 1e-2,
              +        "Decigram (dg)"     : 1e-1,
              +        "Gram (g)"          : 1,
              +        "Decagram (dag)"    : 10,
              +        "Hectogram (hg)"    : 100,
              +        "Kilogram (kg)"     : 1000,
              +        "Megagram (Mg)"     : 1e6,
              +        "Tonne (t)"         : 1e6,
              +        "Gigagram (Gg)"     : 1e9,
              +        "Teragram (Tg)"     : 1e12,
              +        "Petagram (Pg)"     : 1e15,
              +        "Exagram (Eg)"      : 1e18,
              +        "Zettagram (Zg)"    : 1e21,
              +        "Yottagram (Yg)"    : 1e24,
              +        
              +        // Imperial Avoirdupois
              +        "Grain (gr)"        : 64.79891e-3,
              +        "Dram (dr)"         : 1.7718451953125,
              +        "Ounce (oz)"        : 28.349523125,
              +        "Pound (lb)"        : 453.59237,
              +        "Nail"              : 3175.14659,
              +        "Stone (st)"        : 6.35029318e3,
              +        "Quarter (gr)"      : 12700.58636,
              +        "Tod"               : 12700.58636,
              +        "US hundredweight (cwt)" : 45.359237e3,
              +        "Imperial hundredweight (cwt)" : 50.80234544e3,
              +        "US ton (t)"        : 907.18474e3,
              +        "Imperial ton (t)"  : 1016.0469088e3,
              +        
              +        // Imperial Troy
              +        "Pennyweight (dwt)" : 1.55517384,
              +        "Troy dram (dr t)"  : 3.8879346,
              +        "Troy ounce (oz t)" : 31.1034768,
              +        "Troy pound (lb t)" : 373.2417216,
              +        "Mark"              : 248.8278144,
              +        
              +        // Archaic
              +        "Wey"               : 76.5e3,
              +        "Wool wey"          : 101.7e3,
              +        "Suffolk wey"       : 161.5e3,
              +        "Wool sack"         : 153000,
              +        "Coal sack"         : 50.80234544e3,
              +        "Load"              : 918000,
              +        "Last"              : 1836000,
              +        "Flax or feather last" : 770e3,
              +        "Gunpowder last"    : 1090e3,
              +        "Picul"             : 60.478982e3,
              +        "Rice last"         : 1200e3,
              +        
              +        // Comparisons
              +        "Big Ben (14 tonnes)"                      : 14e6,
              +        "Blue whale (180 tonnes)"                  : 180e6,
              +        "International Space Station (417 tonnes)" : 417e6,
              +        "Space Shuttle (2,041 tonnes)"             : 2041e6,
              +        "RMS Titanic (52,000 tonnes)"              : 52000e6,
              +        "Great Pyramid of Giza (6,000,000 tonnes)" : 6e12,
              +        "Earth's oceans (1.4 yottagrams)"          : 1.4e24,
              +        
              +        // Astronomical
              +        "A teaspoon of neutron star (5,500 million tonnes)" : 5.5e15,
              +        "Lunar mass (ML)"                          : 7.342e25,
              +        "Earth mass (M⊕)"                          : 5.97219e27,
              +        "Jupiter mass (MJ)"                        : 1.8981411476999997e30,
              +        "Solar mass (M☉)"                         : 1.98855e33,
              +        "Sagittarius A* (7.5 x 10^36 kgs-ish)"     : 7.5e39,
              +        "Milky Way galaxy (1.2 x 10^42 kgs)"       : 1.2e45,
              +        "The observable universe (1.45 x 10^53 kgs)" : 1.45e56,
              +    },
              +    
              +    /**
              +     * Convert mass operation.
              +     *
              +     * @param {number} input
              +     * @param {Object[]} args
              +     * @returns {number}
              +     */
              +    run_mass: function (input, args) {
              +        var input_units = args[0],
              +            output_units = args[1];
              +            
              +        input = input * Convert.MASS_FACTOR[input_units];
              +        return input / Convert.MASS_FACTOR[output_units];
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    SPEED_UNITS: [
              +        "[Metric]", "Metres per second (m/s)", "Kilometres per hour (km/h)", "[/Metric]",
              +        "[Imperial]", "Miles per hour (mph)", "Knots (kn)", "[/Imperial]",
              +        "[Comparisons]", "Human hair growth rate", "Bamboo growth rate", "World's fastest snail", "Usain Bolt's top speed", "Jet airliner cruising speed", "Concorde", "SR-71 Blackbird", "Space Shuttle", "International Space Station", "[/Comparisons]",
              +        "[Scientific]", "Sound in standard atmosphere", "Sound in water", "Lunar escape velocity", "Earth escape velocity", "Earth's solar orbit", "Solar system's Milky Way orbit", "Milky Way relative to the cosmic microwave background", "Solar escape velocity", "Neutron star escape velocity (0.3c)", "Light in a diamond (0.4136c)", "Signal in an optical fibre (0.667c)", "Light (c)", "[/Scientific]",
              +    ],
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    SPEED_FACTOR: { // Multiples of m/s
              +        // Metric
              +        "Metres per second (m/s)"        : 1,
              +        "Kilometres per hour (km/h)"     : 0.2778,
              +        
              +        // Imperial
              +        "Miles per hour (mph)"           : 0.44704,
              +        "Knots (kn)"                     : 0.5144,
              +        
              +        // Comparisons
              +        "Human hair growth rate"         : 4.8e-9,
              +        "Bamboo growth rate"             : 1.4e-5,
              +        "World's fastest snail"          : 0.00275,
              +        "Usain Bolt's top speed"         : 12.42,
              +        "Jet airliner cruising speed"    : 250,
              +        "Concorde"                       : 603,
              +        "SR-71 Blackbird"                : 981,
              +        "Space Shuttle"                  : 1400,
              +        "International Space Station"    : 7700,
              +        
              +        // Scientific
              +        "Sound in standard atmosphere"   : 340.3,
              +        "Sound in water"                 : 1500,
              +        "Lunar escape velocity"          : 2375,
              +        "Earth escape velocity"          : 11200,
              +        "Earth's solar orbit"            : 29800,
              +        "Solar system's Milky Way orbit" : 200000,
              +        "Milky Way relative to the cosmic microwave background" : 552000,
              +        "Solar escape velocity"          : 617700,
              +        "Neutron star escape velocity (0.3c)" : 100000000,
              +        "Light in a diamond (0.4136c)"   : 124000000,
              +        "Signal in an optical fibre (0.667c)" : 200000000,
              +        "Light (c)"                      : 299792458,
              +    },
              +    
              +    /**
              +     * Convert speed operation.
              +     *
              +     * @param {number} input
              +     * @param {Object[]} args
              +     * @returns {number}
              +     */
              +    run_speed: function (input, args) {
              +        var input_units = args[0],
              +            output_units = args[1];
              +            
              +        input = input * Convert.SPEED_FACTOR[input_units];
              +        return input / Convert.SPEED_FACTOR[output_units];
              +    },
              +    
              +};
              diff --git a/src/js/operations/DateTime.js b/src/js/operations/DateTime.js
              new file mode 100755
              index 00000000..d1f3843a
              --- /dev/null
              +++ b/src/js/operations/DateTime.js
              @@ -0,0 +1,454 @@
              +/* globals moment */
              +
              +/**
              + * Date and time operations.
              + *
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @namespace
              + */
              +var DateTime = {
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    UNITS: ["Seconds (s)", "Milliseconds (ms)", "Microseconds (μs)", "Nanoseconds (ns)"],
              +    
              +    /**
              +     * From UNIX Timestamp operation.
              +     *
              +     * @param {number} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_from_unix_timestamp: function(input, args) {
              +        var units = args[0],
              +            d;
              +        
              +        input = parseFloat(input);
              +        
              +        if (units == "Seconds (s)") {
              +            d = moment.unix(input);
              +            return d.tz("UTC").format("ddd D MMMM YYYY HH:mm:ss") + " UTC";
              +        } else if (units == "Milliseconds (ms)") {
              +            d = moment(input);
              +            return d.tz("UTC").format("ddd D MMMM YYYY HH:mm:ss.SSS") + " UTC";
              +        } else if (units == "Microseconds (μs)") {
              +            d = moment(input / 1000);
              +            return d.tz("UTC").format("ddd D MMMM YYYY HH:mm:ss.SSS") + " UTC";
              +        } else if (units == "Nanoseconds (ns)") {
              +            d = moment(input / 1000000);
              +            return d.tz("UTC").format("ddd D MMMM YYYY HH:mm:ss.SSS") + " UTC";
              +        } else {
              +            throw "Unrecognised unit";
              +        }
              +    },
              +    
              +    
              +    /**
              +     * To UNIX Timestamp operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {number}
              +     */
              +    run_to_unix_timestamp: function(input, args) {
              +        var units = args[0],
              +            d = moment(input);
              +        
              +        if (units == "Seconds (s)") {
              +            return d.unix();
              +        } else if (units == "Milliseconds (ms)") {
              +            return d.valueOf();
              +        } else if (units == "Microseconds (μs)") {
              +            return d.valueOf() * 1000;
              +        } else if (units == "Nanoseconds (ns)") {
              +            return d.valueOf() * 1000000;
              +        } else {
              +            throw "Unrecognised unit";
              +        }
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    DATETIME_FORMATS: [
              +        {
              +            name: "Standard date and time",
              +            value: "DD/MM/YYYY HH:mm:ss"
              +        },
              +        {
              +            name: "American-style date and time",
              +            value: "MM/DD/YYYY HH:mm:ss"
              +        },
              +        {
              +            name: "International date and time",
              +            value: "YYYY-MM-DD HH:mm:ss"
              +        },
              +        {
              +            name: "Verbose date and time",
              +            value: "dddd Do MMMM YYYY HH:mm:ss Z z"
              +        },
              +        {
              +            name: "UNIX timestamp (seconds)",
              +            value: "X"
              +        },
              +        {
              +            name: "UNIX timestamp offset (milliseconds)",
              +            value: "x"
              +        },
              +        {
              +            name: "Automatic",
              +            value: ""
              +        },
              +    ],
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    INPUT_FORMAT_STRING: "DD/MM/YYYY HH:mm:ss",
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    OUTPUT_FORMAT_STRING: "dddd Do MMMM YYYY HH:mm:ss Z z",
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    TIMEZONES: ["UTC"].concat(moment.tz.names()),
              +    
              +    /**
              +     * Translate DateTime Format operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {html}
              +     */
              +    run_translate_format: function(input, args) {
              +        var input_format = args[1],
              +            input_timezone = args[2],
              +            output_format = args[3],
              +            output_timezone = args[4],
              +            date;
              +
              +        try {
              +            date = moment.tz(input, input_format, input_timezone);
              +            if (!date || date.format() == "Invalid date") throw Error;
              +        } catch(err) {
              +            return "Invalid format.\n\n" + DateTime.FORMAT_EXAMPLES;
              +        }
              +        
              +        return date.tz(output_timezone).format(output_format);
              +    },
              +    
              +    
              +    /**
              +     * Parse DateTime operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {html}
              +     */
              +    run_parse: function(input, args) {
              +        var input_format = args[1],
              +            input_timezone = args[2],
              +            date,
              +            output = "";
              +            
              +        try {
              +            date = moment.tz(input, input_format, input_timezone);
              +            if (!date || date.format() == "Invalid date") throw Error;
              +        } catch(err) {
              +            return "Invalid format.\n\n" + DateTime.FORMAT_EXAMPLES;
              +        }
              +        
              +        output += "Date: " + date.format("dddd Do MMMM YYYY") +
              +            "\nTime: " + date.format("HH:mm:ss") +
              +            "\nPeriod: " + date.format("A") +
              +            "\nTimezone: " + date.format("z") +
              +            "\nUTC offset: " + date.format("ZZ") +
              +            "\n\nDaylight Saving Time: " + date.isDST() +
              +            "\nLeap year: " + date.isLeapYear() +
              +            "\nDays in this month: " + date.daysInMonth() +
              +            "\n\nDay of year: " + date.dayOfYear() +
              +            "\nWeek number: " + date.weekYear() +
              +            "\nQuarter: " + date.quarter();
              +        
              +        return output;
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     */
              +    FORMAT_EXAMPLES: "Format string tokens:\n\n\
              +<table class='table table-striped table-hover table-condensed table-bordered' style='font-family: sans-serif'>\
              +  <thead>\
              +    <tr>\
              +      <th>Category</th>\
              +      <th>Token</th>\
              +      <th>Output</th>\
              +    </tr>\
              +  </thead>\
              +  <tbody>\
              +    <tr>\
              +      <td><b>Month</b></td>\
              +      <td>M</td>\
              +      <td>1 2 ... 11 12</td>\
              +    </tr>\
              +    <tr>\
              +      <td></td>\
              +      <td>Mo</td>\
              +      <td>1st 2nd ... 11th 12th</td>\
              +    </tr>\
              +    <tr>\
              +      <td></td>\
              +      <td>MM</td>\
              +      <td>01 02 ... 11 12</td>\
              +    </tr>\
              +    <tr>\
              +      <td></td>\
              +      <td>MMM</td>\
              +      <td>Jan Feb ... Nov Dec</td>\
              +    </tr>\
              +    <tr>\
              +      <td></td>\
              +      <td>MMMM</td>\
              +      <td>January February ... November December</td>\
              +    </tr>\
              +    <tr>\
              +      <td><b>Quarter</b></td>\
              +      <td>Q</td>\
              +      <td>1 2 3 4</td>\
              +    </tr>\
              +    <tr>\
              +      <td><b>Day of Month</b></td>\
              +      <td>D</td>\
              +      <td>1 2 ... 30 31</td>\
              +    </tr>\
              +    <tr>\
              +      <td></td>\
              +      <td>Do</td>\
              +      <td>1st 2nd ... 30th 31st</td>\
              +    </tr>\
              +    <tr>\
              +      <td></td>\
              +      <td>DD</td>\
              +      <td>01 02 ... 30 31</td>\
              +    </tr>\
              +    <tr>\
              +      <td><b>Day of Year</b></td>\
              +      <td>DDD</td>\
              +      <td>1 2 ... 364 365</td>\
              +    </tr>\
              +    <tr>\
              +      <td></td>\
              +      <td>DDDo</td>\
              +      <td>1st 2nd ... 364th 365th</td>\
              +    </tr>\
              +    <tr>\
              +      <td></td>\
              +      <td>DDDD</td>\
              +      <td>001 002 ... 364 365</td>\
              +    </tr>\
              +    <tr>\
              +      <td><b>Day of Week</b></td>\
              +      <td>d</td>\
              +      <td>0 1 ... 5 6</td>\
              +    </tr>\
              +    <tr>\
              +      <td></td>\
              +      <td>do</td>\
              +      <td>0th 1st ... 5th 6th</td>\
              +    </tr>\
              +    <tr>\
              +      <td></td>\
              +      <td>dd</td>\
              +      <td>Su Mo ... Fr Sa</td>\
              +    </tr>\
              +    <tr>\
              +      <td></td>\
              +      <td>ddd</td>\
              +      <td>Sun Mon ... Fri Sat</td>\
              +    </tr>\
              +    <tr>\
              +      <td></td>\
              +      <td>dddd</td>\
              +      <td>Sunday Monday ... Friday Saturday</td>\
              +    </tr>\
              +    <tr>\
              +      <td><b>Day of Week (Locale)</b></td>\
              +      <td>e</td>\
              +      <td>0 1 ... 5 6</td>\
              +    </tr>\
              +    <tr>\
              +      <td><b>Day of Week (ISO)</b></td>\
              +      <td>E</td>\
              +      <td>1 2 ... 6 7</td>\
              +    </tr>\
              +    <tr>\
              +      <td><b>Week of Year</b></td>\
              +      <td>w</td>\
              +      <td>1 2 ... 52 53</td>\
              +    </tr>\
              +    <tr>\
              +      <td></td>\
              +      <td>wo</td>\
              +      <td>1st 2nd ... 52nd 53rd</td>\
              +    </tr>\
              +    <tr>\
              +      <td></td>\
              +      <td>ww</td>\
              +      <td>01 02 ... 52 53</td>\
              +    </tr>\
              +    <tr>\
              +      <td><b>Week of Year (ISO)</b></td>\
              +      <td>W</td>\
              +      <td>1 2 ... 52 53</td>\
              +    </tr>\
              +    <tr>\
              +      <td></td>\
              +      <td>Wo</td>\
              +      <td>1st 2nd ... 52nd 53rd</td>\
              +    </tr>\
              +    <tr>\
              +      <td></td>\
              +      <td>WW</td>\
              +      <td>01 02 ... 52 53</td>\
              +    </tr>\
              +    <tr>\
              +      <td><b>Year</b></td>\
              +      <td>YY</td>\
              +      <td>70 71 ... 29 30</td>\
              +    </tr>\
              +    <tr>\
              +      <td></td>\
              +      <td>YYYY</td>\
              +      <td>1970 1971 ... 2029 2030</td>\
              +    </tr>\
              +    <tr>\
              +      <td><b>Week Year</b></td>\
              +      <td>gg</td>\
              +      <td>70 71 ... 29 30</td>\
              +    </tr>\
              +    <tr>\
              +      <td></td>\
              +      <td>gggg</td>\
              +      <td>1970 1971 ... 2029 2030</td>\
              +    </tr>\
              +    <tr>\
              +      <td><b>Week Year (ISO)</b></td>\
              +      <td>GG</td>\
              +      <td>70 71 ... 29 30</td>\
              +    </tr>\
              +    <tr>\
              +      <td></td>\
              +      <td>GGGG</td>\
              +      <td>1970 1971 ... 2029 2030</td>\
              +    </tr>\
              +    <tr>\
              +      <td><b>AM/PM</b></td>\
              +      <td>A</td>\
              +      <td>AM PM</td>\
              +    </tr>\
              +    <tr>\
              +      <td></td>\
              +      <td>a</td>\
              +      <td>am pm</td>\
              +    </tr>\
              +    <tr>\
              +      <td><b>Hour</b></td>\
              +      <td>H</td>\
              +      <td>0 1 ... 22 23</td>\
              +    </tr>\
              +    <tr>\
              +      <td></td>\
              +      <td>HH</td>\
              +      <td>00 01 ... 22 23</td>\
              +    </tr>\
              +    <tr>\
              +      <td></td>\
              +      <td>h</td>\
              +      <td>1 2 ... 11 12</td>\
              +    </tr>\
              +    <tr>\
              +      <td></td>\
              +      <td>hh</td>\
              +      <td>01 02 ... 11 12</td>\
              +    </tr>\
              +    <tr>\
              +      <td><b>Minute</b></td>\
              +      <td>m</td>\
              +      <td>0 1 ... 58 59</td>\
              +    </tr>\
              +    <tr>\
              +      <td></td>\
              +      <td>mm</td>\
              +      <td>00 01 ... 58 59</td>\
              +    </tr>\
              +    <tr>\
              +      <td><b>Second</b></td>\
              +      <td>s</td>\
              +      <td>0 1 ... 58 59</td>\
              +    </tr>\
              +    <tr>\
              +      <td></td>\
              +      <td>ss</td>\
              +      <td>00 01 ... 58 59</td>\
              +    </tr>\
              +    <tr>\
              +      <td><b>Fractional Second</b></td>\
              +      <td>S</td>\
              +      <td>0 1 ... 8 9</td>\
              +    </tr>\
              +    <tr>\
              +      <td></td>\
              +      <td>SS</td>\
              +      <td>00 01 ... 98 99</td>\
              +    </tr>\
              +    <tr>\
              +      <td></td>\
              +      <td>SSS</td>\
              +      <td>000 001 ... 998 999</td>\
              +    </tr>\
              +    <tr>\
              +      <td></td>\
              +      <td>SSSS ... SSSSSSSSS</td>\
              +      <td>000[0..] 001[0..] ... 998[0..] 999[0..]</td>\
              +    </tr>\
              +    <tr>\
              +      <td><b>Timezone</b></td>\
              +      <td>z or zz</td>\
              +      <td>EST CST ... MST PST</td>\
              +    </tr>\
              +    <tr>\
              +      <td></td>\
              +      <td>Z</td>\
              +      <td>-07:00 -06:00 ... +06:00 +07:00</td>\
              +    </tr>\
              +    <tr>\
              +      <td></td>\
              +      <td>ZZ</td>\
              +      <td>-0700 -0600 ... +0600 +0700</td>\
              +    </tr>\
              +    <tr>\
              +      <td><b>Unix Timestamp</b></td>\
              +      <td>X</td>\
              +      <td>1360013296</td>\
              +    </tr>\
              +    <tr>\
              +      <td><b>Unix Millisecond Timestamp</b></td>\
              +      <td>x</td>\
              +      <td>1360013296123</td>\
              +    </tr>\
              +  </tbody>\
              +</table>",
              +
              +    
              +};
              diff --git a/src/js/operations/Endian.js b/src/js/operations/Endian.js
              new file mode 100755
              index 00000000..13ce1ce6
              --- /dev/null
              +++ b/src/js/operations/Endian.js
              @@ -0,0 +1,94 @@
              +/**
              + * Endian operations.
              + *
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @namespace
              + */
              +var Endian = {
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    DATA_FORMAT: ["Hex", "Raw"],
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    WORD_LENGTH: 4,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    PAD_INCOMPLETE_WORDS: true,
              +    
              +    /**
              +     * Swap endianness operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_swap_endianness: function(input, args) {
              +        var data_format = args[0],
              +            word_length = args[1],
              +            pad_incomplete_words = args[2],
              +            data = [],
              +            result = [],
              +            words = [],
              +            i = 0,
              +            j = 0;
              +            
              +        if (word_length <= 0) {
              +            return "Word length must be greater than 0";
              +        }
              +            
              +        // Convert input to raw data based on specified data format
              +        switch (data_format) {
              +            case "Hex":
              +                data = Utils.from_hex(input);
              +                break;
              +            case "Raw":
              +                data = Utils.str_to_byte_array(input);
              +                break;
              +            default:
              +                data = input;
              +        }
              +        
              +        // Split up into words
              +        for (i = 0; i < data.length; i += word_length) {
              +            var word = data.slice(i, i + word_length);
              +            
              +            // Pad word if too short
              +            if (pad_incomplete_words && word.length < word_length){
              +                for (j = word.length; j < word_length; j++) {
              +                    word.push(0);
              +                }
              +            }
              +            
              +            words.push(word);
              +        }
              +        
              +        // Swap endianness and flatten
              +        for (i = 0; i < words.length; i++) {
              +            j = words[i].length;
              +            while (j--) {
              +                result.push(words[i][j]);
              +            }
              +        }
              +        
              +        // Convert data back to specified data format
              +        switch (data_format) {
              +            case "Hex":
              +                return Utils.to_hex(result);
              +            case "Raw":
              +                return Utils.byte_array_to_utf8(result);
              +            default:
              +                return result;
              +        }
              +    },
              +    
              +};
              diff --git a/src/js/operations/Entropy.js b/src/js/operations/Entropy.js
              new file mode 100755
              index 00000000..cec9b3a1
              --- /dev/null
              +++ b/src/js/operations/Entropy.js
              @@ -0,0 +1,166 @@
              +/**
              + * Entropy operations.
              + *
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @namespace
              + */
              +var Entropy = {
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    CHUNK_SIZE: 1000,
              +    
              +    /**
              +     * Entropy operation.
              +     *
              +     * @param {byte_array} input
              +     * @param {Object[]} args
              +     * @returns {html}
              +     */
              +    run_entropy: function(input, args) {
              +        var chunk_size = args[0],
              +            output = "",
              +            entropy = Entropy._calc_entropy(input);
              +        
              +        output += "Shannon entropy: " + entropy + "\n" +
              +            "<br><canvas id='chart-area'></canvas><br>\n" +
              +            "- 0 represents no randomness (i.e. all the bytes in the data have the same value) whereas 8, the maximum, represents a completely random string.\n" +
              +            "- Standard English text usually falls somewhere between 3.5 and 5.\n" +
              +            "- Properly encrypted or compressed data of a reasonable length should have an entropy of over 7.5.\n\n" +
              +            "The following results show the entropy of chunks of the input data. Chunks with particularly high entropy could suggest encrypted or compressed sections.\n\n" +
              +            "<br><script>\
              +                var canvas = document.getElementById('chart-area'),\
              +                    parent_rect = canvas.parentNode.getBoundingClientRect(),\
              +                    entropy = " + entropy + ",\
              +                    height = parent_rect.height * 0.25;\
              +                \
              +                canvas.width = parent_rect.width * 0.95;\
              +                canvas.height = height > 150 ? 150 : height;\
              +                \
              +                CanvasComponents.draw_scale_bar(canvas, entropy, 8, [\
              +                    {\
              +                        label: 'English text',\
              +                        min: 3.5,\
              +                        max: 5\
              +                    },{\
              +                        label: 'Encrypted/compressed',\
              +                        min: 7.5,\
              +                        max: 8\
              +                    }\
              +                ]);\
              +            </script>";
              +        
              +        var chunk_entropy = 0;
              +        if (chunk_size !== 0) {
              +            for (var i = 0; i < input.length; i += chunk_size) {
              +                chunk_entropy = Entropy._calc_entropy(input.slice(i, i+chunk_size));
              +                output += "Bytes " + i + " to " + (i+chunk_size) + ": " + chunk_entropy + "\n";
              +            }
              +        } else {
              +            output += "Chunk size cannot be 0.";
              +        }
              +        
              +        return output;
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    FREQ_ZEROS: false,
              +    
              +    /**
              +     * Frequency distribution operation.
              +     *
              +     * @param {byte_array} input
              +     * @param {Object[]} args
              +     * @returns {html}
              +     */
              +    run_freq_distrib: function (input, args) {
              +        if (!input.length) return "No data";
              +        
              +        var distrib = new Array(256),
              +            percentages = new Array(256),
              +            len = input.length,
              +            show_zeroes = args[0];
              +        
              +        // Initialise distrib to 0
              +        for (var i = 0; i < 256; i++) {
              +            distrib[i] = 0;
              +        }
              +        
              +        // Count bytes
              +        for (i = 0; i < len; i++) {
              +            distrib[input[i]]++;
              +        }
              +        
              +        // Calculate percentages
              +        var repr = 0;
              +        for (i = 0; i < 256; i++) {
              +            if (distrib[i] > 0) repr++;
              +            percentages[i] = distrib[i] / len * 100;
              +        }
              +        
              +        // Print
              +        var output = "<canvas id='chart-area'></canvas><br>" +
              +            "Total data length: " + len +
              +            "\nNumber of bytes represented: " + repr +
              +            "\nNumber of bytes not represented: " + (256-repr) +
              +            "\n\nByte   Percentage\n" +
              +            "<script>\
              +                var canvas = document.getElementById('chart-area'),\
              +                    parent_rect = canvas.parentNode.getBoundingClientRect(),\
              +                    scores = " + JSON.stringify(percentages) + ";\
              +                \
              +                canvas.width = parent_rect.width * 0.95;\
              +                canvas.height = parent_rect.height * 0.9;\
              +                \
              +                CanvasComponents.draw_bar_chart(canvas, scores, 'Byte', 'Frequency %', 16, 6);\
              +            </script>";
              +                
              +        for (i = 0; i < 256; i++) {
              +            if (distrib[i] || show_zeroes) {
              +                output += " " + Utils.hex(i, 2) + "    (" +
              +                        Utils.pad_right(percentages[i].toFixed(2).replace(".00", "") + "%)", 8) +
              +                        Array(Math.ceil(percentages[i])+1).join("|") + "\n";
              +            }
              +        }
              +        
              +        return output;
              +    },
              +    
              +    
              +    /**
              +     * Calculates the Shannon entropy for a given chunk of data.
              +     *
              +     * @private
              +     * @param {byte_array} data
              +     * @returns {number}
              +     */
              +    _calc_entropy: function(data) {
              +        var prob = [],
              +            uniques = data.unique(),
              +            str = Utils.byte_array_to_chars(data);
              +            
              +        for (var i = 0; i < uniques.length; i++) {
              +            prob.push(str.count(Utils.chr(uniques[i])) / data.length);
              +        }
              +        
              +        var entropy = 0,
              +            p;
              +            
              +        for (i = 0; i < prob.length; i++) {
              +            p = prob[i];
              +            entropy += p * Math.log(p) / Math.log(2);
              +        }
              +        
              +        return -entropy;
              +    },
              +
              +};
              diff --git a/src/js/operations/Extract.js b/src/js/operations/Extract.js
              new file mode 100755
              index 00000000..fdab5591
              --- /dev/null
              +++ b/src/js/operations/Extract.js
              @@ -0,0 +1,297 @@
              +/**
              + * Identifier extraction operations.
              + *
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @namespace
              + */
              +var Extract = {
              +
              +    /**
              +     * Runs search operations across the input data using refular expressions.
              +     *
              +     * @private
              +     * @param {string} input
              +     * @param {RegExp} search_regex
              +     * @param {RegExp} remove_regex - A regular expression defining results to remove from the
              +     *      final list
              +     * @param {boolean} include_total - Whether or not to include the total number of results
              +     * @returns {string}
              +     */
              +    _search: function(input, search_regex, remove_regex, include_total) {
              +        var output = "",
              +            total = 0,
              +            match;
              +            
              +        while (!!(match = search_regex.exec(input))) {
              +            if (remove_regex && remove_regex.test(match[0]))
              +                continue;
              +            total++;
              +            output += match[0] + "\n";
              +        }
              +        
              +        if (include_total)
              +            output = "Total found: " + total + "\n\n" + output;
              +            
              +        return output;
              +    },
              +
              +
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    MIN_STRING_LEN: 3,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    DISPLAY_TOTAL: false,
              +    
              +    /**
              +     * Strings operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_strings: function(input, args) {
              +        var min_len = args[0] || Extract.MIN_STRING_LEN,
              +            display_total = args[1],
              +            strings = "[A-Z\\d/\\-:.,_$%'\"()<>= !\\[\\]{}@]",
              +            regex = new RegExp(strings + "{" + min_len + ",}", "ig");
              +            
              +        return Extract._search(input, regex, null, display_total);
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    INCLUDE_IPV4: true,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    INCLUDE_IPV6: false,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    REMOVE_LOCAL: false,
              +    
              +    /**
              +     * Extract IP addresses operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_ip: function(input, args) {
              +        var include_ipv4  = args[0],
              +            include_ipv6  = args[1],
              +            remove_local  = args[2],
              +            display_total = args[3],
              +            ipv4 = "(?:(?:\\d|[01]?\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d|\\d)(?:\\/\\d{1,2})?",
              +            ipv6 = "((?=.*::)(?!.*::.+::)(::)?([\\dA-F]{1,4}:(:|\\b)|){5}|([\\dA-F]{1,4}:){6})((([\\dA-F]{1,4}((?!\\3)::|:\\b|(?![\\dA-F])))|(?!\\2\\3)){2}|(((2[0-4]|1\\d|[1-9])?\\d|25[0-5])\\.?\\b){4})",
              +            ips  = "";
              +        
              +        if (include_ipv4 && include_ipv6) {
              +            ips = ipv4 + "|" + ipv6;
              +        } else if (include_ipv4) {
              +            ips = ipv4;
              +        } else if (include_ipv6) {
              +            ips = ipv6;
              +        }
              +        
              +        if (ips) {
              +            var regex = new RegExp(ips, "ig");
              +            
              +            if (remove_local) {
              +                var ten = "10\\..+",
              +                    oneninetwo = "192\\.168\\..+",
              +                    oneseventwo = "172\\.(?:1[6-9]|2\\d|3[01])\\..+",
              +                    onetwoseven = "127\\..+",
              +                    remove_regex = new RegExp("^(?:" + ten + "|" + oneninetwo +
              +                        "|" + oneseventwo + "|" + onetwoseven + ")");
              +                        
              +                return Extract._search(input, regex, remove_regex, display_total);
              +            } else {
              +                return Extract._search(input, regex, null, display_total);
              +            }
              +        } else {
              +            return "";
              +        }
              +    },
              +    
              +    
              +    /**
              +     * Extract email addresses operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_email: function(input, args) {
              +        var display_total = args[0],
              +            regex = /\w[-.\w]*@[-\w]+(?:\.[-\w]+)*\.[A-Z]{2,4}/ig;
              +            
              +        return Extract._search(input, regex, null, display_total);
              +    },
              +    
              +    
              +    /**
              +     * Extract MAC addresses operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_mac: function(input, args) {
              +        var display_total = args[0],
              +            regex = /[A-F\d]{2}(?:[:-][A-F\d]{2}){5}/ig;
              +            
              +        return Extract._search(input, regex, null, display_total);
              +    },
              +    
              +    
              +    /**
              +     * Extract URLs operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_urls: function(input, args) {
              +        var display_total = args[0],
              +            protocol = "[A-Z]+://",
              +            hostname = "[-\\w]+(?:\\.\\w[-\\w]*)+",
              +            port = ":\\d+",
              +            path = "/[^.!,?;\"'<>()\\[\\]{}\\s\\x7F-\\xFF]*";
              +            
              +        path += "(?:[.!,?]+[^.!,?;\"'<>()\\[\\]{}\\s\\x7F-\\xFF]+)*";
              +        var regex = new RegExp(protocol + hostname + "(?:" + port +
              +            ")?(?:" + path + ")?", "ig");
              +        return Extract._search(input, regex, null, display_total);
              +    },
              +    
              +    
              +    /**
              +     * Extract domains operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_domains: function(input, args) {
              +        var display_total = args[0],
              +            protocol = "https?://",
              +            hostname = "[-\\w\\.]+",
              +            tld = "\\.(?:com|net|org|biz|info|co|uk|onion|int|mobi|name|edu|gov|mil|eu|ac|ae|af|de|ca|ch|cn|cy|es|gb|hk|il|in|io|tv|me|nl|no|nz|ro|ru|tr|us|az|ir|kz|uz|pk)+",
              +            regex = new RegExp("(?:" + protocol + ")?" + hostname + tld, "ig");
              +        
              +        return Extract._search(input, regex, null, display_total);
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    INCLUDE_WIN_PATH: true,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    INCLUDE_UNIX_PATH: true,
              +    
              +    /**
              +     * Extract file paths operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_file_paths: function(input, args) {
              +        var include_win_path = args[0],
              +            include_unix_path = args[1],
              +            display_total = args[2],
              +            win_drive = "[A-Z]:\\\\",
              +            win_name = "[A-Z\\d][A-Z\\d\\- '_\\(\\)]{0,61}",
              +            win_ext = "[A-Z\\d]{1,6}",
              +            win_path = win_drive + "(?:" + win_name + "\\\\?)*" + win_name +
              +                "(?:\\." + win_ext + ")?",
              +            unix_path = "(?:/[A-Z\\d.][A-Z\\d\\-.]{0,61})+",
              +            file_paths = "";
              +        
              +        if (include_win_path && include_unix_path) {
              +            file_paths = win_path + "|" + unix_path;
              +        } else if (include_win_path) {
              +            file_paths = win_path;
              +        } else if (include_unix_path) {
              +            file_paths = unix_path;
              +        }
              +        
              +        if (file_paths) {
              +            var regex = new RegExp(file_paths, "ig");
              +            return Extract._search(input, regex, null, display_total);
              +        } else {
              +            return "";
              +        }
              +    },
              +    
              +    
              +    /**
              +     * Extract dates operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_dates: function(input, args) {
              +        var display_total = args[0],
              +            date1 = "(?:19|20)\\d\\d[- /.](?:0[1-9]|1[012])[- /.](?:0[1-9]|[12][0-9]|3[01])", // yyyy-mm-dd
              +            date2 = "(?:0[1-9]|[12][0-9]|3[01])[- /.](?:0[1-9]|1[012])[- /.](?:19|20)\\d\\d", // dd/mm/yyyy
              +            date3 = "(?:0[1-9]|1[012])[- /.](?:0[1-9]|[12][0-9]|3[01])[- /.](?:19|20)\\d\\d", // mm/dd/yyyy
              +            regex = new RegExp(date1 + "|" + date2 + "|" + date3, "ig");
              +            
              +        return Extract._search(input, regex, null, display_total);
              +    },
              +    
              +    
              +    /**
              +     * Extract all identifiers operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_all_idents: function(input, args) {
              +        var output = "";
              +        output += "IP addresses\n";
              +        output += Extract.run_ip(input, [true, true, false]);
              +        
              +        output += "\nEmail addresses\n";
              +        output += Extract.run_email(input, []);
              +        
              +        output += "\nMAC addresses\n";
              +        output += Extract.run_mac(input, []);
              +        
              +        output += "\nURLs\n";
              +        output += Extract.run_urls(input, []);
              +        
              +        output += "\nDomain names\n";
              +        output += Extract.run_domains(input, []);
              +        
              +        output += "\nFile paths\n";
              +        output += Extract.run_file_paths(input, [true, true]);
              +        
              +        output += "\nDates\n";
              +        output += Extract.run_dates(input, []);
              +        return output;
              +    },
              +    
              +};
              diff --git a/src/js/operations/FileType.js b/src/js/operations/FileType.js
              new file mode 100755
              index 00000000..bf48906e
              --- /dev/null
              +++ b/src/js/operations/FileType.js
              @@ -0,0 +1,526 @@
              +/**
              + * File type operations.
              + *
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @namespace
              + */
              +var FileType = {
              +
              +    /**
              +     * Detect File Type operation.
              +     *
              +     * @param {byte_array} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_detect: function(input, args) {
              +        var type = FileType._magic_type(input);
              +        
              +        if (!type) {
              +            return "Unknown file type. Have you tried checking the entropy of this data to determine whether it might be encrypted or compressed?";
              +        } else {
              +            var output = "File extension: " + type.ext + "\n" +
              +                "MIME type:      " + type.mime;
              +            
              +            if (type.desc && type.desc.length) {
              +                output += "\nDescription:    " + type.desc;
              +            }
              +            
              +            return output;
              +        }
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    IGNORE_COMMON_BYTE_SEQUENCES: true,
              +    
              +    /**
              +     * Scan for Embedded Files operation.
              +     *
              +     * @param {byte_array} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_scan_for_embedded_files: function(input, args) {
              +        var output = "Scanning data for 'magic bytes' which may indicate embedded files. The following results may be false positives and should not be treat as reliable. Any suffiently long file is likely to contain these magic bytes coincidentally.\n",
              +            type,
              +            ignore_common = args[0],
              +            common_exts = ["ico", "ttf", ""],
              +            num_found = 0,
              +            num_common_found = 0;
              +            
              +        for (var i = 0; i < input.length; i++) {
              +            type = FileType._magic_type(input.slice(i));
              +            if (type) {
              +                if (ignore_common && common_exts.indexOf(type.ext) > -1) {
              +                    num_common_found++;
              +                    continue;
              +                }
              +                num_found++;
              +                output += "\nOffset " + i + " (0x" + Utils.hex(i) + "):\n" +
              +                    "  File extension: " + type.ext + "\n" +
              +                    "  MIME type:      " + type.mime + "\n";
              +                    
              +                if (type.desc && type.desc.length) {
              +                    output += "  Description:    " + type.desc + "\n";
              +                }
              +            }
              +        }
              +        
              +        if (num_found === 0) {
              +            output += "\nNo embedded files were found.";
              +        }
              +        
              +        if (num_common_found > 0) {
              +            output += "\n\n" + num_common_found;
              +            output += num_common_found == 1 ?
              +                " file type was detected that has a common byte sequence. This is likely to be a false positive." :
              +                " file types were detected that have common byte sequences. These are likely to be false positives."; 
              +            output += " Run this operation with the 'Ignore common byte sequences' option unchecked to see details.";
              +        }
              +        
              +        return output;
              +    },
              +    
              +    
              +    /**
              +     * Given a buffer, detects magic byte sequences at specific positions and returns the 
              +     * extension and mime type.
              +     *
              +     * @private
              +     * @param {byte_array} buf
              +     * @returns {Object} type
              +     * @returns {string} type.ext - File extension
              +     * @returns {string} type.mime - Mime type
              +     * @returns {string} [type.desc] - Description
              +     */
              +    _magic_type: function (buf) {
              +        if (!(buf && buf.length > 1)) {
              +            return null;
              +        }
              +
              +        if (buf[0] === 0xFF && buf[1] === 0xD8 && buf[2] === 0xFF) {
              +            return {
              +                ext: 'jpg',
              +                mime: 'image/jpeg'
              +            };
              +        }
              +
              +        if (buf[0] === 0x89 && buf[1] === 0x50 && buf[2] === 0x4E && buf[3] === 0x47) {
              +            return {
              +                ext: 'png',
              +                mime: 'image/png'
              +            };
              +        }
              +
              +        if (buf[0] === 0x47 && buf[1] === 0x49 && buf[2] === 0x46) {
              +            return {
              +                ext: 'gif',
              +                mime: 'image/gif'
              +            };
              +        }
              +
              +        if (buf[8] === 0x57 && buf[9] === 0x45 && buf[10] === 0x42 && buf[11] === 0x50) {
              +            return {
              +                ext: 'webp',
              +                mime: 'image/webp'
              +            };
              +        }
              +
              +        // needs to be before `tif` check
              +        if (((buf[0] === 0x49 && buf[1] === 0x49 && buf[2] === 0x2A && buf[3] === 0x0) || (buf[0] === 0x4D && buf[1] === 0x4D && buf[2] === 0x0 && buf[3] === 0x2A)) && buf[8] === 0x43 && buf[9] === 0x52) {
              +            return {
              +                ext: 'cr2',
              +                mime: 'image/x-canon-cr2'
              +            };
              +        }
              +
              +        if ((buf[0] === 0x49 && buf[1] === 0x49 && buf[2] === 0x2A && buf[3] === 0x0) || (buf[0] === 0x4D && buf[1] === 0x4D && buf[2] === 0x0 && buf[3] === 0x2A)) {
              +            return {
              +                ext: 'tif',
              +                mime: 'image/tiff'
              +            };
              +        }
              +
              +        if (buf[0] === 0x42 && buf[1] === 0x4D) {
              +            return {
              +                ext: 'bmp',
              +                mime: 'image/bmp'
              +            };
              +        }
              +
              +        if (buf[0] === 0x49 && buf[1] === 0x49 && buf[2] === 0xBC) {
              +            return {
              +                ext: 'jxr',
              +                mime: 'image/vnd.ms-photo'
              +            };
              +        }
              +
              +        if (buf[0] === 0x38 && buf[1] === 0x42 && buf[2] === 0x50 && buf[3] === 0x53) {
              +            return {
              +                ext: 'psd',
              +                mime: 'image/vnd.adobe.photoshop'
              +            };
              +        }
              +
              +        // needs to be before `zip` check
              +        if (buf[0] === 0x50 && buf[1] === 0x4B && buf[2] === 0x3 && buf[3] === 0x4 && buf[30] === 0x6D && buf[31] === 0x69 && buf[32] === 0x6D && buf[33] === 0x65 && buf[34] === 0x74 && buf[35] === 0x79 && buf[36] === 0x70 && buf[37] === 0x65 && buf[38] === 0x61 && buf[39] === 0x70 && buf[40] === 0x70 && buf[41] === 0x6C && buf[42] === 0x69 && buf[43] === 0x63 && buf[44] === 0x61 && buf[45] === 0x74 && buf[46] === 0x69 && buf[47] === 0x6F && buf[48] === 0x6E && buf[49] === 0x2F && buf[50] === 0x65 && buf[51] === 0x70 && buf[52] === 0x75 && buf[53] === 0x62 && buf[54] === 0x2B && buf[55] === 0x7A && buf[56] === 0x69 && buf[57] === 0x70) {
              +            return {
              +                ext: 'epub',
              +                mime: 'application/epub+zip'
              +            };
              +        }
              +
              +        if (buf[0] === 0x50 && buf[1] === 0x4B && (buf[2] === 0x3 || buf[2] === 0x5 || buf[2] === 0x7) && (buf[3] === 0x4 || buf[3] === 0x6 || buf[3] === 0x8)) {
              +            return {
              +                ext: 'zip',
              +                mime: 'application/zip'
              +            };
              +        }
              +
              +        if (buf[257] === 0x75 && buf[258] === 0x73 && buf[259] === 0x74 && buf[260] === 0x61 && buf[261] === 0x72) {
              +            return {
              +                ext: 'tar',
              +                mime: 'application/x-tar'
              +            };
              +        }
              +
              +        if (buf[0] === 0x52 && buf[1] === 0x61 && buf[2] === 0x72 && buf[3] === 0x21 && buf[4] === 0x1A && buf[5] === 0x7 && (buf[6] === 0x0 || buf[6] === 0x1)) {
              +            return {
              +                ext: 'rar',
              +                mime: 'application/x-rar-compressed'
              +            };
              +        }
              +
              +        if (buf[0] === 0x1F && buf[1] === 0x8B && buf[2] === 0x8) {
              +            return {
              +                ext: 'gz',
              +                mime: 'application/gzip'
              +            };
              +        }
              +
              +        if (buf[0] === 0x42 && buf[1] === 0x5A && buf[2] === 0x68) {
              +            return {
              +                ext: 'bz2',
              +                mime: 'application/x-bzip2'
              +            };
              +        }
              +
              +        if (buf[0] === 0x37 && buf[1] === 0x7A && buf[2] === 0xBC && buf[3] === 0xAF && buf[4] === 0x27 && buf[5] === 0x1C) {
              +            return {
              +                ext: '7z',
              +                mime: 'application/x-7z-compressed'
              +            };
              +        }
              +
              +        if (buf[0] === 0x78 && buf[1] === 0x01) {
              +            return {
              +                ext: 'dmg',
              +                mime: 'application/x-apple-diskimage'
              +            };
              +        }
              +
              +        if ((buf[0] === 0x0 && buf[1] === 0x0 && buf[2] === 0x0 && (buf[3] === 0x18 || buf[3] === 0x20) && buf[4] === 0x66 && buf[5] === 0x74 && buf[6] === 0x79 && buf[7] === 0x70) || (buf[0] === 0x33 && buf[1] === 0x67 && buf[2] === 0x70 && buf[3] === 0x35) || (buf[0] === 0x0 && buf[1] === 0x0 && buf[2] === 0x0 && buf[3] === 0x1C && buf[4] === 0x66 && buf[5] === 0x74 && buf[6] === 0x79 && buf[7] === 0x70 && buf[8] === 0x6D && buf[9] === 0x70 && buf[10] === 0x34 && buf[11] === 0x32 && buf[16] === 0x6D && buf[17] === 0x70 && buf[18] === 0x34 && buf[19] === 0x31 && buf[20] === 0x6D && buf[21] === 0x70 && buf[22] === 0x34 && buf[23] === 0x32 && buf[24] === 0x69 && buf[25] === 0x73 && buf[26] === 0x6F && buf[27] === 0x6D)) {
              +            return {
              +                ext: 'mp4',
              +                mime: 'video/mp4'
              +            };
              +        }
              +
              +        if ((buf[0] === 0x0 && buf[1] === 0x0 && buf[2] === 0x0 && buf[3] === 0x1C && buf[4] === 0x66 && buf[5] === 0x74 && buf[6] === 0x79 && buf[7] === 0x70 && buf[8] === 0x4D && buf[9] === 0x34 && buf[10] === 0x56)) {
              +            return {
              +                ext: 'm4v',
              +                mime: 'video/x-m4v'
              +            };
              +        }
              +
              +        if (buf[0] === 0x4D && buf[1] === 0x54 && buf[2] === 0x68 && buf[3] === 0x64) {
              +            return {
              +                ext: 'mid',
              +                mime: 'audio/midi'
              +            };
              +        }
              +
              +        // needs to be before the `webm` check
              +        if (buf[31] === 0x6D && buf[32] === 0x61 && buf[33] === 0x74 && buf[34] === 0x72 && buf[35] === 0x6f && buf[36] === 0x73 && buf[37] === 0x6B && buf[38] === 0x61) {
              +            return {
              +                ext: 'mkv',
              +                mime: 'video/x-matroska'
              +            };
              +        }
              +
              +        if (buf[0] === 0x1A && buf[1] === 0x45 && buf[2] === 0xDF && buf[3] === 0xA3) {
              +            return {
              +                ext: 'webm',
              +                mime: 'video/webm'
              +            };
              +        }
              +
              +        if (buf[0] === 0x0 && buf[1] === 0x0 && buf[2] === 0x0 && buf[3] === 0x14 && buf[4] === 0x66 && buf[5] === 0x74 && buf[6] === 0x79 && buf[7] === 0x70) {
              +            return {
              +                ext: 'mov',
              +                mime: 'video/quicktime'
              +            };
              +        }
              +
              +        if (buf[0] === 0x52 && buf[1] === 0x49 && buf[2] === 0x46 && buf[3] === 0x46 && buf[8] === 0x41 && buf[9] === 0x56 && buf[10] === 0x49) {
              +            return {
              +                ext: 'avi',
              +                mime: 'video/x-msvideo'
              +            };
              +        }
              +
              +        if (buf[0] === 0x30 && buf[1] === 0x26 && buf[2] === 0xB2 && buf[3] === 0x75 && buf[4] === 0x8E && buf[5] === 0x66 && buf[6] === 0xCF && buf[7] === 0x11 && buf[8] === 0xA6 && buf[9] === 0xD9) {
              +            return {
              +                ext: 'wmv',
              +                mime: 'video/x-ms-wmv'
              +            };
              +        }
              +
              +        if (buf[0] === 0x0 && buf[1] === 0x0 && buf[2] === 0x1 && buf[3].toString(16)[0] === 'b') {
              +            return {
              +                ext: 'mpg',
              +                mime: 'video/mpeg'
              +            };
              +        }
              +
              +        if ((buf[0] === 0x49 && buf[1] === 0x44 && buf[2] === 0x33) || (buf[0] === 0xFF && buf[1] === 0xfb)) {
              +            return {
              +                ext: 'mp3',
              +                mime: 'audio/mpeg'
              +            };
              +        }
              +
              +        if ((buf[4] === 0x66 && buf[5] === 0x74 && buf[6] === 0x79 && buf[7] === 0x70 && buf[8] === 0x4D && buf[9] === 0x34 && buf[10] === 0x41) || (buf[0] === 0x4D && buf[1] === 0x34 && buf[2] === 0x41 && buf[3] === 0x20)) {
              +            return {
              +                ext: 'm4a',
              +                mime: 'audio/m4a'
              +            };
              +        }
              +
              +        if (buf[0] === 0x4F && buf[1] === 0x67 && buf[2] === 0x67 && buf[3] === 0x53) {
              +            return {
              +                ext: 'ogg',
              +                mime: 'audio/ogg'
              +            };
              +        }
              +
              +        if (buf[0] === 0x66 && buf[1] === 0x4C && buf[2] === 0x61 && buf[3] === 0x43) {
              +            return {
              +                ext: 'flac',
              +                mime: 'audio/x-flac'
              +            };
              +        }
              +
              +        if (buf[0] === 0x52 && buf[1] === 0x49 && buf[2] === 0x46 && buf[3] === 0x46 && buf[8] === 0x57 && buf[9] === 0x41 && buf[10] === 0x56 && buf[11] === 0x45) {
              +            return {
              +                ext: 'wav',
              +                mime: 'audio/x-wav'
              +            };
              +        }
              +
              +        if (buf[0] === 0x23 && buf[1] === 0x21 && buf[2] === 0x41 && buf[3] === 0x4D && buf[4] === 0x52 && buf[5] === 0x0A) {
              +            return {
              +                ext: 'amr',
              +                mime: 'audio/amr'
              +            };
              +        }
              +
              +        if (buf[0] === 0x25 && buf[1] === 0x50 && buf[2] === 0x44 && buf[3] === 0x46) {
              +            return {
              +                ext: 'pdf',
              +                mime: 'application/pdf'
              +            };
              +        }
              +
              +        if (buf[0] === 0x4D && buf[1] === 0x5A) {
              +            return {
              +                ext: 'exe',
              +                mime: 'application/x-msdownload'
              +            };
              +        }
              +
              +        if ((buf[0] === 0x43 || buf[0] === 0x46) && buf[1] === 0x57 && buf[2] === 0x53) {
              +            return {
              +                ext: 'swf',
              +                mime: 'application/x-shockwave-flash'
              +            };
              +        }
              +
              +        if (buf[0] === 0x7B && buf[1] === 0x5C && buf[2] === 0x72 && buf[3] === 0x74 && buf[4] === 0x66) {
              +            return {
              +                ext: 'rtf',
              +                mime: 'application/rtf'
              +            };
              +        }
              +
              +        if (buf[0] === 0x77 && buf[1] === 0x4F && buf[2] === 0x46 && buf[3] === 0x46 && buf[4] === 0x00 && buf[5] === 0x01 && buf[6] === 0x00 && buf[7] === 0x00) {
              +            return {
              +                ext: 'woff',
              +                mime: 'application/font-woff'
              +            };
              +        }
              +
              +        if (buf[0] === 0x77 && buf[1] === 0x4F && buf[2] === 0x46 && buf[3] === 0x32 && buf[4] === 0x00 && buf[5] === 0x01 && buf[6] === 0x00 && buf[7] === 0x00) {
              +            return {
              +                ext: 'woff2',
              +                mime: 'application/font-woff'
              +            };
              +        }
              +
              +        if (buf[34] === 0x4C && buf[35] === 0x50 && ((buf[8] === 0x02 && buf[9] === 0x00 && buf[10] === 0x01) || (buf[8] === 0x01 && buf[9] === 0x00 && buf[10] === 0x00) || (buf[8] === 0x02 && buf[9] === 0x00 && buf[10] === 0x02))) {
              +            return {
              +                ext: 'eot',
              +                mime: 'application/octet-stream'
              +            };
              +        }
              +
              +        if (buf[0] === 0x00 && buf[1] === 0x01 && buf[2] === 0x00 && buf[3] === 0x00 && buf[4] === 0x00) {
              +            return {
              +                ext: 'ttf',
              +                mime: 'application/font-sfnt'
              +            };
              +        }
              +
              +        if (buf[0] === 0x4F && buf[1] === 0x54 && buf[2] === 0x54 && buf[3] === 0x4F && buf[4] === 0x00) {
              +            return {
              +                ext: 'otf',
              +                mime: 'application/font-sfnt'
              +            };
              +        }
              +
              +        if (buf[0] === 0x00 && buf[1] === 0x00 && buf[2] === 0x01 && buf[3] === 0x00) {
              +            return {
              +                ext: 'ico',
              +                mime: 'image/x-icon'
              +            };
              +        }
              +
              +        if (buf[0] === 0x46 && buf[1] === 0x4C && buf[2] === 0x56 && buf[3] === 0x01) {
              +            return {
              +                ext: 'flv',
              +                mime: 'video/x-flv'
              +            };
              +        }
              +
              +        if (buf[0] === 0x25 && buf[1] === 0x21) {
              +            return {
              +                ext: 'ps',
              +                mime: 'application/postscript'
              +            };
              +        }
              +
              +        if (buf[0] === 0xFD && buf[1] === 0x37 && buf[2] === 0x7A && buf[3] === 0x58 && buf[4] === 0x5A && buf[5] === 0x00) {
              +            return {
              +                ext: 'xz',
              +                mime: 'application/x-xz'
              +            };
              +        }
              +
              +        if (buf[0] === 0x53 && buf[1] === 0x51 && buf[2] === 0x4C && buf[3] === 0x69) {
              +            return {
              +                ext: 'sqlite',
              +                mime: 'application/x-sqlite3'
              +            };
              +        }
              +        
              +        // Added by n1474335 [n1474335@gmail.com] from here on
              +        // ################################################################## //
              +        if ((buf[0] === 0x1F && buf[1] === 0x9D) || (buf[0] === 0x1F && buf[1] === 0xA0)) {
              +            return {
              +                ext: 'z, tar.z',
              +                mime: 'application/x-gtar'
              +            };
              +        }
              +        
              +        if (buf[0] === 0x7F && buf[1] === 0x45 && buf[2] === 0x4C && buf[3] === 0x46) {
              +            return {
              +                ext: 'none, axf, bin, elf, o, prx, puff, so',
              +                mime: 'application/x-executable',
              +                desc: 'Executable and Linkable Format file. No standard file extension.'
              +            };
              +        }
              +        
              +        if (buf[0] === 0xCA && buf[1] === 0xFE && buf[2] === 0xBA && buf[3] === 0xBE) {
              +            return {
              +                ext: 'class',
              +                mime: 'application/java-vm'
              +            };
              +        }
              +        
              +        if (buf[0] === 0xEF && buf[1] === 0xBB && buf[2] === 0xBF) {
              +            return {
              +                ext: 'txt',
              +                mime: 'text/plain',
              +                desc: 'UTF-8 encoded Unicode byte order mark detected, commonly but not exclusively seen in text files.'
              +            };
              +        }
              +        
              +        // Must be before Little-endian UTF-16 BOM
              +        if (buf[0] === 0xFF && buf[1] === 0xFE && buf[2] === 0x00 && buf[3] === 0x00) {
              +            return {
              +                ext: '',
              +                mime: '',
              +                desc: 'Little-endian UTF-32 encoded Unicode byte order mark detected.'
              +            };
              +        }
              +        
              +        if (buf[0] === 0xFF && buf[1] === 0xFE) {
              +            return {
              +                ext: '',
              +                mime: '',
              +                desc: 'Little-endian UTF-16 encoded Unicode byte order mark detected.'
              +            };
              +        }
              +        
              +        if ((buf[0x8001] === 0x43 && buf[0x8002] === 0x44 && buf[0x8003] === 0x30 && buf[0x8004] === 0x30 && buf[0x8005] === 0x31) ||
              +            (buf[0x8801] === 0x43 && buf[0x8802] === 0x44 && buf[0x8803] === 0x30 && buf[0x8804] === 0x30 && buf[0x8805] === 0x31) ||
              +            (buf[0x9001] === 0x43 && buf[0x9002] === 0x44 && buf[0x9003] === 0x30 && buf[0x9004] === 0x30 && buf[0x9005] === 0x31)) {
              +            return {
              +                ext: 'iso',
              +                mime: 'application/octet-stream',
              +                desc: 'ISO 9660 CD/DVD image file'
              +            };
              +        }
              +        
              +        if (buf[0] === 0xD0 && buf[1] === 0xCF && buf[2] === 0x11 && buf[3] === 0xE0 && buf[4] === 0xA1 && buf[5] === 0xB1 && buf[6] === 0x1A && buf[7] === 0xE1) {
              +            return {
              +                ext: 'doc, xls, ppt',
              +                mime: 'application/msword, application/vnd.ms-excel, application/vnd.ms-powerpoint',
              +                desc: 'Microsoft Office documents'
              +            };
              +        }
              +        
              +        if (buf[0] === 0x64 && buf[1] === 0x65 && buf[2] === 0x78 && buf[3] === 0x0A && buf[4] === 0x30 && buf[5] === 0x33 && buf[6] === 0x35 && buf[7] === 0x00) {
              +            return {
              +                ext: 'dex',
              +                mime: 'application/octet-stream',
              +                desc: 'Dalvik Executable (Android)'
              +            };
              +        }
              +        
              +        if (buf[0] === 0x4B && buf[1] === 0x44 && buf[2] === 0x4D) {
              +            return {
              +                ext: 'vmdk',
              +                mime: 'application/vmdk, application/x-virtualbox-vmdk'
              +            };
              +        }
              +        
              +        if (buf[0] === 0x43 && buf[1] === 0x72 && buf[2] === 0x32 && buf[3] == 0x34) {
              +            return {
              +                ext: 'crx',
              +                mime: 'application/crx',
              +                desc: 'Google Chrome extension or packaged app'
              +            };
              +        }
              +
              +        return null;
              +    },
              +
              +};
              diff --git a/src/js/operations/HTML.js b/src/js/operations/HTML.js
              new file mode 100755
              index 00000000..80b3b700
              --- /dev/null
              +++ b/src/js/operations/HTML.js
              @@ -0,0 +1,851 @@
              +/**
              + * HTML operations.
              + *
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @namespace
              + */
              +var HTML = {
              +
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    CONVERT_ALL: false,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    CONVERT_OPTIONS: ["Named entities where possible", "Numeric entities", "Hex entities"],
              +    
              +    /**
              +     * To HTML Entity operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_to_entity: function(input, args) {
              +        var convert_all = args[0],
              +            numeric = args[1] == "Numeric entities",
              +            hexa = args[1] == "Hex entities";
              +        
              +        var charcodes = Utils.str_to_charcode(input);
              +        var output = "";
              +        
              +        for (var i = 0; i < charcodes.length; i++) {
              +            if (convert_all && numeric) {
              +                output += "&#" + charcodes[i] + ";";
              +            } else if (convert_all && hexa) {
              +                output += "&#x" + Utils.hex(charcodes[i]) + ";";
              +            } else if (convert_all) {
              +                output += HTML._byte_to_entity[charcodes[i]] || "&#" + charcodes[i] + ";";
              +            } else if (numeric) {
              +                if (charcodes[i] > 255 || HTML._byte_to_entity.hasOwnProperty(charcodes[i])) {
              +                    output += "&#" + charcodes[i] + ";";
              +                } else {
              +                    output += Utils.chr(charcodes[i]);
              +                }
              +            } else if (hexa) {
              +                if (charcodes[i] > 255 || HTML._byte_to_entity.hasOwnProperty(charcodes[i])) {
              +                    output += "&#x" + Utils.hex(charcodes[i]) + ";";
              +                } else {
              +                    output += Utils.chr(charcodes[i]);
              +                }
              +            } else {
              +                output += HTML._byte_to_entity[charcodes[i]] || (
              +                    charcodes[i] > 255 ?
              +                        "&#" + charcodes[i] + ";" :
              +                        Utils.chr(charcodes[i])
              +                );
              +            }
              +        }
              +        return output;
              +    },
              +    
              +    
              +    /**
              +     * From HTML Entity operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_from_entity: function(input, args) {
              +        var regex = /&(#?x?[a-zA-Z0-9]{1,8});/g,
              +            output = "",
              +            m,
              +            i = 0;
              +            
              +        while (!!(m = regex.exec(input))) {
              +            // Add up to match
              +            for (; i < m.index;)
              +                output += input[i++];
              +            
              +            // Add match
              +            var bite = HTML._entity_to_byte[m[1]];
              +            if (bite) {
              +                output += Utils.chr(bite);
              +            } else if (!bite && m[1][0] == "#" && m[1].length > 1 && /^#\d{1,5}$/.test(m[1])) {
              +                // Numeric entity (e.g. &#10;)
              +                var num = m[1].slice(1,m[1].length);
              +                output += Utils.chr(parseInt(num, 10));
              +            } else if (!bite && m[1][0] == "#" && m[1].length > 3 && /^#x[\dA-F]{2,8}$/i.test(m[1])) {
              +                // Hex entity (e.g. &#x3A;)
              +                var hex = m[1].slice(2,m[1].length);
              +                output += Utils.chr(parseInt(hex, 16));
              +            } else {
              +                // Not a valid entity, print as normal
              +                for (; i < regex.lastIndex;)
              +                    output += input[i++];
              +            }
              +            
              +            i = regex.lastIndex;
              +        }
              +        // Add all after final match
              +        for (; i < input.length;)
              +            output += input[i++];
              +        
              +        return output;
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    REMOVE_INDENTATION: true,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    REMOVE_LINE_BREAKS: true,
              +    
              +    /**
              +     * Strip HTML tags operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_strip_tags: function(input, args) {
              +        var remove_indentation = args[0],
              +            remove_line_breaks = args[1];
              +            
              +        input = Utils.strip_html_tags(input);
              +        
              +        if (remove_indentation) {
              +            input = input.replace(/\n[ \f\t]+/g, "\n");
              +        }
              +        
              +        if (remove_line_breaks) {
              +            input = input.replace(/^\s*\n/, "") // first line
              +                         .replace(/(\n\s*){2,}/g, "\n"); // all others
              +        }
              +        
              +        return input;
              +    },
              +    
              +    
              +    /**
              +     * Parse colour code operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {html}
              +     */
              +    run_parse_colour_code: function(input, args) {
              +        var m = null,
              +            r = 0, g = 0, b = 0, a = 1;
              +        
              +        // Read in the input
              +        if (!!(m = input.match(/#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/i))) {
              +            // Hex - #d9edf7
              +            r = parseInt(m[1], 16);
              +            g = parseInt(m[2], 16);
              +            b = parseInt(m[3], 16);
              +        } else if (!!(m = input.match(/rgba?\((\d{1,3}(?:\.\d+)?),\s?(\d{1,3}(?:\.\d+)?),\s?(\d{1,3}(?:\.\d+)?)(?:,\s?(\d(?:\.\d+)?))?\)/i))) {
              +            // RGB or RGBA - rgb(217,237,247) or rgba(217,237,247,1)
              +            r = parseFloat(m[1]);
              +            g = parseFloat(m[2]);
              +            b = parseFloat(m[3]);
              +            a = m[4] ? parseFloat(m[4]) : 1;
              +        } else if (!!(m = input.match(/hsla?\((\d{1,3}(?:\.\d+)?),\s?(\d{1,3}(?:\.\d+)?)%,\s?(\d{1,3}(?:\.\d+)?)%(?:,\s?(\d(?:\.\d+)?))?\)/i))) {
              +            // HSL or HSLA - hsl(200, 65%, 91%) or hsla(200, 65%, 91%, 1)
              +            var h_ = parseFloat(m[1]) / 360,
              +                s_ = parseFloat(m[2]) / 100,
              +                l_ = parseFloat(m[3]) / 100,
              +                rgb_ = HTML._hsl_to_rgb(h_, s_, l_);
              +            
              +            r = rgb_[0];
              +            g = rgb_[1];
              +            b = rgb_[2];
              +            a = m[4] ? parseFloat(m[4]) : 1;
              +        } else if (!!(m = input.match(/cmyk\((\d(?:\.\d+)?),\s?(\d(?:\.\d+)?),\s?(\d(?:\.\d+)?),\s?(\d(?:\.\d+)?)\)/i))) {
              +            // CMYK - cmyk(0.12, 0.04, 0.00, 0.03)
              +            var c_ = parseFloat(m[1]),
              +                m_ = parseFloat(m[2]),
              +                y_ = parseFloat(m[3]),
              +                k_ = parseFloat(m[4]);
              +
              +            r = Math.round(255 * (1 - c_) * (1 - k_));
              +            g = Math.round(255 * (1 - m_) * (1 - k_));
              +            b = Math.round(255 * (1 - y_) * (1 - k_));
              +        }
              +        
              +        var hsl_ = HTML._rgb_to_hsl(r, g, b),
              +            h = Math.round(hsl_[0] * 360),
              +            s = Math.round(hsl_[1] * 100),
              +            l = Math.round(hsl_[2] * 100),
              +            k = 1 - Math.max(r/255, g/255, b/255),
              +            c = (1 - r/255 - k) / (1 - k),
              +            m = (1 - g/255 - k) / (1 - k), // jshint ignore:line
              +            y = (1 - b/255 - k) / (1 - k);
              +            
              +        c = isNaN(c) ? "0" : c.toFixed(2);
              +        m = isNaN(m) ? "0" : m.toFixed(2);
              +        y = isNaN(y) ? "0" : y.toFixed(2);
              +        k = k.toFixed(2);
              +        
              +        var hex = "#" +
              +                Utils.pad_left(Math.round(r).toString(16), 2) +
              +                Utils.pad_left(Math.round(g).toString(16), 2) +
              +                Utils.pad_left(Math.round(b).toString(16), 2),
              +            rgb  = "rgb(" + r + ", " + g + ", " + b + ")",
              +            rgba = "rgba(" + r + ", " + g + ", " + b + ", " + a + ")",
              +            hsl  = "hsl(" + h + ", " + s + "%, " + l + "%)",
              +            hsla = "hsla(" + h + ", " + s + "%, " + l + "%, " + a + ")",
              +            cmyk = "cmyk(" + c + ", " + m + ", " + y + ", " + k + ")";
              +            
              +        // Generate output
              +        return "<div id='colorpicker' style='display: inline-block'></div>" + 
              +            "Hex:  " + hex + "\n" +
              +            "RGB:  " + rgb + "\n" +
              +            "RGBA: " + rgba + "\n" +
              +            "HSL:  " + hsl + "\n" +
              +            "HSLA: " + hsla + "\n" +
              +            "CMYK: " + cmyk +
              +            "<script>\
              +                $('#colorpicker').colorpicker({\
              +                    format: 'rgba',\
              +                    color: '" + rgba + "',\
              +                    container: true,\
              +                    inline: true,\
              +                }).on('changeColor', function(e) {\
              +                    var color = e.color.toRGB();\
              +                    document.getElementById('input-text').value = 'rgba(' +\
              +                        color.r + ', ' + color.g + ', ' + color.b + ', ' + color.a + ')';\
              +                    window.app.auto_bake();\
              +                });\
              +            </script>";
              +    },
              +    
              +    
              +    
              +    /**
              +     * Converts an HSL color value to RGB. Conversion formula
              +     * adapted from http://en.wikipedia.org/wiki/HSL_color_space.
              +     * Assumes h, s, and l are contained in the set [0, 1] and
              +     * returns r, g, and b in the set [0, 255].
              +     *
              +     * @private
              +     * @author Mohsen (http://stackoverflow.com/a/9493060)
              +     *
              +     * @param {number} h - The hue
              +     * @param {number} s - The saturation
              +     * @param {number} l - The lightness
              +     * @return {Array} The RGB representation
              +     */
              +    _hsl_to_rgb: function(h, s, l){
              +        var r, g, b;
              +
              +        if (s === 0){
              +            r = g = b = l; // achromatic
              +        } else {
              +            var hue2rgb = function hue2rgb(p, q, t) {
              +                if (t < 0) t += 1;
              +                if (t > 1) t -= 1;
              +                if (t < 1/6) return p + (q - p) * 6 * t;
              +                if (t < 1/2) return q;
              +                if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
              +                return p;
              +            };
              +
              +            var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
              +            var p = 2 * l - q;
              +            r = hue2rgb(p, q, h + 1/3);
              +            g = hue2rgb(p, q, h);
              +            b = hue2rgb(p, q, h - 1/3);
              +        }
              +
              +        return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
              +    },
              +    
              +    
              +    /**
              +     * Converts an RGB color value to HSL. Conversion formula
              +     * adapted from http://en.wikipedia.org/wiki/HSL_color_space.
              +     * Assumes r, g, and b are contained in the set [0, 255] and
              +     * returns h, s, and l in the set [0, 1].
              +     *
              +     * @private
              +     * @author Mohsen (http://stackoverflow.com/a/9493060)
              +     *
              +     * @param {number} r - The red color value
              +     * @param {number} g - The green color value
              +     * @param {number} b - The blue color value
              +     * @return {Array} The HSL representation
              +     */
              +    _rgb_to_hsl: function(r, g, b) {
              +        r /= 255; g /= 255; b /= 255;
              +        var max = Math.max(r, g, b),
              +            min = Math.min(r, g, b),
              +            h, s, l = (max + min) / 2;
              +
              +        if (max === min) {
              +            h = s = 0; // achromatic
              +        } else {
              +            var d = max - min;
              +            s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
              +            switch(max) {
              +                case r: h = (g - b) / d + (g < b ? 6 : 0); break;
              +                case g: h = (b - r) / d + 2; break;
              +                case b: h = (r - g) / d + 4; break;
              +            }
              +            h /= 6;
              +        }
              +
              +        return [h, s, l];
              +    },
              +    
              +    
              +    /**
              +     * Lookup table to translate byte values to their HTML entity codes.
              +     *
              +     * @private
              +     * @constant
              +     */
              +    _byte_to_entity: {
              +        34 : "&quot;",
              +        38 : "&amp;",
              +        39 : "&apos;",
              +        60 : "&lt;",
              +        62 : "&gt;",
              +        160 : "&nbsp;",
              +        161 : "&iexcl;",
              +        162 : "&cent;",
              +        163 : "&pound;",
              +        164 : "&curren;",
              +        165 : "&yen;",
              +        166 : "&brvbar;",
              +        167 : "&sect;",
              +        168 : "&uml;",
              +        169 : "&copy;",
              +        170 : "&ordf;",
              +        171 : "&laquo;",
              +        172 : "&not;",
              +        173 : "&shy;",
              +        174 : "&reg;",
              +        175 : "&macr;",
              +        176 : "&deg;",
              +        177 : "&plusmn;",
              +        178 : "&sup2;",
              +        179 : "&sup3;",
              +        180 : "&acute;",
              +        181 : "&micro;",
              +        182 : "&para;",
              +        183 : "&middot;",
              +        184 : "&cedil;",
              +        185 : "&sup1;",
              +        186 : "&ordm;",
              +        187 : "&raquo;",
              +        188 : "&frac14;",
              +        189 : "&frac12;",
              +        190 : "&frac34;",
              +        191 : "&iquest;",
              +        192 : "&Agrave;",
              +        193 : "&Aacute;",
              +        194 : "&Acirc;",
              +        195 : "&Atilde;",
              +        196 : "&Auml;",
              +        197 : "&Aring;",
              +        198 : "&AElig;",
              +        199 : "&Ccedil;",
              +        200 : "&Egrave;",
              +        201 : "&Eacute;",
              +        202 : "&Ecirc;",
              +        203 : "&Euml;",
              +        204 : "&Igrave;",
              +        205 : "&Iacute;",
              +        206 : "&Icirc;",
              +        207 : "&Iuml;",
              +        208 : "&ETH;",
              +        209 : "&Ntilde;",
              +        210 : "&Ograve;",
              +        211 : "&Oacute;",
              +        212 : "&Ocirc;",
              +        213 : "&Otilde;",
              +        214 : "&Ouml;",
              +        215 : "&times;",
              +        216 : "&Oslash;",
              +        217 : "&Ugrave;",
              +        218 : "&Uacute;",
              +        219 : "&Ucirc;",
              +        220 : "&Uuml;",
              +        221 : "&Yacute;",
              +        222 : "&THORN;",
              +        223 : "&szlig;",
              +        224 : "&agrave;",
              +        225 : "&aacute;",
              +        226 : "&acirc;",
              +        227 : "&atilde;",
              +        228 : "&auml;",
              +        229 : "&aring;",
              +        230 : "&aelig;",
              +        231 : "&ccedil;",
              +        232 : "&egrave;",
              +        233 : "&eacute;",
              +        234 : "&ecirc;",
              +        235 : "&euml;",
              +        236 : "&igrave;",
              +        237 : "&iacute;",
              +        238 : "&icirc;",
              +        239 : "&iuml;",
              +        240 : "&eth;",
              +        241 : "&ntilde;",
              +        242 : "&ograve;",
              +        243 : "&oacute;",
              +        244 : "&ocirc;",
              +        245 : "&otilde;",
              +        246 : "&ouml;",
              +        247 : "&divide;",
              +        248 : "&oslash;",
              +        249 : "&ugrave;",
              +        250 : "&uacute;",
              +        251 : "&ucirc;",
              +        252 : "&uuml;",
              +        253 : "&yacute;",
              +        254 : "&thorn;",
              +        255 : "&yuml;",
              +        338 : "&OElig;",
              +        339 : "&oelig;",
              +        352 : "&Scaron;",
              +        353 : "&scaron;",
              +        376 : "&Yuml;",
              +        402 : "&fnof;",
              +        710 : "&circ;",
              +        732 : "&tilde;",
              +        913 : "&Alpha;",
              +        914 : "&Beta;",
              +        915 : "&Gamma;",
              +        916 : "&Delta;",
              +        917 : "&Epsilon;",
              +        918 : "&Zeta;",
              +        919 : "&Eta;",
              +        920 : "&Theta;",
              +        921 : "&Iota;",
              +        922 : "&Kappa;",
              +        923 : "&Lambda;",
              +        924 : "&Mu;",
              +        925 : "&Nu;",
              +        926 : "&Xi;",
              +        927 : "&Omicron;",
              +        928 : "&Pi;",
              +        929 : "&Rho;",
              +        931 : "&Sigma;",
              +        932 : "&Tau;",
              +        933 : "&Upsilon;",
              +        934 : "&Phi;",
              +        935 : "&Chi;",
              +        936 : "&Psi;",
              +        937 : "&Omega;",
              +        945 : "&alpha;",
              +        946 : "&beta;",
              +        947 : "&gamma;",
              +        948 : "&delta;",
              +        949 : "&epsilon;",
              +        950 : "&zeta;",
              +        951 : "&eta;",
              +        952 : "&theta;",
              +        953 : "&iota;",
              +        954 : "&kappa;",
              +        955 : "&lambda;",
              +        956 : "&mu;",
              +        957 : "&nu;",
              +        958 : "&xi;",
              +        959 : "&omicron;",
              +        960 : "&pi;",
              +        961 : "&rho;",
              +        962 : "&sigmaf;",
              +        963 : "&sigma;",
              +        964 : "&tau;",
              +        965 : "&upsilon;",
              +        966 : "&phi;",
              +        967 : "&chi;",
              +        968 : "&psi;",
              +        969 : "&omega;",
              +        977 : "&thetasym;",
              +        978 : "&upsih;",
              +        982 : "&piv;",
              +        8194 : "&ensp;",
              +        8195 : "&emsp;",
              +        8201 : "&thinsp;",
              +        8204 : "&zwnj;",
              +        8205 : "&zwj;",
              +        8206 : "&lrm;",
              +        8207 : "&rlm;",
              +        8211 : "&ndash;",
              +        8212 : "&mdash;",
              +        8216 : "&lsquo;",
              +        8217 : "&rsquo;",
              +        8218 : "&sbquo;",
              +        8220 : "&ldquo;",
              +        8221 : "&rdquo;",
              +        8222 : "&bdquo;",
              +        8224 : "&dagger;",
              +        8225 : "&Dagger;",
              +        8226 : "&bull;",
              +        8230 : "&hellip;",
              +        8240 : "&permil;",
              +        8242 : "&prime;",
              +        8243 : "&Prime;",
              +        8249 : "&lsaquo;",
              +        8250 : "&rsaquo;",
              +        8254 : "&oline;",
              +        8260 : "&frasl;",
              +        8364 : "&euro;",
              +        8465 : "&image;",
              +        8472 : "&weierp;",
              +        8476 : "&real;",
              +        8482 : "&trade;",
              +        8501 : "&alefsym;",
              +        8592 : "&larr;",
              +        8593 : "&uarr;",
              +        8594 : "&rarr;",
              +        8595 : "&darr;",
              +        8596 : "&harr;",
              +        8629 : "&crarr;",
              +        8656 : "&lArr;",
              +        8657 : "&uArr;",
              +        8658 : "&rArr;",
              +        8659 : "&dArr;",
              +        8660 : "&hArr;",
              +        8704 : "&forall;",
              +        8706 : "&part;",
              +        8707 : "&exist;",
              +        8709 : "&empty;",
              +        8711 : "&nabla;",
              +        8712 : "&isin;",
              +        8713 : "&notin;",
              +        8715 : "&ni;",
              +        8719 : "&prod;",
              +        8721 : "&sum;",
              +        8722 : "&minus;",
              +        8727 : "&lowast;",
              +        8730 : "&radic;",
              +        8733 : "&prop;",
              +        8734 : "&infin;",
              +        8736 : "&ang;",
              +        8743 : "&and;",
              +        8744 : "&or;",
              +        8745 : "&cap;",
              +        8746 : "&cup;",
              +        8747 : "&int;",
              +        8756 : "&there4;",
              +        8764 : "&sim;",
              +        8773 : "&cong;",
              +        8776 : "&asymp;",
              +        8800 : "&ne;",
              +        8801 : "&equiv;",
              +        8804 : "&le;",
              +        8805 : "&ge;",
              +        8834 : "&sub;",
              +        8835 : "&sup;",
              +        8836 : "&nsub;",
              +        8838 : "&sube;",
              +        8839 : "&supe;",
              +        8853 : "&oplus;",
              +        8855 : "&otimes;",
              +        8869 : "&perp;",
              +        8901 : "&sdot;",
              +        8942 : "&vellip;",
              +        8968 : "&lceil;",
              +        8969 : "&rceil;",
              +        8970 : "&lfloor;",
              +        8971 : "&rfloor;",
              +        9001 : "&lang;",
              +        9002 : "&rang;",
              +        9674 : "&loz;",
              +        9824 : "&spades;",
              +        9827 : "&clubs;",
              +        9829 : "&hearts;",
              +        9830 : "&diams;",
              +    },
              +    
              +    
              +    /**
              +     * Lookup table to translate HTML entity codes to their byte values.
              +     *
              +     * @private
              +     * @constant
              +     */
              +    _entity_to_byte : {
              +        "quot" : 34,
              +        "amp" : 38,
              +        "apos" : 39,
              +        "lt" : 60,
              +        "gt" : 62,
              +        "nbsp" : 160,
              +        "iexcl" : 161,
              +        "cent" : 162,
              +        "pound" : 163,
              +        "curren" : 164,
              +        "yen" : 165,
              +        "brvbar" : 166,
              +        "sect" : 167,
              +        "uml" : 168,
              +        "copy" : 169,
              +        "ordf" : 170,
              +        "laquo" : 171,
              +        "not" : 172,
              +        "shy" : 173,
              +        "reg" : 174,
              +        "macr" : 175,
              +        "deg" : 176,
              +        "plusmn" : 177,
              +        "sup2" : 178,
              +        "sup3" : 179,
              +        "acute" : 180,
              +        "micro" : 181,
              +        "para" : 182,
              +        "middot" : 183,
              +        "cedil" : 184,
              +        "sup1" : 185,
              +        "ordm" : 186,
              +        "raquo" : 187,
              +        "frac14" : 188,
              +        "frac12" : 189,
              +        "frac34" : 190,
              +        "iquest" : 191,
              +        "Agrave" : 192,
              +        "Aacute" : 193,
              +        "Acirc" : 194,
              +        "Atilde" : 195,
              +        "Auml" : 196,
              +        "Aring" : 197,
              +        "AElig" : 198,
              +        "Ccedil" : 199,
              +        "Egrave" : 200,
              +        "Eacute" : 201,
              +        "Ecirc" : 202,
              +        "Euml" : 203,
              +        "Igrave" : 204,
              +        "Iacute" : 205,
              +        "Icirc" : 206,
              +        "Iuml" : 207,
              +        "ETH" : 208,
              +        "Ntilde" : 209,
              +        "Ograve" : 210,
              +        "Oacute" : 211,
              +        "Ocirc" : 212,
              +        "Otilde" : 213,
              +        "Ouml" : 214,
              +        "times" : 215,
              +        "Oslash" : 216,
              +        "Ugrave" : 217,
              +        "Uacute" : 218,
              +        "Ucirc" : 219,
              +        "Uuml" : 220,
              +        "Yacute" : 221,
              +        "THORN" : 222,
              +        "szlig" : 223,
              +        "agrave" : 224,
              +        "aacute" : 225,
              +        "acirc" : 226,
              +        "atilde" : 227,
              +        "auml" : 228,
              +        "aring" : 229,
              +        "aelig" : 230,
              +        "ccedil" : 231,
              +        "egrave" : 232,
              +        "eacute" : 233,
              +        "ecirc" : 234,
              +        "euml" : 235,
              +        "igrave" : 236,
              +        "iacute" : 237,
              +        "icirc" : 238,
              +        "iuml" : 239,
              +        "eth" : 240,
              +        "ntilde" : 241,
              +        "ograve" : 242,
              +        "oacute" : 243,
              +        "ocirc" : 244,
              +        "otilde" : 245,
              +        "ouml" : 246,
              +        "divide" : 247,
              +        "oslash" : 248,
              +        "ugrave" : 249,
              +        "uacute" : 250,
              +        "ucirc" : 251,
              +        "uuml" : 252,
              +        "yacute" : 253,
              +        "thorn" : 254,
              +        "yuml" : 255,
              +        "OElig" : 338,
              +        "oelig" : 339,
              +        "Scaron" : 352,
              +        "scaron" : 353,
              +        "Yuml" : 376,
              +        "fnof" : 402,
              +        "circ" : 710,
              +        "tilde" : 732,
              +        "Alpha" : 913,
              +        "Beta" : 914,
              +        "Gamma" : 915,
              +        "Delta" : 916,
              +        "Epsilon" : 917,
              +        "Zeta" : 918,
              +        "Eta" : 919,
              +        "Theta" : 920,
              +        "Iota" : 921,
              +        "Kappa" : 922,
              +        "Lambda" : 923,
              +        "Mu" : 924,
              +        "Nu" : 925,
              +        "Xi" : 926,
              +        "Omicron" : 927,
              +        "Pi" : 928,
              +        "Rho" : 929,
              +        "Sigma" : 931,
              +        "Tau" : 932,
              +        "Upsilon" : 933,
              +        "Phi" : 934,
              +        "Chi" : 935,
              +        "Psi" : 936,
              +        "Omega" : 937,
              +        "alpha" : 945,
              +        "beta" : 946,
              +        "gamma" : 947,
              +        "delta" : 948,
              +        "epsilon" : 949,
              +        "zeta" : 950,
              +        "eta" : 951,
              +        "theta" : 952,
              +        "iota" : 953,
              +        "kappa" : 954,
              +        "lambda" : 955,
              +        "mu" : 956,
              +        "nu" : 957,
              +        "xi" : 958,
              +        "omicron" : 959,
              +        "pi" : 960,
              +        "rho" : 961,
              +        "sigmaf" : 962,
              +        "sigma" : 963,
              +        "tau" : 964,
              +        "upsilon" : 965,
              +        "phi" : 966,
              +        "chi" : 967,
              +        "psi" : 968,
              +        "omega" : 969,
              +        "thetasym" : 977,
              +        "upsih" : 978,
              +        "piv" : 982,
              +        "ensp" : 8194,
              +        "emsp" : 8195,
              +        "thinsp" : 8201,
              +        "zwnj" : 8204,
              +        "zwj" : 8205,
              +        "lrm" : 8206,
              +        "rlm" : 8207,
              +        "ndash" : 8211,
              +        "mdash" : 8212,
              +        "lsquo" : 8216,
              +        "rsquo" : 8217,
              +        "sbquo" : 8218,
              +        "ldquo" : 8220,
              +        "rdquo" : 8221,
              +        "bdquo" : 8222,
              +        "dagger" : 8224,
              +        "Dagger" : 8225,
              +        "bull" : 8226,
              +        "hellip" : 8230,
              +        "permil" : 8240,
              +        "prime" : 8242,
              +        "Prime" : 8243,
              +        "lsaquo" : 8249,
              +        "rsaquo" : 8250,
              +        "oline" : 8254,
              +        "frasl" : 8260,
              +        "euro" : 8364,
              +        "image" : 8465,
              +        "weierp" : 8472,
              +        "real" : 8476,
              +        "trade" : 8482,
              +        "alefsym" : 8501,
              +        "larr" : 8592,
              +        "uarr" : 8593,
              +        "rarr" : 8594,
              +        "darr" : 8595,
              +        "harr" : 8596,
              +        "crarr" : 8629,
              +        "lArr" : 8656,
              +        "uArr" : 8657,
              +        "rArr" : 8658,
              +        "dArr" : 8659,
              +        "hArr" : 8660,
              +        "forall" : 8704,
              +        "part" : 8706,
              +        "exist" : 8707,
              +        "empty" : 8709,
              +        "nabla" : 8711,
              +        "isin" : 8712,
              +        "notin" : 8713,
              +        "ni" : 8715,
              +        "prod" : 8719,
              +        "sum" : 8721,
              +        "minus" : 8722,
              +        "lowast" : 8727,
              +        "radic" : 8730,
              +        "prop" : 8733,
              +        "infin" : 8734,
              +        "ang" : 8736,
              +        "and" : 8743,
              +        "or" : 8744,
              +        "cap" : 8745,
              +        "cup" : 8746,
              +        "int" : 8747,
              +        "there4" : 8756,
              +        "sim" : 8764,
              +        "cong" : 8773,
              +        "asymp" : 8776,
              +        "ne" : 8800,
              +        "equiv" : 8801,
              +        "le" : 8804,
              +        "ge" : 8805,
              +        "sub" : 8834,
              +        "sup" : 8835,
              +        "nsub" : 8836,
              +        "sube" : 8838,
              +        "supe" : 8839,
              +        "oplus" : 8853,
              +        "otimes" : 8855,
              +        "perp" : 8869,
              +        "sdot" : 8901,
              +        "vellip" : 8942,
              +        "lceil" : 8968,
              +        "rceil" : 8969,
              +        "lfloor" : 8970,
              +        "rfloor" : 8971,
              +        "lang" : 9001,
              +        "rang" : 9002,
              +        "loz" : 9674,
              +        "spades" : 9824,
              +        "clubs" : 9827,
              +        "hearts" : 9829,
              +        "diams" : 9830,
              +    },
              +
              +};
              diff --git a/src/js/operations/HTTP.js b/src/js/operations/HTTP.js
              new file mode 100755
              index 00000000..5b3dcf2d
              --- /dev/null
              +++ b/src/js/operations/HTTP.js
              @@ -0,0 +1,53 @@
              +/* globals UAS_parser */
              +
              +/**
              + * HTTP operations.
              + *
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @namespace
              + */
              +var HTTP = {
              +    
              +    /**
              +     * Strip HTTP headers operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_strip_headers: function(input, args) {
              +        var header_end = input.indexOf("\r\n\r\n") +
              +            (header_end < 0) ? input.indexOf("\n\n") + 2 : header_end + 4;
              +            
              +        return (header_end < 2) ? input : input.slice(header_end, input.length);
              +    },
              +    
              +    
              +    /**
              +     * Parse User Agent operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_parse_user_agent: function(input, args) {
              +        var ua = UAS_parser.parse(input);
              +        
              +        return "Type: " + ua.type + "\n" +
              +            "Family: " + ua.uaFamily + "\n" +
              +            "Name: " + ua.uaName + "\n" +
              +            "URL: " + ua.uaUrl + "\n" +
              +            "Company: " + ua.uaCompany + "\n" +
              +            "Company URL: " + ua.uaCompanyUrl + "\n\n" +
              +            "OS Family: " + ua.osFamily + "\n" +
              +            "OS Name: " + ua.osName + "\n" +
              +            "OS URL: " + ua.osUrl + "\n" +
              +            "OS Company: " + ua.osCompany + "\n" +
              +            "OS Company URL: " + ua.osCompanyUrl + "\n" +
              +            "Device Type: " + ua.deviceType + "\n";
              +    },
              +
              +};
              diff --git a/src/js/operations/Hash.js b/src/js/operations/Hash.js
              new file mode 100755
              index 00000000..983d2bff
              --- /dev/null
              +++ b/src/js/operations/Hash.js
              @@ -0,0 +1,341 @@
              +/* globals CryptoJS, Checksum */
              +
              +/**
              + * Hashing operations.
              + *
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @namespace
              + */
              +var Hash = {
              +    
              +    /**
              +     * MD5 operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_md5: function (input, args) {
              +        input = CryptoJS.enc.Latin1.parse(input); // Cast to WordArray
              +        return CryptoJS.MD5(input).toString(CryptoJS.enc.Hex);
              +    },
              +    
              +    
              +    /**
              +     * SHA1 operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_sha1: function (input, args) {
              +        input = CryptoJS.enc.Latin1.parse(input);
              +        return CryptoJS.SHA1(input).toString(CryptoJS.enc.Hex);
              +    },
              +
              +    
              +    /**
              +     * SHA224 operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_sha224: function (input, args) {
              +        input = CryptoJS.enc.Latin1.parse(input);
              +        return CryptoJS.SHA224(input).toString(CryptoJS.enc.Hex);
              +    },
              +    
              +    
              +    /**
              +     * SHA256 operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_sha256: function (input, args) {
              +        input = CryptoJS.enc.Latin1.parse(input);
              +        return CryptoJS.SHA256(input).toString(CryptoJS.enc.Hex);
              +    },
              +    
              +    
              +    /**
              +     * SHA384 operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_sha384: function (input, args) {
              +        input = CryptoJS.enc.Latin1.parse(input);
              +        return CryptoJS.SHA384(input).toString(CryptoJS.enc.Hex);
              +    },
              +    
              +    
              +    /**
              +     * SHA512 operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_sha512: function (input, args) {
              +        input = CryptoJS.enc.Latin1.parse(input);
              +        return CryptoJS.SHA512(input).toString(CryptoJS.enc.Hex);
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    SHA3_LENGTH: ["512", "384", "256", "224"],
              +    
              +    /**
              +     * SHA3 operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_sha3: function (input, args) {
              +        input = CryptoJS.enc.Latin1.parse(input);
              +        var sha3_length = args[0],
              +            options = {
              +                outputLength: parseInt(sha3_length, 10)
              +            };
              +        return CryptoJS.SHA3(input, options).toString(CryptoJS.enc.Hex);
              +    },
              +    
              +    
              +    /**
              +     * RIPEMD-160 operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_ripemd160: function (input, args) {
              +        input = CryptoJS.enc.Latin1.parse(input);
              +        return CryptoJS.RIPEMD160(input).toString(CryptoJS.enc.Hex);
              +    },
              +
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    HMAC_FUNCTIONS: ["MD5", "SHA1", "SHA224", "SHA256", "SHA384", "SHA512", "SHA3", "RIPEMD-160"],
              +    
              +    /**
              +     * HMAC operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_hmac: function (input, args) {
              +        var hash_func = args[1];
              +        input = CryptoJS.enc.Latin1.parse(input);
              +        var execute = {
              +            "MD5": CryptoJS.HmacMD5(input, args[0]),
              +            "SHA1": CryptoJS.HmacSHA1(input, args[0]),
              +            "SHA224": CryptoJS.HmacSHA224(input, args[0]),
              +            "SHA256": CryptoJS.HmacSHA256(input, args[0]),
              +            "SHA384": CryptoJS.HmacSHA384(input, args[0]),
              +            "SHA512": CryptoJS.HmacSHA512(input, args[0]),
              +            "SHA3": CryptoJS.HmacSHA3(input, args[0]),
              +            "RIPEMD-160": CryptoJS.HmacRIPEMD160(input, args[0]),
              +        };
              +        return execute[hash_func].toString(CryptoJS.enc.Hex);
              +    },
              +    
              +    
              +    /**
              +     * Generate all hashes operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_all: function (input, args) {
              +        var byte_array = Utils.str_to_byte_array(input),
              +            output = "MD5:         " + Hash.run_md5(input, []) +
              +                "\nSHA1:        " + Hash.run_sha1(input, []) +
              +                "\nSHA2 224:    " + Hash.run_sha224(input, []) +
              +                "\nSHA2 256:    " + Hash.run_sha256(input, []) +
              +                "\nSHA2 384:    " + Hash.run_sha384(input, []) +
              +                "\nSHA2 512:    " + Hash.run_sha512(input, []) +
              +                "\nSHA3 224:    " + Hash.run_sha3(input, ["224"]) +
              +                "\nSHA3 256:    " + Hash.run_sha3(input, ["256"]) +
              +                "\nSHA3 384:    " + Hash.run_sha3(input, ["384"]) +
              +                "\nSHA3 512:    " + Hash.run_sha3(input, ["512"]) +
              +                "\nRIPEMD-160:  " + Hash.run_ripemd160(input, []) +
              +                "\n\nChecksums:" +
              +                "\nFletcher-16: " + Checksum.run_fletcher16(byte_array, []) +
              +                "\nAdler-32:    " + Checksum.run_adler32(byte_array, []) +
              +                "\nCRC-32:      " + Checksum.run_crc32(byte_array, []);
              +                
              +        return output;
              +    },
              +    
              +    
              +    /**
              +     * Analyse hash operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_analyse: function(input, args) {
              +        input = input.replace(/\s/g, "");
              +    
              +        var output = "",
              +            byte_length = input.length / 2,
              +            bit_length = byte_length * 8,
              +            possible_hash_functions = [];
              +        
              +        if (!/^[a-f0-9]+$/i.test(input)) {
              +            return "Invalid hash";
              +        }
              +        
              +        output += "Hash length: " + input.length + "\n" +
              +            "Byte length: " + byte_length + "\n" +
              +            "Bit length:  " + bit_length + "\n\n" +
              +            "Based on the length, this hash could have been generated by one of the following hashing functions:\n";
              +                
              +        switch (bit_length) {
              +            case 4:
              +                possible_hash_functions = [
              +                    "Fletcher-4",
              +                    "Luhn algorithm",
              +                    "Verhoeff algorithm",
              +                ];
              +                break;
              +            case 8:
              +                possible_hash_functions = [
              +                    "Fletcher-8",
              +                ];
              +                break;
              +            case 16:
              +                possible_hash_functions = [
              +                    "BSD checksum",
              +                    "CRC-16",
              +                    "SYSV checksum",
              +                    "Fletcher-16"
              +                ];
              +                break;
              +            case 32:
              +                possible_hash_functions = [
              +                    "CRC-32",
              +                    "Fletcher-32",
              +                    "Adler-32",
              +                ];
              +                break;
              +            case 64:
              +                possible_hash_functions = [
              +                    "CRC-64",
              +                    "RIPEMD-64",
              +                    "SipHash",
              +                ];
              +                break;
              +            case 128:
              +                possible_hash_functions = [
              +                    "MD5",
              +                    "MD4",
              +                    "MD2",
              +                    "HAVAL-128",
              +                    "RIPEMD-128",
              +                    "Snefru",
              +                    "Tiger-128",
              +                ];
              +                break;
              +            case 160:
              +                possible_hash_functions = [
              +                    "SHA-1",
              +                    "SHA-0",
              +                    "FSB-160",
              +                    "HAS-160",
              +                    "HAVAL-160",
              +                    "RIPEMD-160",
              +                    "Tiger-160",
              +                ];
              +                break;
              +            case 192:
              +                possible_hash_functions = [
              +                    "Tiger",
              +                    "HAVAL-192",
              +                ];
              +                break;
              +            case 224:
              +                possible_hash_functions = [
              +                    "SHA-224",
              +                    "SHA3-224",
              +                    "ECOH-224",
              +                    "FSB-224",
              +                    "HAVAL-224",
              +                ];
              +                break;
              +            case 256:
              +                possible_hash_functions = [
              +                    "SHA-256",
              +                    "SHA3-256",
              +                    "BLAKE-256",
              +                    "ECOH-256",
              +                    "FSB-256",
              +                    "GOST",
              +                    "Grøstl-256",
              +                    "HAVAL-256",
              +                    "PANAMA",
              +                    "RIPEMD-256",
              +                    "Snefru",
              +                ];
              +                break;
              +            case 320:
              +                possible_hash_functions = [
              +                    "RIPEMD-320",
              +                ];
              +                break;
              +            case 384:
              +                possible_hash_functions = [
              +                    "SHA-384",
              +                    "SHA3-384",
              +                    "ECOH-384",
              +                    "FSB-384",
              +                ];
              +                break;
              +            case 512:
              +                possible_hash_functions = [
              +                    "SHA-512",
              +                    "SHA3-512",
              +                    "BLAKE-512",
              +                    "ECOH-512",
              +                    "FSB-512",
              +                    "Grøstl-512",
              +                    "JH",
              +                    "MD6",
              +                    "Spectral Hash",
              +                    "SWIFFT",
              +                    "Whirlpool",
              +                ];
              +                break;
              +            case 1024:
              +                possible_hash_functions = [
              +                    "Fowler-Noll-Vo",
              +                ];
              +                break;
              +            default:
              +                possible_hash_functions = [
              +                    "Unknown"
              +                ];
              +                break;
              +        }
              +        
              +        return output + possible_hash_functions.join("\n");
              +    },
              +    
              +};
              diff --git a/src/js/operations/Hexdump.js b/src/js/operations/Hexdump.js
              new file mode 100755
              index 00000000..7132ed8a
              --- /dev/null
              +++ b/src/js/operations/Hexdump.js
              @@ -0,0 +1,195 @@
              +/* globals app */
              +
              +/**
              + * Hexdump operations.
              + *
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @namespace
              + */
              +var Hexdump = {
              +
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    WIDTH: 16,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    UPPER_CASE: false,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    INCLUDE_FINAL_LENGTH: false,
              +    
              +    /**
              +     * To Hexdump operation.
              +     *
              +     * @param {byte_array} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_to: function(input, args) {
              +        var length = args[0] || Hexdump.WIDTH;
              +        var upper_case = args[1];
              +        var include_final_length = args[2];
              +        
              +        var output = "", padding = 2;
              +        for (var i = 0; i < input.length; i += length) {
              +            var buff = input.slice(i, i+length);
              +            var hexa = "";
              +            for (var j = 0; j < buff.length; j++) {
              +                hexa += Utils.hex(buff[j], padding) + " ";
              +            }
              +            
              +            var line_no = Utils.hex(i, 8);
              +            
              +            if (upper_case) {
              +                hexa = hexa.toUpperCase();
              +                line_no = line_no.toUpperCase();
              +            }
              +            
              +            output += line_no + "  " +
              +                Utils.pad_right(hexa, (length*(padding+1))) +
              +                " |" + Utils.pad_right(Utils.printable(Utils.byte_array_to_chars(buff)), buff.length) + "|\n";
              +                
              +            if (include_final_length && i+buff.length == input.length) {
              +                output += Utils.hex(i+buff.length, 8) + "\n";
              +            }
              +        }
              +        
              +        return output.slice(0, -1);
              +    },
              +    
              +    
              +    /**
              +     * From Hexdump operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {byte_array}
              +     */
              +    run_from: function(input, args) {
              +        var output = [],
              +            regex = /^\s*(?:[\dA-F]{4,16}:?)?\s*((?:[\dA-F]{2}\s){1,8}(?:\s|[\dA-F]{2}-)(?:[\dA-F]{2}\s){1,8}|(?:[\dA-F]{2}\s|[\dA-F]{4}\s)+)/igm,
              +            block, line;
              +            
              +        while (!!(block = regex.exec(input))) {
              +            line = Utils.from_hex(block[1].replace(/-/g, " "));
              +            for (var i = 0; i < line.length; i++) {
              +                output.push(line[i]);
              +            }
              +        }
              +        // Is this a CyberChef hexdump or is it from a different tool?
              +        var width = input.indexOf("\n");
              +        var w = (width - 13) / 4;
              +        // w should be the specified width of the hexdump and therefore a round number
              +        if (Math.floor(w) != w || input.indexOf("\r") != -1 || output.indexOf(13) != -1) {
              +            app.options.attempt_highlight = false;
              +        }
              +        return output;
              +    },
              +    
              +    
              +    /**
              +     * Highlight to hexdump
              +     *
              +     * @param {Object[]} pos
              +     * @param {number} pos[].start
              +     * @param {number} pos[].end
              +     * @param {Object[]} args
              +     * @returns {Object[]} pos
              +     */
              +    highlight_to: function(pos, args) {
              +        // Calculate overall selection
              +        var w = args[0] || 16,
              +            width = 14 + (w*4),
              +            line = Math.floor(pos[0].start / w),
              +            offset = pos[0].start % w,
              +            start = 0,
              +            end = 0;
              +            
              +        pos[0].start = line*width + 10 + offset*3;
              +        
              +        line = Math.floor(pos[0].end / w);
              +        offset = pos[0].end % w;
              +        if (offset === 0) { line--; offset = w; }
              +        pos[0].end = line*width + 10 + offset*3 - 1;
              +        
              +        // Set up multiple selections for bytes
              +        var start_line_num = Math.floor(pos[0].start / width);
              +        var end_line_num = Math.floor(pos[0].end / width);
              +        
              +        if (start_line_num == end_line_num) {
              +            pos.push(pos[0]);
              +        } else {
              +            start = pos[0].start;
              +            end = (start_line_num+1) * width - w - 5;
              +            pos.push({ start: start, end: end });
              +            while (end < pos[0].end) {
              +                start_line_num++;
              +                start = start_line_num * width + 10;
              +                end = (start_line_num+1) * width - w - 5;
              +                if (end > pos[0].end) end = pos[0].end;
              +                pos.push({ start: start, end: end });
              +            }
              +        }
              +        
              +        // Set up multiple selections for ASCII
              +        var len = pos.length, line_num = 0;
              +        start = 0;
              +        end = 0;
              +        for (var i = 1; i < len; i++) {
              +            line_num = Math.floor(pos[i].start / width);
              +            start = (((pos[i].start - (line_num * width)) - 10) / 3) + (width - w -2) + (line_num * width);
              +            end = (((pos[i].end + 1 - (line_num * width)) - 10) / 3) + (width - w -2) + (line_num * width);
              +            pos.push({ start: start, end: end });
              +        }
              +        return pos;
              +    },
              +    
              +    
              +    /**
              +     * Highlight from hexdump
              +     *
              +     * @param {Object[]} pos
              +     * @param {number} pos[].start
              +     * @param {number} pos[].end
              +     * @param {Object[]} args
              +     * @returns {Object[]} pos
              +     */
              +    highlight_from: function(pos, args) {
              +        var w = args[0] || 16;
              +        var width = 14 + (w*4);
              +        
              +        var line = Math.floor(pos[0].start / width);
              +        var offset = pos[0].start % width;
              +        
              +        if (offset < 10) { // In line number section
              +            pos[0].start = line*w;
              +        } else if (offset > 10+(w*3)) { // In ASCII section
              +            pos[0].start = (line+1)*w;
              +        } else { // In byte section
              +            pos[0].start = line*w + Math.floor((offset-10)/3);
              +        }
              +        
              +        line = Math.floor(pos[0].end / width);
              +        offset = pos[0].end % width;
              +        
              +        if (offset < 10) { // In line number section
              +            pos[0].end = line*w;
              +        } else if (offset > 10+(w*3)) { // In ASCII section
              +            pos[0].end = (line+1)*w;
              +        } else { // In byte section
              +            pos[0].end = line*w + Math.ceil((offset-10)/3);
              +        }
              +        
              +        return pos;
              +    },
              +    
              +};
              diff --git a/src/js/operations/IP.js b/src/js/operations/IP.js
              new file mode 100755
              index 00000000..6a86df00
              --- /dev/null
              +++ b/src/js/operations/IP.js
              @@ -0,0 +1,802 @@
              +/* globals BigInteger */
              +
              +/**
              + * Internet Protocol address operations.
              + *
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @namespace
              + */
              +var IP = {
              +
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    INCLUDE_NETWORK_INFO: true,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    ENUMERATE_ADDRESSES: true,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    ALLOW_LARGE_LIST: false,
              +    
              +    /**
              +     * Parse IP range operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_parse_ip_range: function (input, args) {
              +        var include_network_info = args[0],
              +            enumerate_addresses = args[1],
              +            allow_large_list = args[2];
              +        
              +        // Check what type of input we are looking at
              +        var ipv4_cidr_regex = /^\s*((?:\d{1,3}\.){3}\d{1,3})\/(\d\d?)\s*$/,
              +            ipv4_range_regex = /^\s*((?:\d{1,3}\.){3}\d{1,3})\s*-\s*((?:\d{1,3}\.){3}\d{1,3})\s*$/,
              +            ipv6_cidr_regex = /^\s*(((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\4)::|:\b|(?![\dA-F])))|(?!\3\4)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\/(\d\d?\d?)\s*$/i,
              +            ipv6_range_regex = /^\s*(((?=.*::)(?!.*::[^-]+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\4)::|:\b|(?![\dA-F])))|(?!\3\4)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\s*-\s*(((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\17)::|:\b|(?![\dA-F])))|(?!\16\17)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\s*$/i,
              +            match;
              +        
              +        if (!!(match = ipv4_cidr_regex.exec(input))) {
              +            return IP._ipv4_cidr_range(match, include_network_info, enumerate_addresses, allow_large_list);
              +        } else if (!!(match = ipv4_range_regex.exec(input))) {
              +            return IP._ipv4_hyphenated_range(match, include_network_info, enumerate_addresses, allow_large_list);
              +        } else if (!!(match = ipv6_cidr_regex.exec(input))) {
              +            return IP._ipv6_cidr_range(match, include_network_info);
              +        } else if (!!(match = ipv6_range_regex.exec(input))) {
              +            return IP._ipv6_hyphenated_range(match, include_network_info);
              +        } else {
              +            return "Invalid input.\n\nEnter either a CIDR range (e.g. 10.0.0.0/24) or a hyphenated range (e.g. 10.0.0.0 - 10.0.1.0). IPv6 also supported.";
              +        }
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    IPv4_REGEX: /^\s*((?:\d{1,3}\.){3}\d{1,3})\s*$/,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    IPv6_REGEX: /^\s*(((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\4)::|:\b|(?![\dA-F])))|(?!\3\4)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\s*$/i,
              +    
              +    /**
              +     * Parse IPv6 address operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_parse_ipv6: function (input, args) {
              +        var match,
              +            output = "";
              +        
              +        if (!!(match = IP.IPv6_REGEX.exec(input))) {
              +            var ipv6 = IP._str_to_ipv6(match[1]),
              +                longhand = IP._ipv6_to_str(ipv6),
              +                shorthand = IP._ipv6_to_str(ipv6, true);
              +                
              +            output += "Longhand:  " + longhand + "\nShorthand: " + shorthand + "\n";
              +            
              +            // Detect reserved addresses
              +            if (shorthand == "::") {
              +                // Unspecified address
              +                output += "\nUnspecified address corresponding to 0.0.0.0/32 in IPv4.";
              +                output += "\nUnspecified address range: ::/128";
              +            } else if (shorthand == "::1") {
              +                // Loopback address
              +                output += "\nLoopback address to the local host corresponding to 127.0.0.1/8 in IPv4.";
              +                output += "\nLoopback addresses range: ::1/128";
              +            } else if (ipv6[0] === 0 && ipv6[1] === 0 && ipv6[2] === 0 &&
              +                ipv6[3] === 0 && ipv6[4] === 0 && ipv6[5] === 0xffff) {
              +                // IPv4-mapped IPv6 address
              +                output += "\nIPv4-mapped IPv6 address detected. IPv6 clients will be handled natively by default, and IPv4 clients appear as IPv6 clients at their IPv4-mapped IPv6 address.";
              +                output += "\nMapped IPv4 address: " + IP._ipv4_to_str((ipv6[6] << 16) + ipv6[7]);
              +                output += "\nIPv4-mapped IPv6 addresses range: ::ffff:0:0/96";
              +            } else if (ipv6[0] === 0 && ipv6[1] === 0 && ipv6[2] === 0 &&
              +                ipv6[3] === 0 && ipv6[4] === 0xffff && ipv6[5] === 0) {
              +                // IPv4-translated address
              +                output += "\nIPv4-translated address detected. Used by Stateless IP/ICMP Translation (SIIT). See RFCs 6145 and 6052 for more details.";
              +                output += "\nTranslated IPv4 address: " + IP._ipv4_to_str((ipv6[6] << 16) + ipv6[7]);
              +                output += "\nIPv4-translated addresses range: ::ffff:0:0:0/96";
              +            } else if (ipv6[0] === 0x100) {
              +                // Discard prefix per RFC 6666
              +                output += "\nDiscard prefix detected. This is used when forwarding traffic to a sinkhole router to mitigate the effects of a denial-of-service attack. See RFC 6666 for more details.";
              +                output += "\nDiscard range: 100::/64";
              +            } else if (ipv6[0] === 0x64 && ipv6[1] === 0xff9b && ipv6[2] === 0 &&
              +                ipv6[3] === 0 && ipv6[4] === 0 && ipv6[5] === 0) {
              +                // IPv4/IPv6 translation per RFC 6052
              +                output += "\n'Well-Known' prefix for IPv4/IPv6 translation detected. See RFC 6052 for more details.";
              +                output += "\nTranslated IPv4 address: " + IP._ipv4_to_str((ipv6[6] << 16) + ipv6[7]);
              +                output += "\n'Well-Known prefix range: 64:ff9b::/96";
              +            } else if (ipv6[0] === 0x2001 && ipv6[1] === 0) {
              +                // Teredo tunneling
              +                output += "\nTeredo tunneling IPv6 address detected\n";
              +                var server_ipv4  = (ipv6[2] << 16) + ipv6[3],
              +                    udp_port     = (~ipv6[5]) & 0xffff,
              +                    client_ipv4  = ~((ipv6[6] << 16) + ipv6[7]),
              +                    flag_cone    = (ipv6[4] >>> 15) & 1,
              +                    flag_r       = (ipv6[4] >>> 14) & 1,
              +                    flag_random1 = (ipv6[4] >>> 10) & 15,
              +                    flag_ug      = (ipv6[4] >>> 8) & 3,
              +                    flag_random2 = ipv6[4] & 255;
              +                
              +                output += "\nServer IPv4 address: " + IP._ipv4_to_str(server_ipv4) +
              +                    "\nClient IPv4 address: " + IP._ipv4_to_str(client_ipv4) +
              +                    "\nClient UDP port:     " + udp_port +
              +                    "\nFlags:" +
              +                    "\n\tCone:    " + flag_cone;
              +                    
              +                if (flag_cone) {
              +                    output += " (Client is behind a cone NAT)";
              +                } else {
              +                    output += " (Client is not behind a cone NAT)";
              +                }
              +                
              +                output += "\n\tR:       " + flag_r;
              +                
              +                if (flag_r) {
              +                    output += " Error: This flag should be set to 0. See RFC 5991 and RFC 4380.";
              +                }
              +                    
              +                output += "\n\tRandom1: " + Utils.bin(flag_random1, 4) +
              +                    "\n\tUG:      " + Utils.bin(flag_ug, 2);
              +                        
              +                if (flag_ug) {
              +                    output += " Error: This flag should be set to 00. See RFC 4380.";
              +                }
              +                    
              +                output += "\n\tRandom2: " + Utils.bin(flag_random2, 8);
              +                
              +                if (!flag_r && !flag_ug && flag_random1 && flag_random2) {
              +                    output += "\n\nThis is a valid Teredo address which complies with RFC 4380 and RFC 5991.";
              +                } else if (!flag_r && !flag_ug) {
              +                    output += "\n\nThis is a valid Teredo address which complies with RFC 4380, however it does not comply with RFC 5991 (Teredo Security Updates) as there are no randomised bits in the flag field.";
              +                } else {
              +                    output += "\n\nThis is an invalid Teredo address.";
              +                }
              +                output += "\n\nTeredo prefix range: 2001::/32";
              +            } else if (ipv6[0] === 0x2001 && ipv6[1] === 0x2 && ipv6[2] === 0) {
              +                // Benchmarking
              +                output += "\nAssigned to the Benchmarking Methodology Working Group (BMWG) for benchmarking IPv6. Corresponds to 198.18.0.0/15 for benchmarking IPv4. See RFC 5180 for more details.";
              +                output += "\nBMWG range: 2001:2::/48";
              +            } else if (ipv6[0] == 0x2001 && ipv6[1] >= 0x10 && ipv6[1] <= 0x1f) {
              +                // ORCHIDv1
              +                output += "\nDeprecated, previously ORCHIDv1 (Overlay Routable Cryptographic Hash Identifiers).\nORCHIDv1 range: 2001:10::/28\nORCHIDv2 now uses 2001:20::/28.";
              +            } else if (ipv6[0] == 0x2001 && ipv6[1] >= 0x20 && ipv6[1] <= 0x2f) {
              +                // ORCHIDv2
              +                output += "\nORCHIDv2 (Overlay Routable Cryptographic Hash Identifiers).\nThese are non-routed IPv6 addresses used for Cryptographic Hash Identifiers.";
              +                output += "\nORCHIDv2 range: 2001:20::/28";
              +            } else if (ipv6[0] == 0x2001 && ipv6[1] == 0xdb8) {
              +                // Documentation
              +                output += "\nThis is a documentation IPv6 address. This range should be used whenever an example IPv6 address is given or to model networking scenarios. Corresponds to 192.0.2.0/24, 198.51.100.0/24, and 203.0.113.0/24 in IPv4.";
              +                output += "\nDocumentation range: 2001:db8::/32";
              +            } else if (ipv6[0] == 0x2002) {
              +                // 6to4
              +                output += "\n6to4 transition IPv6 address detected. See RFC 3056 for more details." +
              +                    "\n6to4 prefix range: 2002::/16";
              +                
              +                var v4_addr = IP._ipv4_to_str((ipv6[1] << 16) + ipv6[2]),
              +                    sla_id = ipv6[3],
              +                    interface_id_str = ipv6[4].toString(16) + ipv6[5].toString(16) + ipv6[6].toString(16) + ipv6[7].toString(16),
              +                    interface_id = new BigInteger(interface_id_str, 16);
              +                
              +                output += "\n\nEncapsulated IPv4 address: " + v4_addr +
              +                    "\nSLA ID: " + sla_id +
              +                    "\nInterface ID (base 16): " + interface_id_str +
              +                    "\nInterface ID (base 10): " + interface_id.toString();
              +            } else if (ipv6[0] >= 0xfc00 && ipv6[0] <= 0xfdff) {
              +                // Unique local address
              +                output += "\nThis is a unique local address comparable to the IPv4 private addresses 10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16. See RFC 4193 for more details.";
              +                output += "\nUnique local addresses range: fc00::/7";
              +            } else if (ipv6[0] >= 0xfe80 && ipv6[0] <= 0xfebf) {
              +                // Link-local address
              +                output += "\nThis is a link-local address comparable to the auto-configuration addresses 169.254.0.0/16 in IPv4.";
              +                output += "\nLink-local addresses range: fe80::/10";
              +            } else if (ipv6[0] >= 0xff00) {
              +                // Multicast
              +                output += "\nThis is a reserved multicast address.";
              +                output += "\nMulticast addresses range: ff00::/8";
              +            }
              +        } else {
              +            return "Invalid IPv6 address";
              +        }
              +        return output;
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    IP_FORMAT_LIST: ["Dotted Decimal", "Decimal", "Hex"],
              +    
              +    /**
              +     * Change IP format operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_change_ip_format: function(input, args) {
              +        var in_format  = args[0],
              +            out_format = args[1],
              +            lines = input.split("\n"),
              +            output = "",
              +            j = 0;
              +            
              +        
              +        for (var i = 0; i < lines.length; i++) {
              +            if (lines[i] === "") continue;
              +            var ba_ip = [];
              +            
              +            if (in_format == out_format) {
              +                output += lines[i] + "\n";
              +                continue;
              +            }
              +            
              +            // Convert to byte array IP from input format
              +            switch (in_format) {
              +                case "Dotted Decimal":
              +                    var octets = lines[i].split(".");
              +                    for (j = 0; j < octets.length; j++) {
              +                        ba_ip.push(parseInt(octets[j], 10));
              +                    }
              +                    break;
              +                case "Decimal":
              +                    var decimal = lines[i].toString();
              +                    ba_ip.push(decimal >> 24 & 255);
              +                    ba_ip.push(decimal >> 16 & 255);
              +                    ba_ip.push(decimal >> 8 & 255);
              +                    ba_ip.push(decimal & 255);
              +                    break;
              +                case "Hex":
              +                    ba_ip = Utils.hex_to_byte_array(lines[i]);
              +                    break;
              +                default:
              +                    throw "Unsupported input IP format";
              +            }
              +            
              +            // Convert byte array IP to output format
              +            switch (out_format) {
              +                case "Dotted Decimal":
              +                    var dd_ip = "";
              +                    for (j = 0; j < ba_ip.length; j++) {
              +                        dd_ip += ba_ip[j] + ".";
              +                    }
              +                    output += dd_ip.slice(0, dd_ip.length-1) + "\n";
              +                    break;
              +                case "Decimal":
              +                    var dec_ip = ((ba_ip[0] << 24) | (ba_ip[1] << 16) | (ba_ip[2] << 8) | ba_ip[3]) >>> 0;
              +                    output += dec_ip.toString() + "\n";
              +                    break;
              +                case "Hex":
              +                    var hex_ip = "";
              +                    for (j = 0; j < ba_ip.length; j++) {
              +                        hex_ip += Utils.hex(ba_ip[j]);
              +                    }
              +                    output += hex_ip + "\n";
              +                    break;
              +                default:
              +                    throw "Unsupported output IP format";
              +            }
              +        }
              +        
              +        return output.slice(0, output.length-1);
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    DELIM_OPTIONS: ["Line feed", "CRLF", "Space", "Comma", "Semi-colon"],
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    GROUP_CIDR: 24,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    GROUP_ONLY_SUBNET: false,
              +    
              +    /**
              +     * Group IP addresses operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_group_ips: function(input, args) {
              +        var delim = Utils.char_rep[args[0]],
              +            cidr = args[1],
              +            only_subnets = args[2],
              +            ipv4_mask = cidr < 32 ? ~(0xFFFFFFFF >>> cidr) : 0xFFFFFFFF,
              +            ipv6_mask = IP._gen_ipv6_mask(cidr),
              +            ips = input.split(delim),
              +            ipv4_networks = {},
              +            ipv6_networks = {},
              +            match = null,
              +            output = "",
              +            ip = null,
              +            network = null,
              +            network_str = "";
              +            
              +        if (cidr < 0 || cidr > 127) {
              +            return "CIDR must be less than 32 for IPv4 or 128 for IPv6";
              +        }
              +            
              +        // Parse all IPs and add to network dictionary
              +        for (var i = 0; i < ips.length; i++) {
              +            if (!!(match = IP.IPv4_REGEX.exec(ips[i]))) {
              +                ip = IP._str_to_ipv4(match[1]) >>> 0;
              +                network = ip & ipv4_mask;
              +                
              +                if (ipv4_networks.hasOwnProperty(network)) {
              +                    ipv4_networks[network].push(ip);
              +                } else {
              +                    ipv4_networks[network] = [ip];
              +                }
              +            } else if (!!(match = IP.IPv6_REGEX.exec(ips[i]))) {
              +                ip = IP._str_to_ipv6(match[1]);
              +                network = [];
              +                network_str = "";
              +                
              +                for (var j = 0; j < 8; j++) {
              +                    network.push(ip[j] & ipv6_mask[j]);
              +                }
              +                
              +                network_str = IP._ipv6_to_str(network, true);
              +                
              +                if (ipv6_networks.hasOwnProperty(network_str)) {
              +                    ipv6_networks[network_str].push(ip);
              +                } else {
              +                    ipv6_networks[network_str] = [ip];
              +                }
              +            }
              +        }
              +        
              +        // Sort IPv4 network dictionaries and print
              +        for (network in ipv4_networks) {
              +            ipv4_networks[network] = ipv4_networks[network].sort();
              +            
              +            output += IP._ipv4_to_str(network) + "/" + cidr + "\n";
              +            
              +            if (!only_subnets) {
              +                for (i = 0; i < ipv4_networks[network].length; i++) {
              +                    output += "  " + IP._ipv4_to_str(ipv4_networks[network][i]) + "\n";
              +                }
              +                output += "\n";
              +            }
              +        }
              +        
              +        // Sort IPv6 network dictionaries and print
              +        for (network_str in ipv6_networks) {
              +            //ipv6_networks[network_str] = ipv6_networks[network_str].sort();  TODO
              +            
              +            output += network_str + "/" + cidr + "\n";
              +            
              +            if (!only_subnets) {
              +                for (i = 0; i < ipv6_networks[network_str].length; i++) {
              +                    output += "  " + IP._ipv6_to_str(ipv6_networks[network_str][i], true) + "\n";
              +                }
              +                output += "\n";
              +            }
              +        }
              +
              +        return output;
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     * @default
              +     * @private
              +     */
              +    _LARGE_RANGE_ERROR: "The specified range contains more than 65,536 addresses. Running this query could crash your browser. If you want to run it, select the \"Allow large queries\" option. You are advised to turn off \"Auto Bake\" whilst editing large ranges.",
              +    
              +    /**
              +     * Parses an IPv4 CIDR range (e.g. 192.168.0.0/24) and displays information about it.
              +     *
              +     * @private
              +     * @param {RegExp} cidr
              +     * @param {boolean} include_network_info
              +     * @param {boolean} enumerate_addresses
              +     * @param {boolean} allow_large_list
              +     * @returns {string}
              +     */
              +    _ipv4_cidr_range: function(cidr, include_network_info, enumerate_addresses, allow_large_list) {
              +        var output = "",
              +            network = IP._str_to_ipv4(cidr[1]),
              +            cidr_range = parseInt(cidr[2], 10);
              +            
              +        if (cidr_range < 0 || cidr_range > 31) {
              +            return "IPv4 CIDR must be less than 32";
              +        }
              +        
              +        var mask = ~(0xFFFFFFFF >>> cidr_range),
              +            ip1 = network & mask,
              +            ip2 = ip1 | ~mask;
              +        
              +        if (include_network_info) {
              +            output += "Network: " + IP._ipv4_to_str(network) + "\n";
              +            output += "CIDR: " + cidr_range + "\n";
              +            output += "Mask: " + IP._ipv4_to_str(mask) + "\n";
              +            output += "Range: " + IP._ipv4_to_str(ip1) + " - " + IP._ipv4_to_str(ip2) + "\n";
              +            output += "Total addresses in range: " + (((ip2 - ip1) >>> 0) + 1) + "\n\n";
              +        }
              +        
              +        if (enumerate_addresses) {
              +            if (cidr_range >= 16 || allow_large_list) {
              +                output += IP._generate_ipv4_range(ip1, ip2).join("\n");
              +            } else {
              +                output += IP._LARGE_RANGE_ERROR;
              +            }
              +        }
              +        return output;
              +    },
              +    
              +    
              +    /**
              +     * Parses an IPv6 CIDR range (e.g. ff00::/48) and displays information about it.
              +     *
              +     * @private
              +     * @param {RegExp} cidr
              +     * @param {boolean} include_network_info
              +     * @returns {string}
              +     */
              +    _ipv6_cidr_range: function(cidr, include_network_info) {
              +        var output = "",
              +            network = IP._str_to_ipv6(cidr[1]),
              +            cidr_range = parseInt(cidr[cidr.length-1], 10);
              +            
              +        if (cidr_range < 0 || cidr_range > 127) {
              +            return "IPv6 CIDR must be less than 128";
              +        }
              +        
              +        var mask = IP._gen_ipv6_mask(cidr_range),
              +            ip1 = new Array(8),
              +            ip2 = new Array(8),
              +            total_diff = "",
              +            total = new Array(128);
              +            
              +        for (var i = 0; i < 8; i++) {
              +            ip1[i] = network[i] & mask[i];
              +            ip2[i] = ip1[i] | (~mask[i] & 0x0000FFFF);
              +            total_diff = (ip2[i] - ip1[i]).toString(2);
              +            
              +            if (total_diff != "0") {
              +                for (var n = 0; n < total_diff.length; n++) {
              +                    total[i*16 + 16-(total_diff.length-n)] = total_diff[n];
              +                }
              +            }
              +        }
              +
              +        if (include_network_info) {
              +            output += "Network: " + IP._ipv6_to_str(network) + "\n";
              +            output += "Shorthand: " + IP._ipv6_to_str(network, true) + "\n";
              +            output += "CIDR: " + cidr_range + "\n";
              +            output += "Mask: " + IP._ipv6_to_str(mask) + "\n";
              +            output += "Range: " + IP._ipv6_to_str(ip1) + " - " + IP._ipv6_to_str(ip2) + "\n";
              +            output += "Total addresses in range: " + (parseInt(total.join(""), 2) + 1) + "\n\n";
              +        }
              +        
              +        return output;
              +    },
              +    
              +    
              +    /**
              +     * Generates an IPv6 subnet mask given a CIDR value.
              +     *
              +     * @private
              +     * @param {number} cidr
              +     * @returns {number[]}
              +     */
              +    _gen_ipv6_mask: function(cidr) {
              +        var mask = new Array(8),
              +            shift;
              +            
              +        for (var i = 0; i < 8; i++) {
              +            if (cidr > ((i+1)*16)) {
              +                mask[i] = 0x0000FFFF;
              +            } else {
              +                shift = cidr-(i*16);
              +                if (shift < 0) shift = 0;
              +                mask[i] = ~((0x0000FFFF >>> shift) | 0xFFFF0000);
              +            }
              +        }
              +        
              +        return mask;
              +    },
              +    
              +    
              +    /**
              +     * Parses an IPv4 hyphenated range (e.g. 192.168.0.0 - 192.168.0.255) and displays information
              +     * about it.
              +     *
              +     * @private
              +     * @param {RegExp} range
              +     * @param {boolean} include_network_info
              +     * @param {boolean} enumerate_addresses
              +     * @param {boolean} allow_large_list
              +     * @returns {string}
              +     */
              +    _ipv4_hyphenated_range: function(range, include_network_info, enumerate_addresses, allow_large_list) {
              +        var output = "",
              +            ip1 = IP._str_to_ipv4(range[1]),
              +            ip2 = IP._str_to_ipv4(range[2]);
              +        
              +        // Calculate mask
              +        var diff = ip1 ^ ip2,
              +            cidr = 32,
              +            mask = 0;
              +            
              +        while (diff !== 0) {
              +            diff >>= 1;
              +            cidr--;
              +            mask = (mask << 1) | 1;
              +        }
              +        
              +        mask = ~mask >>> 0;
              +        var network = ip1 & mask,
              +            sub_ip1 = network & mask,
              +            sub_ip2 = sub_ip1 | ~mask;
              +        
              +        if (include_network_info) {
              +            output += "Minimum subnet required to hold this range:\n";
              +            output += "\tNetwork: " + IP._ipv4_to_str(network) + "\n";
              +            output += "\tCIDR: " + cidr + "\n";
              +            output += "\tMask: " + IP._ipv4_to_str(mask) + "\n";
              +            output += "\tSubnet range: " + IP._ipv4_to_str(sub_ip1) + " - " + IP._ipv4_to_str(sub_ip2) + "\n";
              +            output += "\tTotal addresses in subnet: " + (((sub_ip2 - sub_ip1) >>> 0) + 1) + "\n\n";
              +            output += "Range: " + IP._ipv4_to_str(ip1) + " - " + IP._ipv4_to_str(ip2) + "\n";
              +            output += "Total addresses in range: " + (((ip2 - ip1) >>> 0) + 1) + "\n\n";
              +        }
              +        
              +        if (enumerate_addresses) {
              +            if (((ip2 - ip1) >>> 0) <= 65536 || allow_large_list) {
              +                output += IP._generate_ipv4_range(ip1, ip2).join("\n");
              +            } else {
              +                output += IP._LARGE_RANGE_ERROR;
              +            }
              +        }
              +        return output;
              +    },
              +    
              +    
              +    /**
              +     * Parses an IPv6 hyphenated range (e.g. ff00:: - ffff::) and displays information about it.
              +     *
              +     * @private
              +     * @param {RegExp} range
              +     * @param {boolean} include_network_info
              +     * @returns {string}
              +     */
              +    _ipv6_hyphenated_range: function(range, include_network_info) {
              +        var output = "",
              +            ip1 = IP._str_to_ipv6(range[1]),
              +            ip2 = IP._str_to_ipv6(range[14]);
              +        
              +        var t = "",
              +            total = new Array(128);
              +            
              +        // Initialise total array to "0"
              +        for (var i = 0; i < 128; i++)
              +            total[i] = "0";
              +        
              +        for (i = 0; i < 8; i++) {
              +            t = (ip2[i] - ip1[i]).toString(2);
              +            if (t != "0") {
              +                for (var n = 0; n < t.length; n++) {
              +                    total[i*16 + 16-(t.length-n)] = t[n];
              +                }
              +            }
              +        }
              +        
              +        if (include_network_info) {
              +            output += "Range: " + IP._ipv6_to_str(ip1) + " - " + IP._ipv6_to_str(ip2) + "\n";
              +            output += "Shorthand range: " + IP._ipv6_to_str(ip1, true) + " - " + IP._ipv6_to_str(ip2, true) + "\n";
              +            output += "Total addresses in range: " + (parseInt(total.join(""), 2) + 1) + "\n\n";
              +        }
              +        
              +        return output;
              +    },
              +    
              +    
              +    /**
              +     * Converts an IPv4 address from string format to numerical format.
              +     *
              +     * @private
              +     * @param {string} ip_str
              +     * @returns {number}
              +     *
              +     * @example
              +     * // returns 168427520
              +     * IP._str_to_ipv4("10.10.0.0");
              +     */
              +    _str_to_ipv4: function (ip_str) {
              +        var blocks = ip_str.split("."),
              +            num_blocks = parse_blocks(blocks),
              +            result = 0;
              +            
              +        result += num_blocks[0] << 24;
              +        result += num_blocks[1] << 16;
              +        result += num_blocks[2] << 8;
              +        result += num_blocks[3];
              +        
              +        return result;
              +        
              +        function parse_blocks(blocks) {
              +            if (blocks.length != 4)
              +                throw "More than 4 blocks.";
              +                
              +            var num_blocks = [];
              +            for (var i = 0; i < 4; i++) {
              +                num_blocks[i] = parseInt(blocks[i], 10);
              +                if (num_blocks[i] < 0 || num_blocks[i] > 255)
              +                    throw "Block out of range.";
              +            }
              +            return num_blocks;
              +        }
              +    },
              +    
              +    
              +    /**
              +     * Converts an IPv4 address from numerical format to string format.
              +     *
              +     * @private
              +     * @param {number} ip_int
              +     * @returns {string}
              +     *
              +     * @example
              +     * // returns "10.10.0.0"
              +     * IP._ipv4_to_str(168427520);
              +     */
              +    _ipv4_to_str: function(ip_int) {
              +        var blockA = (ip_int >> 24) & 255,
              +            blockB = (ip_int >> 16) & 255,
              +            blockC = (ip_int >> 8) & 255,
              +            blockD = ip_int & 255;
              +        
              +        return blockA + "." + blockB + "." + blockC + "." + blockD;
              +    },
              +    
              +    
              +    /**
              +     * Converts an IPv6 address from string format to numerical array format.
              +     *
              +     * @private
              +     * @param {string} ip_str
              +     * @returns {number[]}
              +     *
              +     * @example
              +     * // returns [65280, 0, 0, 0, 0, 0, 4369, 8738]
              +     * IP._str_to_ipv6("ff00::1111:2222");
              +     */
              +    _str_to_ipv6: function(ip_str) {
              +        var blocks = ip_str.split(":"),
              +            num_blocks = parse_blocks(blocks),
              +            j = 0,
              +            ipv6 = new Array(8);
              +        
              +        for (var i = 0; i < 8; i++) {
              +            if (isNaN(num_blocks[j])) {
              +                ipv6[i] = 0;
              +                if (i == (8-num_blocks.slice(j).length)) j++;
              +            } else {
              +                ipv6[i] = num_blocks[j];
              +                j++;
              +            }
              +        }
              +        return ipv6;
              +        
              +        function parse_blocks(blocks) {
              +            if (blocks.length < 3 || blocks.length > 8)
              +                throw "Badly formatted IPv6 address.";
              +            var num_blocks = [];
              +            for (var i = 0; i < blocks.length; i++) {
              +                num_blocks[i] = parseInt(blocks[i], 16);
              +                if (num_blocks[i] < 0 || num_blocks[i] > 65535)
              +                    throw "Block out of range.";
              +            }
              +            return num_blocks;
              +        }
              +    },
              +    
              +    
              +    /**
              +     * Converts an IPv6 address from numerical array format to string format.
              +     *
              +     * @private
              +     * @param {number[]} ipv6
              +     * @param {boolean} compact - Whether or not to return the address in shorthand or not
              +     * @returns {string}
              +     *
              +     * @example
              +     * // returns "ff00::1111:2222"
              +     * IP._ipv6_to_str([65280, 0, 0, 0, 0, 0, 4369, 8738], true);
              +     *
              +     * // returns "ff00:0000:0000:0000:0000:0000:1111:2222"
              +     * IP._ipv6_to_str([65280, 0, 0, 0, 0, 0, 4369, 8738], false);
              +     */
              +    _ipv6_to_str: function(ipv6, compact) {
              +        var output = "",
              +            skips = 0,
              +            i = 0;
              +            
              +        if (compact) {
              +            var start = -1,
              +                end = -1,
              +                s = 0,
              +                e = -1;
              +                
              +            for (i = 0; i < 8; i++) {
              +                if (ipv6[i] === 0 && e === (i-1)) {
              +                    e = i;
              +                } else if (ipv6[i] === 0) {
              +                    s = i; e = i;
              +                }
              +                if (e >= 0 && (e-s) > (end - start)) {
              +                    start = s;
              +                    end = e;
              +                }
              +            }
              +            
              +            for (i = 0; i < 8; i++) {
              +                if (i != start) {
              +                    output += Utils.hex(ipv6[i],1) + ":";
              +                } else {
              +                    output += ":";
              +                    i = end;
              +                    if (end === 7) output += ":";
              +                }
              +            }
              +            if (output[0] === ":")
              +                output = ":" + output;
              +        } else {
              +            for (i = 0; i < 8; i++) {
              +                output += Utils.hex(ipv6[i],4) + ":";
              +            }
              +        }
              +        return output.slice(0,output.length-1);
              +    },
              +    
              +    
              +    /**
              +     * Generates a list of IPv4 addresses in string format between two given numerical values.
              +     *
              +     * @private
              +     * @param {number} ip
              +     * @param {number} end_ip
              +     * @returns {string[]}
              +     *
              +     * @example
              +     * // returns ["0.0.0.1", "0.0.0.2", "0.0.0.3"]
              +     * IP._generate_ipv4_range(1, 3);
              +     */
              +    _generate_ipv4_range: function(ip, end_ip) {
              +        var range = [];
              +        if (end_ip >= ip) {
              +            for (; ip <= end_ip; ip++) {
              +                range.push(IP._ipv4_to_str(ip));
              +            }
              +        } else {
              +            range[0] = "Second IP address smaller than first.";
              +        }
              +        return range;
              +    },
              +
              +};
              diff --git a/src/js/operations/JS.js b/src/js/operations/JS.js
              new file mode 100755
              index 00000000..076c6321
              --- /dev/null
              +++ b/src/js/operations/JS.js
              @@ -0,0 +1,159 @@
              +/* globals esprima, escodegen, esmangle */
              +
              +/**
              + * JavaScript operations.
              + *
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @namespace
              + */
              +var JS = {
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    PARSE_LOC: false,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    PARSE_RANGE: false,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    PARSE_TOKENS: false,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    PARSE_COMMENT: false,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    PARSE_TOLERANT: false,
              +    
              +    /**
              +     * JavaScript Parser operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_parse: function (input, args) {
              +        var parse_loc = args[0],
              +            parse_range = args[1],
              +            parse_tokens = args[2],
              +            parse_comment = args[3],
              +            parse_tolerant = args[4],
              +            result = {},
              +            options = {
              +                loc:      parse_loc,
              +                range:    parse_range,
              +                tokens:   parse_tokens,
              +                comment:  parse_comment,
              +                tolerant: parse_tolerant
              +            };
              +            
              +        result = esprima.parse(input, options);
              +        return JSON.stringify(result, null, 2);
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    BEAUTIFY_INDENT: "\\t",
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    BEAUTIFY_QUOTES: ["Auto", "Single", "Double"],
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    BEAUTIFY_SEMICOLONS: true,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    BEAUTIFY_COMMENT: true,
              +    
              +    /**
              +     * JavaScript Beautify operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_beautify: function(input, args) {
              +        var beautify_indent = args[0] || JS.BEAUTIFY_INDENT,
              +            quotes = args[1].toLowerCase(),
              +            beautify_semicolons = args[2],
              +            beautify_comment = args[3],
              +            result = "",
              +            AST;
              +            
              +        try {
              +            AST = esprima.parse(input, {
              +                range: true,
              +                tokens: true,
              +                comment: true
              +            });
              +            
              +            var options = {
              +                format: {
              +                    indent: {
              +                        style: beautify_indent
              +                    },
              +                    quotes: quotes,
              +                    semicolons: beautify_semicolons,
              +                },
              +                comment: beautify_comment
              +            };
              +            
              +            if (options.comment)
              +                AST = escodegen.attachComments(AST, AST.comments, AST.tokens);
              +                
              +            result = escodegen.generate(AST, options);
              +        } catch(e) {
              +            // Leave original error so the user can see the detail
              +            throw "Unable to parse JavaScript.<br>" + e.message;
              +        }
              +        return result;
              +    },
              +    
              +    
              +    /**
              +     * JavaScript Minify operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_minify: function(input, args) {
              +        var result = "",
              +            AST = esprima.parse(input),
              +            optimised_AST = esmangle.optimize(AST, null),
              +            mangled_AST = esmangle.mangle(optimised_AST);
              +            
              +        result = escodegen.generate(mangled_AST, {
              +            format: {
              +                renumber:    true,
              +                hexadecimal: true,
              +                escapeless:  true,
              +                compact:     true,
              +                semicolons:  false,
              +                parentheses: false
              +            }
              +        });
              +        return result;
              +    },
              +
              +};
              diff --git a/src/js/operations/MAC.js b/src/js/operations/MAC.js
              new file mode 100755
              index 00000000..5a800b91
              --- /dev/null
              +++ b/src/js/operations/MAC.js
              @@ -0,0 +1,88 @@
              +/**
              + * MAC address operations.
              + *
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @namespace
              + */
              +var MAC = {
              +
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    OUTPUT_CASE: ["Both", "Upper only", "Lower only"],
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    NO_DELIM: true,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    DASH_DELIM: true,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    COLON_DELIM: true,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    CISCO_STYLE: false,
              +
              +    /**
              +     * Format MAC addresses operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_format: function(input, args) {
              +        if (!input) return "";
              +    
              +        var output_case = args[0],
              +            no_delim = args[1],
              +            dash_delim = args[2],
              +            colon_delim = args[3],
              +            cisco_style = args[4],
              +            output_list = [],
              +            macs = input.toLowerCase().split(/[,\s\r\n]+/);
              +
              +        macs.forEach(function(mac) {
              +            var cleanMac = mac.replace(/[:.-]+/g, ''),
              +                macHyphen = cleanMac.replace(/(.{2}(?=.))/g, '$1-'),
              +                macColon = cleanMac.replace(/(.{2}(?=.))/g, '$1:'),
              +                macCisco = cleanMac.replace(/(.{4}(?=.))/g, '$1.');
              +                
              +            if (output_case == "Lower only") {
              +                if (no_delim) output_list.push(cleanMac);
              +                if (dash_delim) output_list.push(macHyphen);
              +                if (colon_delim) output_list.push(macColon);
              +                if (cisco_style) output_list.push(macCisco);
              +            } else if (output_case == "Upper only") {
              +                if (no_delim) output_list.push(cleanMac.toUpperCase());
              +                if (dash_delim) output_list.push(macHyphen.toUpperCase());
              +                if (colon_delim) output_list.push(macColon.toUpperCase());
              +                if (cisco_style) output_list.push(macCisco.toUpperCase());
              +            } else {
              +                if (no_delim) output_list.push(cleanMac, cleanMac.toUpperCase());
              +                if (dash_delim) output_list.push(macHyphen, macHyphen.toUpperCase());
              +                if (colon_delim) output_list.push(macColon, macColon.toUpperCase());
              +                if (cisco_style) output_list.push(macCisco, macCisco.toUpperCase());
              +            }
              +            
              +            output_list.push(
              +                "" // Empty line to delimit groups
              +            );
              +        });
              +
              +        // Return the data as a string
              +        return output_list.join('\n');
              +    },
              +
              +};
              diff --git a/src/js/operations/Numberwang.js b/src/js/operations/Numberwang.js
              new file mode 100755
              index 00000000..a178b0b8
              --- /dev/null
              +++ b/src/js/operations/Numberwang.js
              @@ -0,0 +1,27 @@
              +/**
              + * Numberwang operations.
              + *
              + * @author Unknown Male 282
              + * @namespace
              + */
              +var Numberwang = {
              +
              +    /**
              +     * Numberwang operation. Remain indoors.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run: function(input, args) {
              +        if (!input) return "Let's play Wangernumb!";
              +        var match = input.match(/\d+/);
              +        if (match) {
              +            return match[0] + "! That's Numberwang!";
              +        } else {
              +            // That's a bad miss!
              +            return "Sorry, that's not Numberwang. Let's rotate the board!";
              +        }
              +    },
              +    
              +};
              diff --git a/src/js/operations/OS.js b/src/js/operations/OS.js
              new file mode 100755
              index 00000000..90d24810
              --- /dev/null
              +++ b/src/js/operations/OS.js
              @@ -0,0 +1,309 @@
              +/**
              + * Operating system operations.
              + *
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @namespace
              + */
              +var OS = {
              +
              +    /**
              +     * Parse UNIX file permissions operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_parse_unix_perms: function(input, args) {
              +        var perms = {
              +                d : false,  // directory
              +                sl : false, // symbolic link
              +                np : false, // named pipe
              +                s : false,  // socket
              +                cd : false, // character device
              +                bd : false, // block device
              +                dr : false, // door
              +                sb : false, // sticky bit
              +                su : false, // setuid
              +                sg : false, // setgid
              +                ru : false, // read user
              +                wu : false, // write user
              +                eu : false, // execute user
              +                rg : false, // read group
              +                wg : false, // write group
              +                eg : false, // execute group
              +                ro : false, // read other
              +                wo : false, // write other
              +                eo : false // execute other
              +            },
              +            d = 0,
              +            u = 0,
              +            g = 0,
              +            o = 0,
              +            output = "",
              +            octal = null,
              +            textual = null;
              +        
              +        if (input.search(/\s*[0-7]{1,4}\s*/i) === 0) {
              +            // Input is octal
              +            octal = input.match(/\s*([0-7]{1,4})\s*/i)[1];
              +
              +            if (octal.length == 4) {
              +                d = parseInt(octal[0], 8);
              +                u = parseInt(octal[1], 8);
              +                g = parseInt(octal[2], 8);
              +                o = parseInt(octal[3], 8);
              +            } else {
              +                if (octal.length > 0) u = parseInt(octal[0], 8);
              +                if (octal.length > 1) g = parseInt(octal[1], 8);
              +                if (octal.length > 2) o = parseInt(octal[2], 8);
              +            }
              +            
              +            perms.su = d >> 2 & 0x1;
              +            perms.sg = d >> 1 & 0x1;
              +            perms.sb = d & 0x1;
              +                    
              +            perms.ru = u >> 2 & 0x1;
              +            perms.wu = u >> 1 & 0x1;
              +            perms.eu = u & 0x1;
              +            
              +            perms.rg = g >> 2 & 0x1;
              +            perms.wg = g >> 1 & 0x1;
              +            perms.eg = g & 0x1;
              +            
              +            perms.ro = o >> 2 & 0x1;
              +            perms.wo = o >> 1 & 0x1;
              +            perms.eo = o & 0x1;
              +        } else if (input.search(/\s*[dlpcbDrwxsStT-]{1,10}\s*/) === 0) {
              +            // Input is textual
              +            textual = input.match(/\s*([dlpcbDrwxsStT-]{1,10})\s*/)[1];
              +            
              +            switch (textual[0]) {
              +                case "d":
              +                    perms.d = true;
              +                    break;
              +                case "l":
              +                    perms.sl = true;
              +                    break;
              +                case "p":
              +                    perms.np = true;
              +                    break;
              +                case "s":
              +                    perms.s = true;
              +                    break;
              +                case "c":
              +                    perms.cd = true;
              +                    break;
              +                case "b":
              +                    perms.bd = true;
              +                    break;
              +                case "D":
              +                    perms.dr = true;
              +                    break;
              +            }
              +            
              +            if (textual.length > 1) perms.ru = textual[1] == "r";
              +            if (textual.length > 2) perms.wu = textual[2] == "w";
              +            if (textual.length > 3) {
              +                switch (textual[3]) {
              +                    case "x":
              +                        perms.eu = true;
              +                        break;
              +                    case "s":
              +                        perms.eu = true;
              +                        perms.su = true;
              +                        break;
              +                    case "S":
              +                        perms.su = true;
              +                        break;
              +                }
              +            }
              +            
              +            if (textual.length > 4) perms.rg = textual[4] == "r";
              +            if (textual.length > 5) perms.wg = textual[5] == "w";
              +            if (textual.length > 6) {
              +                switch (textual[6]) {
              +                    case "x":
              +                        perms.eg = true;
              +                        break;
              +                    case "s":
              +                        perms.eg = true;
              +                        perms.sg = true;
              +                        break;
              +                    case "S":
              +                        perms.sg = true;
              +                        break;
              +                }
              +            }
              +            
              +            if (textual.length > 7) perms.ro = textual[7] == "r";
              +            if (textual.length > 8) perms.wo = textual[8] == "w";
              +            if (textual.length > 9) {
              +                switch (textual[9]) {
              +                    case "x":
              +                        perms.eo = true;
              +                        break;
              +                    case "t":
              +                        perms.eo = true;
              +                        perms.sb = true;
              +                        break;
              +                    case "T":
              +                        perms.sb = true;
              +                        break;
              +                }
              +            }
              +        } else {
              +            return "Invalid input format.\nPlease enter the permissions in either octal (e.g. 755) or textual (e.g. drwxr-xr-x) format.";
              +        }
              +        
              +        output += "Textual representation: " + OS._perms_to_str(perms);
              +        output += "\nOctal representation:   " + OS._perms_to_octal(perms);
              + 
              +        // File type
              +        if (textual) {
              +            output += "\nFile type: " + OS._ft_from_perms(perms);
              +        }
              +        
              +        // setuid, setgid
              +        if (perms.su) {
              +            output += "\nThe setuid flag is set";
              +        }
              +        if (perms.sg) {
              +            output += "\nThe setgid flag is set";
              +        }
              +        
              +        // sticky bit
              +        if (perms.sb) {
              +            output += "\nThe sticky bit is set";
              +        }
              +        
              +        // Permission matrix
              +        output += "\n\n +---------+-------+-------+-------+\n" +
              +            " |         | User  | Group | Other |\n" + 
              +            " +---------+-------+-------+-------+\n" +
              +            " |    Read |   " + (perms.ru ? "X" : " ") + "   |   " + (perms.rg ? "X" : " ") + "   |   " + (perms.ro ? "X" : " ") + "   |\n" +
              +            " +---------+-------+-------+-------+\n" +
              +            " |   Write |   " + (perms.wu ? "X" : " ") + "   |   " + (perms.wg ? "X" : " ") + "   |   " + (perms.wo ? "X" : " ") + "   |\n" +
              +            " +---------+-------+-------+-------+\n" +
              +            " | Execute |   " + (perms.eu ? "X" : " ") + "   |   " + (perms.eg ? "X" : " ") + "   |   " + (perms.eo ? "X" : " ") + "   |\n" +
              +            " +---------+-------+-------+-------+\n";
              + 
              +        return output;
              +    },
              +    
              +    
              +    /**
              +     * Given a permissions object dictionary, generates a textual permissions string.
              +     *
              +     * @private
              +     * @param {Object} perms
              +     * @returns {string}
              +     */
              +    _perms_to_str: function(perms) {
              +        var str = "",
              +            type = "-";
              +            
              +        if (perms.d) type = "d";
              +        if (perms.sl) type = "l";
              +        if (perms.np) type = "p";
              +        if (perms.s) type = "s";
              +        if (perms.cd) type = "c";
              +        if (perms.bd) type = "b";
              +        if (perms.dr) type = "D";
              +        
              +        str = type;
              +        
              +        str += perms.ru ? "r" : "-";
              +        str += perms.wu ? "w" : "-";
              +        if (perms.eu && perms.su) {
              +            str += "s";
              +        } else if (perms.su) {
              +            str += "S";
              +        } else if (perms.eu) {
              +            str += "x";
              +        } else {
              +            str += "-";
              +        }
              +        
              +        str += perms.rg ? "r" : "-";
              +        str += perms.wg ? "w" : "-";
              +        if (perms.eg && perms.sg) {
              +            str += "s";
              +        } else if (perms.sg) {
              +            str += "S";
              +        } else if (perms.eg) {
              +            str += "x";
              +        } else {
              +            str += "-";
              +        }
              +        
              +        str += perms.ro ? "r" : "-";
              +        str += perms.wo ? "w" : "-";
              +        if (perms.eo && perms.sb) {
              +            str += "t";
              +        } else if (perms.sb) {
              +            str += "T";
              +        } else if (perms.eo) {
              +            str += "x";
              +        } else {
              +            str += "-";
              +        }
              +        
              +        return str;
              +    },
              +    
              +    
              +    /**
              +     * Given a permissions object dictionary, generates an octal permissions string.
              +     *
              +     * @private
              +     * @param {Object} perms
              +     * @returns {string}
              +     */
              +    _perms_to_octal: function(perms) {
              +        var d = 0,
              +            u = 0,
              +            g = 0,
              +            o = 0;
              +        
              +        if (perms.su) d += 4;
              +        if (perms.sg) d += 2;
              +        if (perms.sb) d += 1;
              +        
              +        if (perms.ru) u += 4;
              +        if (perms.wu) u += 2;
              +        if (perms.eu) u += 1;
              +        
              +        if (perms.rg) g += 4;
              +        if (perms.wg) g += 2;
              +        if (perms.eg) g += 1;
              +        
              +        if (perms.ro) o += 4;
              +        if (perms.wo) o += 2;
              +        if (perms.eo) o += 1;
              +        
              +        return d.toString() + u.toString() + g.toString() + o.toString();
              +    },
              +    
              +    
              +    /**
              +     * Given a permissions object dictionary, returns the file type.
              +     *
              +     * @private
              +     * @param {Object} perms
              +     * @returns {string}
              +     */
              +    _ft_from_perms: function(perms) {
              +        if (perms.d) return "Directory";
              +        if (perms.sl) return "Symbolic link";
              +        if (perms.np) return "Named pipe";
              +        if (perms.s) return "Socket";
              +        if (perms.cd) return "Character device";
              +        if (perms.bd) return "Block device";
              +        if (perms.dr) return "Door";
              +        return "Regular file";
              +    },
              +    
              +};
              diff --git a/src/js/operations/PublicKey.js b/src/js/operations/PublicKey.js
              new file mode 100755
              index 00000000..7b7cae62
              --- /dev/null
              +++ b/src/js/operations/PublicKey.js
              @@ -0,0 +1,1053 @@
              +/* globals X509, KJUR, ASN1HEX, KEYUTIL, BigInteger */
              +
              +/**
              + * Public Key operations.
              + *
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @namespace
              + */
              +var PublicKey = {
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    X509_INPUT_FORMAT: ["PEM", "DER Hex", "Base64", "Raw"],
              +    
              +    /**
              +     * Parse X.509 certificate operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_parse_x509: function (input, args) {
              +        var cert = new X509(),
              +            input_format = args[0];
              +            
              +        if (!input.length) {
              +            return "No input";
              +        }
              +        
              +        switch (input_format) {
              +            case "DER Hex":
              +                input = input.replace(/\s/g, "");
              +                cert.hex = input;
              +                cert.pem = KJUR.asn1.ASN1Util.getPEMStringFromHex(input, "CERTIFICATE");
              +                break;
              +            case "PEM":
              +                cert.hex = X509.pemToHex(input);
              +                cert.pem = input;
              +                break;
              +            case "Base64":
              +                cert.hex = Utils.to_hex(Utils.from_base64(input, null, "byte_array"), "");
              +                cert.pem = KJUR.asn1.ASN1Util.getPEMStringFromHex(cert.hex, "CERTIFICATE");
              +                break;
              +            case "Raw":
              +                cert.hex = Utils.to_hex(Utils.str_to_byte_array(input), "");
              +                cert.pem = KJUR.asn1.ASN1Util.getPEMStringFromHex(cert.hex, "CERTIFICATE");
              +                break;
              +            default:
              +                throw "Undefined input format";
              +        }
              +        
              +        var version = ASN1HEX.getDecendantHexVByNthList(cert.hex, 0, [0, 0, 0]),
              +            sn = cert.getSerialNumberHex(),
              +            algorithm = KJUR.asn1.x509.OID.oid2name(KJUR.asn1.ASN1Util.oidHexToInt(ASN1HEX.getDecendantHexVByNthList(cert.hex, 0, [0, 2, 0]))),
              +            issuer = cert.getIssuerString(),
              +            not_before = cert.getNotBefore(),
              +            not_after = cert.getNotAfter(),
              +            subject = cert.getSubjectString(),
              +            pk_algorithm = KJUR.asn1.x509.OID.oid2name(KJUR.asn1.ASN1Util.oidHexToInt(ASN1HEX.getDecendantHexVByNthList(cert.hex, 0, [0, 6, 0, 0]))),
              +            pk = X509.getPublicKeyFromCertPEM(cert.pem),
              +            pk_fields = [],
              +            pk_str = "",
              +            cert_sig_alg = KJUR.asn1.x509.OID.oid2name(KJUR.asn1.ASN1Util.oidHexToInt(ASN1HEX.getDecendantHexVByNthList(cert.hex, 0, [1, 0]))),
              +            cert_sig = ASN1HEX.getDecendantHexVByNthList(cert.hex, 0, [2]).substr(2),
              +            sig_str = "",
              +            extensions = ASN1HEX.dump(ASN1HEX.getDecendantHexVByNthList(cert.hex, 0, [0, 7]));
              +        
              +        // Public Key fields
              +        if (pk.type == "EC") { // ECDSA
              +            pk_fields.push({
              +                key: "Curve Name",
              +                value: pk.curveName
              +            });
              +            pk_fields.push({
              +                key: "Length",
              +                value: (((new BigInteger(pk.pubKeyHex, 16)).bitLength()-3) /2) + " bits"
              +            });
              +            pk_fields.push({
              +                key: "pub",
              +                value: PublicKey._format_byte_str(pk.pubKeyHex, 16, 18)
              +            });
              +        } else if (pk.type == "DSA") { // DSA
              +            pk_fields.push({
              +                key: "pub",
              +                value: PublicKey._format_byte_str(pk.y.toString(16), 16, 18)
              +            });
              +            pk_fields.push({
              +                key: "P",
              +                value: PublicKey._format_byte_str(pk.p.toString(16), 16, 18)
              +            });
              +            pk_fields.push({
              +                key: "Q",
              +                value: PublicKey._format_byte_str(pk.q.toString(16), 16, 18)
              +            });
              +            pk_fields.push({
              +                key: "G",
              +                value: PublicKey._format_byte_str(pk.g.toString(16), 16, 18)
              +            });
              +        } else if (pk.e) { // RSA
              +            pk_fields.push({
              +                key: "Length",
              +                value: pk.n.bitLength() + " bits"
              +            });
              +            pk_fields.push({
              +                key: "Modulus",
              +                value: PublicKey._format_byte_str(pk.n.toString(16), 16, 18)
              +            });
              +            pk_fields.push({
              +                key: "Exponent",
              +                value: pk.e + " (0x" + pk.e.toString(16) + ")"
              +            });
              +        } else {
              +            pk_fields.push({
              +                key: "Error",
              +                value: "Unknown Public Key type"
              +            });
              +        }
              +        
              +        // Signature fields
              +        if (ASN1HEX.dump(cert_sig).indexOf("SEQUENCE") === 0) { // DSA or ECDSA
              +            sig_str = "  r:              " + PublicKey._format_byte_str(ASN1HEX.getDecendantHexVByNthList(cert_sig, 0, [0]), 16, 18) + "\n" +
              +                "  s:              " + PublicKey._format_byte_str(ASN1HEX.getDecendantHexVByNthList(cert_sig, 0, [1]), 16, 18) + "\n";
              +        } else { // RSA
              +            sig_str = "  Signature:      " + PublicKey._format_byte_str(cert_sig, 16, 18) + "\n";
              +        }
              +        
              +        // Format Public Key fields
              +        for (var i = 0; i < pk_fields.length; i++) {
              +            pk_str += "  " + pk_fields[i].key + ":" +
              +                Utils.pad_left(
              +                    pk_fields[i].value + "\n",
              +                    18 - (pk_fields[i].key.length + 3) + pk_fields[i].value.length + 1,
              +                    " "
              +                );
              +        }
              +        
              +        var issuer_str = PublicKey._format_dn_str(issuer, 2),
              +            nb_date = PublicKey._format_date(not_before),
              +            na_date = PublicKey._format_date(not_after),
              +            subject_str = PublicKey._format_dn_str(subject, 2),
              +            cert_sig_str = PublicKey._format_byte_str(cert_sig, 16, 18);
              +        
              +        var output = "Version:          " + (parseInt(version, 16) + 1) + " (0x" + version + ")\n" +
              +            "Serial number:    " + new BigInteger(sn, 16).toString() + " (0x" + sn + ")\n" +
              +            "Algorithm ID:     " + algorithm + "\n" +
              +            "Validity\n" +
              +            "  Not Before:     " + nb_date + " (dd-mm-yy hh:mm:ss) (" + not_before + ")\n" +
              +            "  Not After:      " + na_date + " (dd-mm-yy hh:mm:ss) (" + not_after + ")\n" +
              +            "Issuer\n" +
              +            issuer_str +
              +            "Subject\n" +
              +            subject_str +
              +            "Public Key\n" +
              +            "  Algorithm:      " + pk_algorithm + "\n" +
              +            pk_str +
              +            "Certificate Signature\n" +
              +            "  Algorithm:      " + cert_sig_alg + "\n" +
              +            sig_str +
              +            "\nExtensions (parsed ASN.1)\n" +
              +            extensions;
              +        
              +        return output;
              +    },
              +
              +    
              +    /**
              +     * PEM to Hex operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_pem_to_hex: function(input, args) {
              +        if (input.indexOf("-----BEGIN") < 0) {
              +            // Add header so that the KEYUTIL function works
              +            input = "-----BEGIN CERTIFICATE-----" + input;
              +        }
              +        if (input.indexOf("-----END") < 0) {
              +            // Add footer so that the KEYUTIL function works
              +            input = input + "-----END CERTIFICATE-----";
              +        }
              +        return KEYUTIL.getHexFromPEM(input);
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    PEM_HEADER_STRING: "CERTIFICATE",
              +    
              +    /**
              +     * Hex to PEM operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_hex_to_pem: function(input, args) {
              +        return KJUR.asn1.ASN1Util.getPEMStringFromHex(input.replace(/\s/g, ""), args[0]);
              +    },
              +    
              +    
              +    /**
              +     * Hex to Object Identifier operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_hex_to_object_identifier: function(input, args) {
              +        return KJUR.asn1.ASN1Util.oidHexToInt(input.replace(/\s/g, ""));
              +    },
              +    
              +    
              +    /**
              +     * Object Identifier to Hex operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_object_identifier_to_hex: function(input, args) {
              +        return KJUR.asn1.ASN1Util.oidIntToHex(input);
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    ASN1_TRUNCATE_LENGTH: 32,
              +    
              +    /**
              +     * Parse ASN.1 hex string operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_parse_asn1_hex_string: function(input, args) {
              +        var truncate_len = args[1],
              +            index = args[0];
              +        return ASN1HEX.dump(input.replace(/\s/g, ""), {
              +            "ommit_long_octet": truncate_len
              +        }, index);
              +    },
              +    
              +    
              +    /**
              +     * Formats Distinguished Name (DN) strings.
              +     *
              +     * @private
              +     * @param {string} dn_str
              +     * @param {number} indent
              +     * @returns {string}
              +     */
              +    _format_dn_str: function(dn_str, indent) {
              +        var output = "",
              +            fields = dn_str.split(",/|"),
              +            max_key_len = 0,
              +            key,
              +            value,
              +            str;
              +        
              +        for (var i = 0; i < fields.length; i++) {
              +            if (!fields[i].length) continue;
              +            
              +            key = fields[i].split("=")[0];
              +                
              +            max_key_len = key.length > max_key_len ? key.length : max_key_len;
              +        }
              +        
              +        for (i = 0; i < fields.length; i++) {
              +            if (!fields[i].length) continue;
              +            
              +            key = fields[i].split("=")[0];
              +            value = fields[i].split("=")[1];
              +            str = Utils.pad_right(key, max_key_len) + " = " + value + "\n";
              +            
              +            output += Utils.pad_left(str, indent + str.length, " ");
              +        }
              +        
              +        return output;
              +    },
              +    
              +    
              +    /**
              +     * Formats byte strings by adding line breaks and delimiters.
              +     *
              +     * @private
              +     * @param {string} byte_str
              +     * @param {number} length - Line width
              +     * @param {number} indent
              +     * @returns {string}
              +     */
              +    _format_byte_str: function(byte_str, length, indent) {
              +        byte_str = Utils.to_hex(Utils.from_hex(byte_str), ":");
              +        length = length * 3;
              +        var output = "";
              +        
              +        for (var i = 0; i < byte_str.length; i += length) {
              +            var str = byte_str.slice(i, i + length) + "\n";
              +            if (i === 0) {
              +                output += str;
              +            } else {
              +                output += Utils.pad_left(str, indent + str.length, " ");
              +            }
              +        }
              +        
              +        return output.slice(0, output.length-1);
              +    },
              +    
              +    
              +    /**
              +     * Formats dates.
              +     *
              +     * @private
              +     * @param {string} date_str
              +     * @returns {string}
              +     */
              +    _format_date: function(date_str) {
              +        return date_str[4] + date_str[5] + "/" +
              +            date_str[2] + date_str[3] + "/" +
              +            date_str[0] + date_str[1] + " " +
              +            date_str[6] + date_str[7] + ":" +
              +            date_str[8] + date_str[9] + ":" +
              +            date_str[10] + date_str[11];
              +    },
              +    
              +};
              +
              +
              +/**
              + * Overwrite X509.hex2dn function so as to join RDNs with a string which can be split on without
              + * causing problems later (I hope).
              + *
              + * @param {string} hDN - Hex DN string
              + * @returns {string}
              + */
              +X509.hex2dn = function(hDN) {
              +    var s = "";
              +    var a = ASN1HEX.getPosArrayOfChildren_AtObj(hDN, 0);
              +    for (var i = 0; i < a.length; i++) {
              +        var hRDN = ASN1HEX.getHexOfTLV_AtObj(hDN, a[i]);
              +        s = s + ",/|" + X509.hex2rdn(hRDN);
              +    }
              +    return s;
              +};
              +
              +
              +/**
              + * Overwrite DN attribute lookup in jsrasign library with a much more complete version from
              + * https://github.com/nfephp-org/nfephp/blob/master/libs/Common/Certificate/Oids.php
              + *
              + * Various duplicates commented out.
              + *
              + * @constant
              + */
              +X509.DN_ATTRHEX = {
              +    '0603550403' : 'commonName',
              +    '0603550404' : 'surname',
              +    '0603550406' : 'countryName',
              +    '0603550407' : 'localityName',
              +    '0603550408' : 'stateOrProvinceName',
              +    '0603550409' : 'streetAddress',
              +    '060355040a' : 'organizationName',
              +    '060355040b' : 'organizationalUnitName',
              +    '060355040c' : 'title',
              +    '0603550414' : 'telephoneNumber',
              +    '060355042a' : 'givenName',
              +    // '0603551d0e' : 'id-ce-subjectKeyIdentifier',
              +    // '0603551d0f' : 'id-ce-keyUsage',
              +    // '0603551d11' : 'id-ce-subjectAltName',
              +    // '0603551d13' : 'id-ce-basicConstraints',
              +    // '0603551d14' : 'id-ce-cRLNumber',
              +    // '0603551d1f' : 'id-ce-CRLDistributionPoints',
              +    // '0603551d20' : 'id-ce-certificatePolicies',
              +    // '0603551d23' : 'id-ce-authorityKeyIdentifier',
              +    // '0603551d25' : 'id-ce-extKeyUsage',
              +    // '06032a864886f70d010901' : 'Email',
              +    // '06032a864886f70d010101' : 'RSAEncryption',
              +    // '06032a864886f70d010102' : 'md2WithRSAEncryption',
              +    // '06032a864886f70d010104' : 'md5withRSAEncryption',
              +    // '06032a864886f70d010105' : 'SHA-1WithRSAEncryption',
              +    // '06032a8648ce380403' : 'id-dsa-with-sha-1',
              +    // '06032b06010505070302' : 'id_kp_clientAuth',
              +    // '06032b06010505070304' : 'id_kp_securityemail',
              +    '06032b06010505070201' : 'id_certificatePolicies',
              +    '06036086480186f8420101' : 'netscape-cert-type',
              +    '06036086480186f8420102' : 'netscape-base-url',
              +    '06036086480186f8420103' : 'netscape-revocation-url',
              +    '06036086480186f8420104' : 'netscape-ca-revocation-url',
              +    '06036086480186f8420107' : 'netscape-cert-renewal-url',
              +    '06036086480186f8420108' : 'netscape-ca-policy-url',
              +    '06036086480186f842010c' : 'netscape-ssl-server-name',
              +    '06036086480186f842010d' : 'netscape-comment',
              +    '0603604c010201' : 'A1',
              +    '0603604c010203' : 'A3',
              +    '0603604c01020110' : 'Certification Practice Statement pointer',
              +    '0603604c010301' : 'Dados do cert parte 1',
              +    '0603604c010305' : 'Dados do cert parte 2',
              +    '0603604c010306' : 'Dados do cert parte 3',
              +    '06030992268993f22c640119' : 'domainComponent',
              +    '06032a24a0f2a07d01010a' : 'Signet pilot',
              +    '06032a24a0f2a07d01010b' : 'Signet intraNet',
              +    '06032a24a0f2a07d010102' : 'Signet personal',
              +    '06032a24a0f2a07d010114' : 'Signet securityPolicy',
              +    '06032a24a0f2a07d010103' : 'Signet business',
              +    '06032a24a0f2a07d010104' : 'Signet legal',
              +    '06032a24a497a35301640101' : 'Certificates Australia policyIdentifier',
              +    '06032a85702201' : 'seis-cp',
              +    '06032a8570220101' : 'SEIS certificatePolicy-s10',
              +    '06032a85702202' : 'SEIS pe',
              +    '06032a85702203' : 'SEIS at',
              +    '06032a8570220301' : 'SEIS at-personalIdentifier',
              +    '06032a8648ce380201' : 'holdinstruction-none',
              +    '06032a8648ce380202' : 'holdinstruction-callissuer',
              +    '06032a8648ce380203' : 'holdinstruction-reject',
              +    '06032a8648ce380401' : 'dsa',
              +    '06032a8648ce380403' : 'dsaWithSha1',
              +    '06032a8648ce3d01' : 'fieldType',
              +    '06032a8648ce3d0101' : 'prime-field',
              +    '06032a8648ce3d0102' : 'characteristic-two-field',
              +    '06032a8648ce3d010201' : 'ecPublicKey',
              +    '06032a8648ce3d010203' : 'characteristic-two-basis',
              +    '06032a8648ce3d01020301' : 'onBasis',
              +    '06032a8648ce3d01020302' : 'tpBasis',
              +    '06032a8648ce3d01020303' : 'ppBasis',
              +    '06032a8648ce3d02' : 'publicKeyType',
              +    '06032a8648ce3d0201' : 'ecPublicKey',
              +    '06032a8648ce3e0201' : 'dhPublicNumber',
              +    '06032a864886f67d07' : 'nsn',
              +    '06032a864886f67d0741' : 'nsn-ce',
              +    '06032a864886f67d074100' : 'entrustVersInfo',
              +    '06032a864886f67d0742' : 'nsn-alg',
              +    '06032a864886f67d07420a' : 'cast5CBC',
              +    '06032a864886f67d07420b' : 'cast5MAC',
              +    '06032a864886f67d07420c' : 'pbeWithMD5AndCAST5-CBC',
              +    '06032a864886f67d07420d' : 'passwordBasedMac',
              +    '06032a864886f67d074203' : 'cast3CBC',
              +    '06032a864886f67d0743' : 'nsn-oc',
              +    '06032a864886f67d074300' : 'entrustUser',
              +    '06032a864886f67d0744' : 'nsn-at',
              +    '06032a864886f67d074400' : 'entrustCAInfo',
              +    '06032a864886f67d07440a' : 'attributeCertificate',
              +    '06032a864886f70d0101' : 'pkcs-1',
              +    '06032a864886f70d010101' : 'rsaEncryption',
              +    '06032a864886f70d010102' : 'md2withRSAEncryption',
              +    '06032a864886f70d010103' : 'md4withRSAEncryption',
              +    '06032a864886f70d010104' : 'md5withRSAEncryption',
              +    '06032a864886f70d010105' : 'sha1withRSAEncryption',
              +    '06032a864886f70d010106' : 'rsaOAEPEncryptionSET',
              +    '06032a864886f70d010910020b' : 'SMIMEEncryptionKeyPreference',
              +    '06032a864886f70d010c' : 'pkcs-12',
              +    '06032a864886f70d010c01' : 'pkcs-12-PbeIds',
              +    '06032a864886f70d010c0101' : 'pbeWithSHAAnd128BitRC4',
              +    '06032a864886f70d010c0102' : 'pbeWithSHAAnd40BitRC4',
              +    '06032a864886f70d010c0103' : 'pbeWithSHAAnd3-KeyTripleDES-CBC',
              +    '06032a864886f70d010c0104' : 'pbeWithSHAAnd2-KeyTripleDES-CBC',
              +    '06032a864886f70d010c0105' : 'pbeWithSHAAnd128BitRC2-CBC',
              +    '06032a864886f70d010c0106' : 'pbeWithSHAAnd40BitRC2-CBC',
              +    '06032a864886f70d010c0a' : 'pkcs-12Version1',
              +    '06032a864886f70d010c0a01' : 'pkcs-12BadIds',
              +    '06032a864886f70d010c0a0101' : 'pkcs-12-keyBag',
              +    '06032a864886f70d010c0a0102' : 'pkcs-12-pkcs-8ShroudedKeyBag',
              +    '06032a864886f70d010c0a0103' : 'pkcs-12-certBag',
              +    '06032a864886f70d010c0a0104' : 'pkcs-12-crlBag',
              +    '06032a864886f70d010c0a0105' : 'pkcs-12-secretBag',
              +    '06032a864886f70d010c0a0106' : 'pkcs-12-safeContentsBag',
              +    '06032a864886f70d010c02' : 'pkcs-12-ESPVKID',
              +    '06032a864886f70d010c0201' : 'pkcs-12-PKCS8KeyShrouding',
              +    '06032a864886f70d010c03' : 'pkcs-12-BagIds',
              +    '06032a864886f70d010c0301' : 'pkcs-12-keyBagId',
              +    '06032a864886f70d010c0302' : 'pkcs-12-certAndCRLBagId',
              +    '06032a864886f70d010c0303' : 'pkcs-12-secretBagId',
              +    '06032a864886f70d010c0304' : 'pkcs-12-safeContentsId',
              +    '06032a864886f70d010c0305' : 'pkcs-12-pkcs-8ShroudedKeyBagId',
              +    '06032a864886f70d010c04' : 'pkcs-12-CertBagID',
              +    '06032a864886f70d010c0401' : 'pkcs-12-X509CertCRLBagID',
              +    '06032a864886f70d010c0402' : 'pkcs-12-SDSICertBagID',
              +    '06032a864886f70d010c05' : 'pkcs-12-OID',
              +    '06032a864886f70d010c0501' : 'pkcs-12-PBEID',
              +    '06032a864886f70d010c050101' : 'pkcs-12-PBEWithSha1And128BitRC4',
              +    '06032a864886f70d010c050102' : 'pkcs-12-PBEWithSha1And40BitRC4',
              +    '06032a864886f70d010c050103' : 'pkcs-12-PBEWithSha1AndTripleDESCBC',
              +    '06032a864886f70d010c050104' : 'pkcs-12-PBEWithSha1And128BitRC2CBC',
              +    '06032a864886f70d010c050105' : 'pkcs-12-PBEWithSha1And40BitRC2CBC',
              +    '06032a864886f70d010c050106' : 'pkcs-12-PBEWithSha1AndRC4',
              +    '06032a864886f70d010c050107' : 'pkcs-12-PBEWithSha1AndRC2CBC',
              +    '06032a864886f70d010c0502' : 'pkcs-12-EnvelopingID',
              +    '06032a864886f70d010c050201' : 'pkcs-12-RSAEncryptionWith128BitRC4',
              +    '06032a864886f70d010c050202' : 'pkcs-12-RSAEncryptionWith40BitRC4',
              +    '06032a864886f70d010c050203' : 'pkcs-12-RSAEncryptionWithTripleDES',
              +    '06032a864886f70d010c0503' : 'pkcs-12-SignatureID',
              +    '06032a864886f70d010c050301' : 'pkcs-12-RSASignatureWithSHA1Digest',
              +    '06032a864886f70d0103' : 'pkcs-3',
              +    '06032a864886f70d010301' : 'dhKeyAgreement',
              +    '06032a864886f70d0105' : 'pkcs-5',
              +    '06032a864886f70d010501' : 'pbeWithMD2AndDES-CBC',
              +    '06032a864886f70d01050a' : 'pbeWithSHAAndDES-CBC',
              +    '06032a864886f70d010503' : 'pbeWithMD5AndDES-CBC',
              +    '06032a864886f70d010504' : 'pbeWithMD2AndRC2-CBC',
              +    '06032a864886f70d010506' : 'pbeWithMD5AndRC2-CBC',
              +    '06032a864886f70d010509' : 'pbeWithMD5AndXOR',
              +    '06032a864886f70d0107' : 'pkcs-7',
              +    '06032a864886f70d010701' : 'data',
              +    '06032a864886f70d010702' : 'signedData',
              +    '06032a864886f70d010703' : 'envelopedData',
              +    '06032a864886f70d010704' : 'signedAndEnvelopedData',
              +    '06032a864886f70d010705' : 'digestData',
              +    '06032a864886f70d010706' : 'encryptedData',
              +    '06032a864886f70d010707' : 'dataWithAttributes',
              +    '06032a864886f70d010708' : 'encryptedPrivateKeyInfo',
              +    '06032a864886f70d0109' : 'pkcs-9',
              +    '06032a864886f70d010901' : 'emailAddress',
              +    '06032a864886f70d01090a' : 'issuerAndSerialNumber',
              +    '06032a864886f70d01090b' : 'passwordCheck',
              +    '06032a864886f70d01090c' : 'publicKey',
              +    '06032a864886f70d01090d' : 'signingDescription',
              +    '06032a864886f70d01090e' : 'extensionReq',
              +    '06032a864886f70d01090f' : 'sMIMECapabilities',
              +    '06032a864886f70d01090f01' : 'preferSignedData',
              +    '06032a864886f70d01090f02' : 'canNotDecryptAny',
              +    '06032a864886f70d01090f03' : 'receiptRequest',
              +    '06032a864886f70d01090f04' : 'receipt',
              +    '06032a864886f70d01090f05' : 'contentHints',
              +    '06032a864886f70d01090f06' : 'mlExpansionHistory',
              +    '06032a864886f70d010910' : 'id-sMIME',
              +    '06032a864886f70d01091000' : 'id-mod',
              +    '06032a864886f70d0109100001' : 'id-mod-cms',
              +    '06032a864886f70d0109100002' : 'id-mod-ess',
              +    '06032a864886f70d01091001' : 'id-ct',
              +    '06032a864886f70d0109100101' : 'id-ct-receipt',
              +    '06032a864886f70d01091002' : 'id-aa',
              +    '06032a864886f70d0109100201' : 'id-aa-receiptRequest',
              +    '06032a864886f70d0109100202' : 'id-aa-securityLabel',
              +    '06032a864886f70d0109100203' : 'id-aa-mlExpandHistory',
              +    '06032a864886f70d0109100204' : 'id-aa-contentHint',
              +    '06032a864886f70d010902' : 'unstructuredName',
              +    '06032a864886f70d010914' : 'friendlyName',
              +    '06032a864886f70d010915' : 'localKeyID',
              +    '06032a864886f70d010916' : 'certTypes',
              +    '06032a864886f70d01091601' : 'x509Certificate',
              +    '06032a864886f70d01091602' : 'sdsiCertificate',
              +    '06032a864886f70d010917' : 'crlTypes',
              +    '06032a864886f70d01091701' : 'x509Crl',
              +    '06032a864886f70d010903' : 'contentType',
              +    '06032a864886f70d010904' : 'messageDigest',
              +    '06032a864886f70d010905' : 'signingTime',
              +    '06032a864886f70d010906' : 'countersignature',
              +    '06032a864886f70d010907' : 'challengePassword',
              +    '06032a864886f70d010908' : 'unstructuredAddress',
              +    '06032a864886f70d010909' : 'extendedCertificateAttributes',
              +    '06032a864886f70d02' : 'digestAlgorithm',
              +    '06032a864886f70d0202' : 'md2',
              +    '06032a864886f70d0204' : 'md4',
              +    '06032a864886f70d0205' : 'md5',
              +    '06032a864886f70d03' : 'encryptionAlgorithm',
              +    '06032a864886f70d030a' : 'desCDMF',
              +    '06032a864886f70d0302' : 'rc2CBC',
              +    '06032a864886f70d0303' : 'rc2ECB',
              +    '06032a864886f70d0304' : 'rc4',
              +    '06032a864886f70d0305' : 'rc4WithMAC',
              +    '06032a864886f70d0306' : 'DESX-CBC',
              +    '06032a864886f70d0307' : 'DES-EDE3-CBC',
              +    '06032a864886f70d0308' : 'RC5CBC',
              +    '06032a864886f70d0309' : 'RC5-CBCPad',
              +    '06032a864886f7140403' : 'microsoftExcel',
              +    '06032a864886f7140404' : 'titledWithOID',
              +    '06032a864886f7140405' : 'microsoftPowerPoint',
              +    '06032b81051086480954' : 'x9-84',
              +    '06032b8105108648095400' : 'x9-84-Module',
              +    '06032b810510864809540001' : 'x9-84-Biometrics',
              +    '06032b810510864809540002' : 'x9-84-CMS',
              +    '06032b810510864809540003' : 'x9-84-Identifiers',
              +    '06032b8105108648095401' : 'biometric',
              +    '06032b810510864809540100' : 'id-unknown-Type',
              +    '06032b810510864809540101' : 'id-body-Odor',
              +    '06032b81051086480954010a' : 'id-palm',
              +    '06032b81051086480954010b' : 'id-retina',
              +    '06032b81051086480954010c' : 'id-signature',
              +    '06032b81051086480954010d' : 'id-speech-Pattern',
              +    '06032b81051086480954010e' : 'id-thermal-Image',
              +    '06032b81051086480954010f' : 'id-vein-Pattern',
              +    '06032b810510864809540110' : 'id-thermal-Face-Image',
              +    '06032b810510864809540111' : 'id-thermal-Hand-Image',
              +    '06032b810510864809540112' : 'id-lip-Movement',
              +    '06032b810510864809540113' : 'id-gait',
              +    '06032b810510864809540102' : 'id-dna',
              +    '06032b810510864809540103' : 'id-ear-Shape',
              +    '06032b810510864809540104' : 'id-facial-Features',
              +    '06032b810510864809540105' : 'id-finger-Image',
              +    '06032b810510864809540106' : 'id-finger-Geometry',
              +    '06032b810510864809540107' : 'id-hand-Geometry',
              +    '06032b810510864809540108' : 'id-iris-Features',
              +    '06032b810510864809540109' : 'id-keystroke-Dynamics',
              +    '06032b8105108648095402' : 'processing-algorithm',
              +    '06032b8105108648095403' : 'matching-method',
              +    '06032b8105108648095404' : 'format-Owner',
              +    '06032b810510864809540400' : 'cbeff-Owner',
              +    '06032b810510864809540401' : 'ibia-Owner',
              +    '06032b81051086480954040101' : 'id-ibia-SAFLINK',
              +    '06032b8105108648095404010a' : 'id-ibia-SecuGen',
              +    '06032b8105108648095404010b' : 'id-ibia-PreciseBiometric',
              +    '06032b8105108648095404010c' : 'id-ibia-Identix',
              +    '06032b8105108648095404010d' : 'id-ibia-DERMALOG',
              +    '06032b8105108648095404010e' : 'id-ibia-LOGICO',
              +    '06032b8105108648095404010f' : 'id-ibia-NIST',
              +    '06032b81051086480954040110' : 'id-ibia-A3Vision',
              +    '06032b81051086480954040111' : 'id-ibia-NEC',
              +    '06032b81051086480954040112' : 'id-ibia-STMicroelectronics',
              +    '06032b81051086480954040102' : 'id-ibia-Bioscrypt',
              +    '06032b81051086480954040103' : 'id-ibia-Visionics',
              +    '06032b81051086480954040104' : 'id-ibia-InfineonTechnologiesAG',
              +    '06032b81051086480954040105' : 'id-ibia-IridianTechnologies',
              +    '06032b81051086480954040106' : 'id-ibia-Veridicom',
              +    '06032b81051086480954040107' : 'id-ibia-CyberSIGN',
              +    '06032b81051086480954040108' : 'id-ibia-eCryp.',
              +    '06032b81051086480954040109' : 'id-ibia-FingerprintCardsAB',
              +    '06032b810510864809540402' : 'x9-Owner',
              +    '06032b0e021a05' : 'sha',
              +    '06032b0e03020101' : 'rsa',
              +    '06032b0e03020a' : 'desMAC',
              +    '06032b0e03020b' : 'rsaSignature',
              +    '06032b0e03020c' : 'dsa',
              +    '06032b0e03020d' : 'dsaWithSHA',
              +    '06032b0e03020e' : 'mdc2WithRSASignature',
              +    '06032b0e03020f' : 'shaWithRSASignature',
              +    '06032b0e030210' : 'dhWithCommonModulus',
              +    '06032b0e030211' : 'desEDE',
              +    '06032b0e030212' : 'sha',
              +    '06032b0e030213' : 'mdc-2',
              +    '06032b0e030202' : 'md4WitRSA',
              +    '06032b0e03020201' : 'sqmod-N',
              +    '06032b0e030214' : 'dsaCommon',
              +    '06032b0e030215' : 'dsaCommonWithSHA',
              +    '06032b0e030216' : 'rsaKeyTransport',
              +    '06032b0e030217' : 'keyed-hash-seal',
              +    '06032b0e030218' : 'md2WithRSASignature',
              +    '06032b0e030219' : 'md5WithRSASignature',
              +    '06032b0e03021a' : 'sha1',
              +    '06032b0e03021b' : 'dsaWithSHA1',
              +    '06032b0e03021c' : 'dsaWithCommonSHA1',
              +    '06032b0e03021d' : 'sha-1WithRSAEncryption',
              +    '06032b0e030203' : 'md5WithRSA',
              +    '06032b0e03020301' : 'sqmod-NwithRSA',
              +    '06032b0e030204' : 'md4WithRSAEncryption',
              +    '06032b0e030206' : 'desECB',
              +    '06032b0e030207' : 'desCBC',
              +    '06032b0e030208' : 'desOFB',
              +    '06032b0e030209' : 'desCFB',
              +    '06032b0e030301' : 'simple-strong-auth-mechanism',
              +    '06032b0e07020101' : 'ElGamal',
              +    '06032b0e07020301' : 'md2WithRSA',
              +    '06032b0e07020302' : 'md2WithElGamal',
              +    '06032b2403' : 'algorithm',
              +    '06032b240301' : 'encryptionAlgorithm',
              +    '06032b24030101' : 'des',
              +    '06032b240301010101' : 'desECBPad',
              +    '06032b24030101010101' : 'desECBPadISO',
              +    '06032b240301010201' : 'desCBCPad',
              +    '06032b24030101020101' : 'desCBCPadISO',
              +    '06032b24030102' : 'idea',
              +    '06032b2403010201' : 'ideaECB',
              +    '06032b240301020101' : 'ideaECBPad',
              +    '06032b24030102010101' : 'ideaECBPadISO',
              +    '06032b2403010202' : 'ideaCBC',
              +    '06032b240301020201' : 'ideaCBCPad',
              +    '06032b24030102020101' : 'ideaCBCPadISO',
              +    '06032b2403010203' : 'ideaOFB',
              +    '06032b2403010204' : 'ideaCFB',
              +    '06032b24030103' : 'des-3',
              +    '06032b240301030101' : 'des-3ECBPad',
              +    '06032b24030103010101' : 'des-3ECBPadISO',
              +    '06032b240301030201' : 'des-3CBCPad',
              +    '06032b24030103020101' : 'des-3CBCPadISO',
              +    '06032b240302' : 'hashAlgorithm',
              +    '06032b24030201' : 'ripemd160',
              +    '06032b24030202' : 'ripemd128',
              +    '06032b24030203' : 'ripemd256',
              +    '06032b24030204' : 'mdc2singleLength',
              +    '06032b24030205' : 'mdc2doubleLength',
              +    '06032b240303' : 'signatureAlgorithm',
              +    '06032b24030301' : 'rsa',
              +    '06032b2403030101' : 'rsaMitSHA-1',
              +    '06032b2403030102' : 'rsaMitRIPEMD160',
              +    '06032b24030302' : 'ellipticCurve',
              +    '06032b240304' : 'signatureScheme',
              +    '06032b24030401' : 'iso9796-1',
              +    '06032b2403040201' : 'iso9796-2',
              +    '06032b2403040202' : 'iso9796-2rsa',
              +    '06032b2404' : 'attribute',
              +    '06032b2405' : 'policy',
              +    '06032b2406' : 'api',
              +    '06032b240601' : 'manufacturerSpecific',
              +    '06032b240602' : 'functionalitySpecific',
              +    '06032b2407' : 'api',
              +    '06032b240701' : 'keyAgreement',
              +    '06032b240702' : 'keyTransport',
              +    '06032b06010401927c0a0101' : 'UNINETT policyIdentifier',
              +    '06032b0601040195180a' : 'ICE-TEL policyIdentifier',
              +    '06032b0601040197552001' : 'cryptlibEnvelope',
              +    '06032b0601040197552002' : 'cryptlibPrivateKey',
              +    '060a2b060104018237' : 'Microsoft OID',
              +    '060a2b0601040182370a' : 'Crypto 2.0',
              +    '060a2b0601040182370a01' : 'certTrustList',
              +    '060a2b0601040182370a0101' : 'szOID_SORTED_CTL',
              +    '060a2b0601040182370a0a' : 'Microsoft CMC OIDs',
              +    '060a2b0601040182370a0a01' : 'szOID_CMC_ADD_ATTRIBUTES',
              +    '060a2b0601040182370a0b' : 'Microsoft certificate property OIDs',
              +    '060a2b0601040182370a0b01' : 'szOID_CERT_PROP_ID_PREFIX',
              +    '060a2b0601040182370a0c' : 'CryptUI',
              +    '060a2b0601040182370a0c01' : 'szOID_ANY_APPLICATION_POLICY',
              +    '060a2b0601040182370a02' : 'nextUpdateLocation',
              +    '060a2b0601040182370a0301' : 'certTrustListSigning',
              +    '060a2b0601040182370a030a' : 'szOID_KP_QUALIFIED_SUBORDINATION',
              +    '060a2b0601040182370a030b' : 'szOID_KP_KEY_RECOVERY',
              +    '060a2b0601040182370a030c' : 'szOID_KP_DOCUMENT_SIGNING',
              +    '060a2b0601040182370a0302' : 'timeStampSigning',
              +    '060a2b0601040182370a0303' : 'serverGatedCrypto',
              +    '060a2b0601040182370a030301' : 'szOID_SERIALIZED',
              +    '060a2b0601040182370a0304' : 'encryptedFileSystem',
              +    '060a2b0601040182370a030401' : 'szOID_EFS_RECOVERY',
              +    '060a2b0601040182370a0305' : 'szOID_WHQL_CRYPTO',
              +    '060a2b0601040182370a0306' : 'szOID_NT5_CRYPTO',
              +    '060a2b0601040182370a0307' : 'szOID_OEM_WHQL_CRYPTO',
              +    '060a2b0601040182370a0308' : 'szOID_EMBEDDED_NT_CRYPTO',
              +    '060a2b0601040182370a0309' : 'szOID_ROOT_LIST_SIGNER',
              +    '060a2b0601040182370a0401' : 'yesnoTrustAttr',
              +    '060a2b0601040182370a0501' : 'szOID_DRM',
              +    '060a2b0601040182370a0502' : 'szOID_DRM_INDIVIDUALIZATION',
              +    '060a2b0601040182370a0601' : 'szOID_LICENSES',
              +    '060a2b0601040182370a0602' : 'szOID_LICENSE_SERVER',
              +    '060a2b0601040182370a07' : 'szOID_MICROSOFT_RDN_PREFIX',
              +    '060a2b0601040182370a0701' : 'szOID_KEYID_RDN',
              +    '060a2b0601040182370a0801' : 'szOID_REMOVE_CERTIFICATE',
              +    '060a2b0601040182370a0901' : 'szOID_CROSS_CERT_DIST_POINTS',
              +    '060a2b0601040182370c' : 'Catalog',
              +    '060a2b0601040182370c0101' : 'szOID_CATALOG_LIST',
              +    '060a2b0601040182370c0102' : 'szOID_CATALOG_LIST_MEMBER',
              +    '060a2b0601040182370c0201' : 'CAT_NAMEVALUE_OBJID',
              +    '060a2b0601040182370c0202' : 'CAT_MEMBERINFO_OBJID',
              +    '060a2b0601040182370d' : 'Microsoft PKCS10 OIDs',
              +    '060a2b0601040182370d01' : 'szOID_RENEWAL_CERTIFICATE',
              +    '060a2b0601040182370d0201' : 'szOID_ENROLLMENT_NAME_VALUE_PAIR',
              +    '060a2b0601040182370d0202' : 'szOID_ENROLLMENT_CSP_PROVIDER',
              +    '060a2b0601040182370d0203' : 'OS Version',
              +    '060a2b0601040182370f' : 'Microsoft Java',
              +    '060a2b06010401823710' : 'Microsoft Outlook/Exchange',
              +    '060a2b0601040182371004' : 'Outlook Express',
              +    '060a2b06010401823711' : 'Microsoft PKCS12 attributes',
              +    '060a2b0601040182371101' : 'szOID_LOCAL_MACHINE_KEYSET',
              +    '060a2b06010401823712' : 'Microsoft Hydra',
              +    '060a2b06010401823713' : 'Microsoft ISPU Test',
              +    '060a2b06010401823702' : 'Authenticode',
              +    '060a2b06010401823702010a' : 'spcAgencyInfo',
              +    '060a2b06010401823702010b' : 'spcStatementType',
              +    '060a2b06010401823702010c' : 'spcSpOpusInfo',
              +    '060a2b06010401823702010e' : 'certExtensions',
              +    '060a2b06010401823702010f' : 'spcPelmageData',
              +    '060a2b060104018237020112' : 'SPC_RAW_FILE_DATA_OBJID',
              +    '060a2b060104018237020113' : 'SPC_STRUCTURED_STORAGE_DATA_OBJID',
              +    '060a2b060104018237020114' : 'spcLink',
              +    '060a2b060104018237020115' : 'individualCodeSigning',
              +    '060a2b060104018237020116' : 'commercialCodeSigning',
              +    '060a2b060104018237020119' : 'spcLink',
              +    '060a2b06010401823702011a' : 'spcMinimalCriteriaInfo',
              +    '060a2b06010401823702011b' : 'spcFinancialCriteriaInfo',
              +    '060a2b06010401823702011c' : 'spcLink',
              +    '060a2b06010401823702011d' : 'SPC_HASH_INFO_OBJID',
              +    '060a2b06010401823702011e' : 'SPC_SIPINFO_OBJID',
              +    '060a2b060104018237020104' : 'spcIndirectDataContext',
              +    '060a2b0601040182370202' : 'CTL for Software Publishers Trusted CAs',
              +    '060a2b060104018237020201' : 'szOID_TRUSTED_CODESIGNING_CA_LIST',
              +    '060a2b060104018237020202' : 'szOID_TRUSTED_CLIENT_AUTH_CA_LIST',
              +    '060a2b060104018237020203' : 'szOID_TRUSTED_SERVER_AUTH_CA_LIST',
              +    '060a2b06010401823714' : 'Microsoft Enrollment Infrastructure',
              +    '060a2b0601040182371401' : 'szOID_AUTO_ENROLL_CTL_USAGE',
              +    '060a2b0601040182371402' : 'szOID_ENROLL_CERTTYPE_EXTENSION',
              +    '060a2b060104018237140201' : 'szOID_ENROLLMENT_AGENT',
              +    '060a2b060104018237140202' : 'szOID_KP_SMARTCARD_LOGON',
              +    '060a2b060104018237140203' : 'szOID_NT_PRINCIPAL_NAME',
              +    '060a2b0601040182371403' : 'szOID_CERT_MANIFOLD',
              +    '06092b06010401823715' : 'Microsoft CertSrv Infrastructure',
              +    '06092b0601040182371501' : 'szOID_CERTSRV_CA_VERSION',
              +    '06092b0601040182371514' : 'Client Information',
              +    '060a2b06010401823719' : 'Microsoft Directory Service',
              +    '060a2b0601040182371901' : 'szOID_NTDS_REPLICATION',
              +    '060a2b06010401823703' : 'Time Stamping',
              +    '060a2b060104018237030201' : 'SPC_TIME_STAMP_REQUEST_OBJID',
              +    '060a2b0601040182371e' : 'IIS',
              +    '060a2b0601040182371f' : 'Windows updates and service packs',
              +    '060a2b0601040182371f01' : 'szOID_PRODUCT_UPDATE',
              +    '060a2b06010401823704' : 'Permissions',
              +    '060a2b06010401823728' : 'Fonts',
              +    '060a2b06010401823729' : 'Microsoft Licensing and Registration',
              +    '060a2b0601040182372a' : 'Microsoft Corporate PKI (ITG)',
              +    '060a2b06010401823758' : 'CAPICOM',
              +    '060a2b0601040182375801' : 'szOID_CAPICOM_VERSION',
              +    '060a2b0601040182375802' : 'szOID_CAPICOM_ATTRIBUTE',
              +    '060a2b060104018237580201' : 'szOID_CAPICOM_DOCUMENT_NAME',
              +    '060a2b060104018237580202' : 'szOID_CAPICOM_DOCUMENT_DESCRIPTION',
              +    '060a2b0601040182375803' : 'szOID_CAPICOM_ENCRYPTED_DATA',
              +    '060a2b060104018237580301' : 'szOID_CAPICOM_ENCRYPTED_CONTENT',
              +    '06032b0601050507' : 'pkix',
              +    '06032b060105050701' : 'privateExtension',
              +    '06032b06010505070101' : 'authorityInfoAccess',
              +    '06032b06010505070c02' : 'CMC Data',
              +    '06032b060105050702' : 'policyQualifierIds',
              +    // '06032b06010505070201' : 'cps',
              +    '06032b06010505070202' : 'unotice',
              +    '06032b060105050703' : 'keyPurpose',
              +    '06032b06010505070301' : 'serverAuth',
              +    '06032b06010505070302' : 'clientAuth',
              +    '06032b06010505070303' : 'codeSigning',
              +    '06032b06010505070304' : 'emailProtection',
              +    '06032b06010505070305' : 'ipsecEndSystem',
              +    '06032b06010505070306' : 'ipsecTunnel',
              +    '06032b06010505070307' : 'ipsecUser',
              +    '06032b06010505070308' : 'timeStamping',
              +    '06032b060105050704' : 'cmpInformationTypes',
              +    '06032b06010505070401' : 'caProtEncCert',
              +    '06032b06010505070402' : 'signKeyPairTypes',
              +    '06032b06010505070403' : 'encKeyPairTypes',
              +    '06032b06010505070404' : 'preferredSymmAlg',
              +    '06032b06010505070405' : 'caKeyUpdateInfo',
              +    '06032b06010505070406' : 'currentCRL',
              +    '06032b06010505073001' : 'ocsp',
              +    '06032b06010505073002' : 'caIssuers',
              +    '06032b06010505080101' : 'HMAC-MD5',
              +    '06032b06010505080102' : 'HMAC-SHA',
              +    '060360864801650201010a' : 'mosaicKeyManagementAlgorithm',
              +    '060360864801650201010b' : 'sdnsKMandSigAlgorithm',
              +    '060360864801650201010c' : 'mosaicKMandSigAlgorithm',
              +    '060360864801650201010d' : 'SuiteASignatureAlgorithm',
              +    '060360864801650201010e' : 'SuiteAConfidentialityAlgorithm',
              +    '060360864801650201010f' : 'SuiteAIntegrityAlgorithm',
              +    '06036086480186f84201' : 'cert-extension',
              +    // '06036086480186f8420101' : 'netscape-cert-type',
              +    '06036086480186f842010a' : 'EntityLogo',
              +    '06036086480186f842010b' : 'UserPicture',
              +    // '06036086480186f842010c' : 'netscape-ssl-server-name',
              +    // '06036086480186f842010d' : 'netscape-comment',
              +    // '06036086480186f8420102' : 'netscape-base-url',
              +    // '06036086480186f8420103' : 'netscape-revocation-url',
              +    // '06036086480186f8420104' : 'netscape-ca-revocation-url',
              +    // '06036086480186f8420107' : 'netscape-cert-renewal-url',
              +    // '06036086480186f8420108' : 'netscape-ca-policy-url',
              +    '06036086480186f8420109' : 'HomePage-url',
              +    '06036086480186f84202' : 'data-type',
              +    '06036086480186f8420201' : 'GIF',
              +    '06036086480186f8420202' : 'JPEG',
              +    '06036086480186f8420203' : 'URL',
              +    '06036086480186f8420204' : 'HTML',
              +    '06036086480186f8420205' : 'netscape-cert-sequence',
              +    '06036086480186f8420206' : 'netscape-cert-url',
              +    '06036086480186f84203' : 'directory',
              +    '06036086480186f8420401' : 'serverGatedCrypto',
              +    '06036086480186f845010603' : 'Unknown Verisign extension',
              +    '06036086480186f845010606' : 'Unknown Verisign extension',
              +    '06036086480186f84501070101' : 'Verisign certificatePolicy',
              +    '06036086480186f8450107010101' : 'Unknown Verisign policy qualifier',
              +    '06036086480186f8450107010102' : 'Unknown Verisign policy qualifier',
              +    '0603678105' : 'TCPA',
              +    '060367810501' : 'tcpa_specVersion',
              +    '060367810502' : 'tcpa_attribute',
              +    '06036781050201' : 'tcpa_at_tpmManufacturer',
              +    '0603678105020a' : 'tcpa_at_securityQualities',
              +    '0603678105020b' : 'tcpa_at_tpmProtectionProfile',
              +    '0603678105020c' : 'tcpa_at_tpmSecurityTarget',
              +    '0603678105020d' : 'tcpa_at_foundationProtectionProfile',
              +    '0603678105020e' : 'tcpa_at_foundationSecurityTarget',
              +    '0603678105020f' : 'tcpa_at_tpmIdLabel',
              +    '06036781050202' : 'tcpa_at_tpmModel',
              +    '06036781050203' : 'tcpa_at_tpmVersion',
              +    '06036781050204' : 'tcpa_at_platformManufacturer',
              +    '06036781050205' : 'tcpa_at_platformModel',
              +    '06036781050206' : 'tcpa_at_platformVersion',
              +    '06036781050207' : 'tcpa_at_componentManufacturer',
              +    '06036781050208' : 'tcpa_at_componentModel',
              +    '06036781050209' : 'tcpa_at_componentVersion',
              +    '060367810503' : 'tcpa_protocol',
              +    '06036781050301' : 'tcpa_prtt_tpmIdProtocol',
              +    '0603672a00' : 'contentType',
              +    '0603672a0000' : 'PANData',
              +    '0603672a0001' : 'PANToken',
              +    '0603672a0002' : 'PANOnly',
              +    '0603672a01' : 'msgExt',
              +    '0603672a0a' : 'national',
              +    '0603672a0a8140' : 'Japan',
              +    '0603672a02' : 'field',
              +    '0603672a0200' : 'fullName',
              +    '0603672a0201' : 'givenName',
              +    '0603672a020a' : 'amount',
              +    '0603672a0202' : 'familyName',
              +    '0603672a0203' : 'birthFamilyName',
              +    '0603672a0204' : 'placeName',
              +    '0603672a0205' : 'identificationNumber',
              +    '0603672a0206' : 'month',
              +    '0603672a0207' : 'date',
              +    '0603672a02070b' : 'accountNumber',
              +    '0603672a02070c' : 'passPhrase',
              +    '0603672a0208' : 'address',
              +    '0603672a0209' : 'telephone',
              +    '0603672a03' : 'attribute',
              +    '0603672a0300' : 'cert',
              +    '0603672a030000' : 'rootKeyThumb',
              +    '0603672a030001' : 'additionalPolicy',
              +    '0603672a04' : 'algorithm',
              +    '0603672a05' : 'policy',
              +    '0603672a0500' : 'root',
              +    '0603672a06' : 'module',
              +    '0603672a07' : 'certExt',
              +    '0603672a0700' : 'hashedRootKey',
              +    '0603672a0701' : 'certificateType',
              +    '0603672a0702' : 'merchantData',
              +    '0603672a0703' : 'cardCertRequired',
              +    '0603672a0704' : 'tunneling',
              +    '0603672a0705' : 'setExtensions',
              +    '0603672a0706' : 'setQualifier',
              +    '0603672a08' : 'brand',
              +    '0603672a0801' : 'IATA-ATA',
              +    '0603672a081e' : 'Diners',
              +    '0603672a0822' : 'AmericanExpress',
              +    '0603672a0804' : 'VISA',
              +    '0603672a0805' : 'MasterCard',
              +    '0603672a08ae7b' : 'Novus',
              +    '0603672a09' : 'vendor',
              +    '0603672a0900' : 'GlobeSet',
              +    '0603672a0901' : 'IBM',
              +    '0603672a090a' : 'Griffin',
              +    '0603672a090b' : 'Certicom',
              +    '0603672a090c' : 'OSS',
              +    '0603672a090d' : 'TenthMountain',
              +    '0603672a090e' : 'Antares',
              +    '0603672a090f' : 'ECC',
              +    '0603672a0910' : 'Maithean',
              +    '0603672a0911' : 'Netscape',
              +    '0603672a0912' : 'Verisign',
              +    '0603672a0913' : 'BlueMoney',
              +    '0603672a0902' : 'CyberCash',
              +    '0603672a0914' : 'Lacerte',
              +    '0603672a0915' : 'Fujitsu',
              +    '0603672a0916' : 'eLab',
              +    '0603672a0917' : 'Entrust',
              +    '0603672a0918' : 'VIAnet',
              +    '0603672a0919' : 'III',
              +    '0603672a091a' : 'OpenMarket',
              +    '0603672a091b' : 'Lexem',
              +    '0603672a091c' : 'Intertrader',
              +    '0603672a091d' : 'Persimmon',
              +    '0603672a0903' : 'Terisa',
              +    '0603672a091e' : 'NABLE',
              +    '0603672a091f' : 'espace-net',
              +    '0603672a0920' : 'Hitachi',
              +    '0603672a0921' : 'Microsoft',
              +    '0603672a0922' : 'NEC',
              +    '0603672a0923' : 'Mitsubishi',
              +    '0603672a0924' : 'NCR',
              +    '0603672a0925' : 'e-COMM',
              +    '0603672a0926' : 'Gemplus',
              +    '0603672a0904' : 'RSADSI',
              +    '0603672a0905' : 'VeriFone',
              +    '0603672a0906' : 'TrinTech',
              +    '0603672a0907' : 'BankGate',
              +    '0603672a0908' : 'GTE',
              +    '0603672a0909' : 'CompuSource',
              +    '0603551d01' : 'authorityKeyIdentifier',
              +    '0603551d0a' : 'basicConstraints',
              +    '0603551d0b' : 'nameConstraints',
              +    '0603551d0c' : 'policyConstraints',
              +    '0603551d0d' : 'basicConstraints',
              +    '0603551d0e' : 'subjectKeyIdentifier',
              +    '0603551d0f' : 'keyUsage',
              +    '0603551d10' : 'privateKeyUsagePeriod',
              +    '0603551d11' : 'subjectAltName',
              +    '0603551d12' : 'issuerAltName',
              +    '0603551d13' : 'basicConstraints',
              +    '0603551d02' : 'keyAttributes',
              +    '0603551d14' : 'cRLNumber',
              +    '0603551d15' : 'cRLReason',
              +    '0603551d16' : 'expirationDate',
              +    '0603551d17' : 'instructionCode',
              +    '0603551d18' : 'invalidityDate',
              +    '0603551d1a' : 'issuingDistributionPoint',
              +    '0603551d1b' : 'deltaCRLIndicator',
              +    '0603551d1c' : 'issuingDistributionPoint',
              +    '0603551d1d' : 'certificateIssuer',
              +    '0603551d03' : 'certificatePolicies',
              +    '0603551d1e' : 'nameConstraints',
              +    '0603551d1f' : 'cRLDistributionPoints',
              +    '0603551d20' : 'certificatePolicies',
              +    '0603551d21' : 'policyMappings',
              +    '0603551d22' : 'policyConstraints',
              +    '0603551d23' : 'authorityKeyIdentifier',
              +    '0603551d24' : 'policyConstraints',
              +    '0603551d25' : 'extKeyUsage',
              +    '0603551d04' : 'keyUsageRestriction',
              +    '0603551d05' : 'policyMapping',
              +    '0603551d06' : 'subtreesConstraint',
              +    '0603551d07' : 'subjectAltName',
              +    '0603551d08' : 'issuerAltName',
              +    '0603551d09' : 'subjectDirectoryAttributes',
              +    '0603550400' : 'objectClass',
              +    '0603550401' : 'aliasObjectName',
              +    // '060355040c' : 'title',
              +    '060355040d' : 'description',
              +    '060355040e' : 'searchGuide',
              +    '060355040f' : 'businessCategory',
              +    '0603550410' : 'postalAddress',
              +    '0603550411' : 'postalCode',
              +    '0603550412' : 'postOfficeBox',
              +    '0603550413' : 'physicalDeliveryOfficeName',
              +    '0603550402' : 'knowledgeInformation',
              +    // '0603550414' : 'telephoneNumber',
              +    '0603550415' : 'telexNumber',
              +    '0603550416' : 'teletexTerminalIdentifier',
              +    '0603550417' : 'facsimileTelephoneNumber',
              +    '0603550418' : 'x121Address',
              +    '0603550419' : 'internationalISDNNumber',
              +    '060355041a' : 'registeredAddress',
              +    '060355041b' : 'destinationIndicator',
              +    '060355041c' : 'preferredDeliveryMehtod',
              +    '060355041d' : 'presentationAddress',
              +    '060355041e' : 'supportedApplicationContext',
              +    '060355041f' : 'member',
              +    '0603550420' : 'owner',
              +    '0603550421' : 'roleOccupant',
              +    '0603550422' : 'seeAlso',
              +    '0603550423' : 'userPassword',
              +    '0603550424' : 'userCertificate',
              +    '0603550425' : 'caCertificate',
              +    '0603550426' : 'authorityRevocationList',
              +    '0603550427' : 'certificateRevocationList',
              +    '0603550428' : 'crossCertificatePair',
              +    '0603550429' : 'givenName',
              +    // '060355042a' : 'givenName',
              +    '0603550405' : 'serialNumber',
              +    '0603550434' : 'supportedAlgorithms',
              +    '0603550435' : 'deltaRevocationList',
              +    '060355043a' : 'crossCertificatePair',
              +    // '0603550409' : 'streetAddress',
              +    '06035508' : 'X.500-Algorithms',
              +    '0603550801' : 'X.500-Alg-Encryption',
              +    '060355080101' : 'rsa',
              +    '0603604c0101' : 'DPC'
              +};
              \ No newline at end of file
              diff --git a/src/js/operations/Punycode.js b/src/js/operations/Punycode.js
              new file mode 100755
              index 00000000..cf58a8f1
              --- /dev/null
              +++ b/src/js/operations/Punycode.js
              @@ -0,0 +1,55 @@
              +/* globals punycode */
              +
              +/**
              + * Punycode operations.
              + *
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @namespace
              + */
              +var Punycode = {
              +
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    IDN: false,
              +    
              +    /**
              +     * To Punycode operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_to_ascii: function(input, args) {
              +        var idn = args[0];
              +        
              +        if (idn) {
              +            return punycode.ToASCII(input);
              +        } else {
              +            return punycode.encode(input);
              +        }
              +    },
              +    
              +    
              +    /**
              +     * From Punycode operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_to_unicode: function(input, args) {
              +        var idn = args[0];
              +        
              +        if (idn) {
              +            return punycode.ToUnicode(input);
              +        } else {
              +            return punycode.decode(input);
              +        }
              +    },
              +    
              +};
              diff --git a/src/js/operations/QuotedPrintable.js b/src/js/operations/QuotedPrintable.js
              new file mode 100755
              index 00000000..44375753
              --- /dev/null
              +++ b/src/js/operations/QuotedPrintable.js
              @@ -0,0 +1,270 @@
              +/** @license
              +========================================================================
              +  mimelib: http://github.com/andris9/mimelib
              +  Copyright (c) 2011-2012 Andris Reinman
              +  
              +  Permission is hereby granted, free of charge, to any person obtaining a copy
              +  of this software and associated documentation files (the "Software"), to deal
              +  in the Software without restriction, including without limitation the rights
              +  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
              +  copies of the Software, and to permit persons to whom the Software is
              +  furnished to do so, subject to the following conditions:
              +  
              +  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
              +  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
              +  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
              +  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
              +  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
              +  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
              +  SOFTWARE.
              +*/
              +
              +/**
              + * Quoted Printable operations.
              + * Some parts taken from mimelib (http://github.com/andris9/mimelib)
              + *
              + * @author Andris Reinman
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @namespace
              + */
              +var QuotedPrintable = {
              +    
              +    /**
              +     * To Quoted Printable operation.
              +     *
              +     * @param {byte_array} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_to: function (input, args) {
              +        var mimeEncodedStr = QuotedPrintable.mimeEncode(input);
              +        
              +        // fix line breaks
              +        mimeEncodedStr = mimeEncodedStr.replace(/\r?\n|\r/g, function() {
              +            return "\r\n";
              +        }).replace(/[\t ]+$/gm, function(spaces) {
              +            return spaces.replace(/ /g, "=20").replace(/\t/g, "=09");
              +        });
              +
              +        return QuotedPrintable._addSoftLinebreaks(mimeEncodedStr, "qp");
              +    },
              +    
              +    
              +    /**
              +     * From Quoted Printable operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {byte_array}
              +     */
              +    run_from: function (input, args) {
              +        var str = input.replace(/\=(?:\r?\n|$)/g, "");
              +        return QuotedPrintable.mimeDecode(str);
              +    },
              +    
              +    
              +    /**
              +     * Decodes mime-encoded data.
              +     *
              +     * @param {string} str
              +     * @returns {byte_array}
              +     */
              +    mimeDecode: function(str) {
              +        var encodedBytesCount = (str.match(/\=[\da-fA-F]{2}/g) || []).length,
              +            bufferLength = str.length - encodedBytesCount * 2,
              +            chr, hex,
              +            buffer = new Array(bufferLength),
              +            bufferPos = 0;
              +
              +        for (var i = 0, len = str.length; i < len; i++) {
              +            chr = str.charAt(i);
              +            if (chr == "=" && (hex = str.substr(i + 1, 2)) && /[\da-fA-F]{2}/.test(hex)) {
              +                buffer[bufferPos++] = parseInt(hex, 16);
              +                i += 2;
              +                continue;
              +            }
              +            buffer[bufferPos++] = chr.charCodeAt(0);
              +        }
              +
              +        return buffer;
              +    },
              +    
              +    
              +    /**
              +     * Encodes mime data.
              +     *
              +     * @param {byte_array} buffer
              +     * @returns {string}
              +     */
              +    mimeEncode: function(buffer) {
              +        var ranges = [
              +                [0x09],
              +                [0x0A],
              +                [0x0D],
              +                [0x20],
              +                [0x21],
              +                [0x23, 0x3C],
              +                [0x3E],
              +                [0x40, 0x5E],
              +                [0x60, 0x7E]
              +            ],
              +            result = "";
              +
              +        for (var i = 0, len = buffer.length; i < len; i++) {
              +            if (this._checkRanges(buffer[i], ranges)) {
              +                result += String.fromCharCode(buffer[i]);
              +                continue;
              +            }
              +            result += "=" + (buffer[i] < 0x10 ? "0" : "") + buffer[i].toString(16).toUpperCase();
              +        }
              +
              +        return result;
              +    },
              +    
              +    
              +    /**
              +     * Checks if a given number falls within a given set of ranges.
              +     *
              +     * @private
              +     * @param {number} nr
              +     * @param {byte_array[]} ranges
              +     * @returns {bolean}
              +     */
              +    _checkRanges: function(nr, ranges) {
              +        for (var i = ranges.length - 1; i >= 0; i--) {
              +            if (!ranges[i].length)
              +                continue;
              +            if (ranges[i].length == 1 && nr == ranges[i][0])
              +                return true;
              +            if (ranges[i].length == 2 && nr >= ranges[i][0] && nr <= ranges[i][1])
              +                return true;
              +        }
              +        return false;
              +    },
              +
              +    
              +    /**
              +     * Adds soft line breaks to a string.
              +     * Lines can't be longer that 76 + <CR><LF> = 78 bytes
              +     * http://tools.ietf.org/html/rfc2045#section-6.7
              +     *
              +     * @private
              +     * @param {string} str
              +     * @param {string} encoding
              +     * @returns {string}
              +     */
              +    _addSoftLinebreaks: function(str, encoding) {
              +        var lineLengthMax = 76;
              +
              +        encoding = (encoding || "base64").toString().toLowerCase().trim();
              +
              +        if (encoding == "qp") {
              +            return this._addQPSoftLinebreaks(str, lineLengthMax);
              +        } else {
              +            return this._addBase64SoftLinebreaks(str, lineLengthMax);
              +        }
              +    },
              +
              +    
              +    /**
              +     * Adds soft line breaks to a base64 string.
              +     *
              +     * @private
              +     * @param {string} base64EncodedStr
              +     * @param {number} lineLengthMax
              +     * @returns {string}
              +     */
              +    _addBase64SoftLinebreaks: function(base64EncodedStr, lineLengthMax) {
              +        base64EncodedStr = (base64EncodedStr || "").toString().trim();
              +        return base64EncodedStr.replace(new RegExp(".{" + lineLengthMax + "}", "g"), "$&\r\n").trim();
              +    },
              +
              +    
              +    /**
              +     * Adds soft line breaks to a quoted printable string.
              +     *
              +     * @private
              +     * @param {string} mimeEncodedStr
              +     * @param {number} lineLengthMax
              +     * @returns {string}
              +     */
              +    _addQPSoftLinebreaks: function(mimeEncodedStr, lineLengthMax) {
              +        var pos = 0,
              +            len = mimeEncodedStr.length,
              +            match, code, line,
              +            lineMargin = Math.floor(lineLengthMax / 3),
              +            result = "";
              +
              +        // insert soft linebreaks where needed
              +        while (pos < len) {
              +            line = mimeEncodedStr.substr(pos, lineLengthMax);
              +            if ((match = line.match(/\r\n/))) {
              +                line = line.substr(0, match.index + match[0].length);
              +                result += line;
              +                pos += line.length;
              +                continue;
              +            }
              +
              +            if (line.substr(-1) == "\n") {
              +                // nothing to change here
              +                result += line;
              +                pos += line.length;
              +                continue;
              +            } else if ((match = line.substr(-lineMargin).match(/\n.*?$/))) {
              +                // truncate to nearest line break
              +                line = line.substr(0, line.length - (match[0].length - 1));
              +                result += line;
              +                pos += line.length;
              +                continue;
              +            } else if (line.length > lineLengthMax - lineMargin && (match = line.substr(-lineMargin).match(/[ \t\.,!\?][^ \t\.,!\?]*$/))) {
              +                // truncate to nearest space
              +                line = line.substr(0, line.length - (match[0].length - 1));
              +            } else if (line.substr(-1) == "\r") {
              +                line = line.substr(0, line.length - 1);
              +            } else {
              +                if (line.match(/\=[\da-f]{0,2}$/i)) {
              +
              +                    // push incomplete encoding sequences to the next line
              +                    if ((match = line.match(/\=[\da-f]{0,1}$/i))) {
              +                        line = line.substr(0, line.length - match[0].length);
              +                    }
              +
              +                    // ensure that utf-8 sequences are not split
              +                    while (line.length > 3 && line.length < len - pos && !line.match(/^(?:=[\da-f]{2}){1,4}$/i) && (match = line.match(/\=[\da-f]{2}$/ig))) {
              +                        code = parseInt(match[0].substr(1, 2), 16);
              +                        if (code < 128) {
              +                            break;
              +                        }
              +
              +                        line = line.substr(0, line.length - 3);
              +
              +                        if (code >= 0xC0) {
              +                            break;
              +                        }
              +                    }
              +
              +                }
              +            }
              +
              +            if (pos + line.length < len && line.substr(-1) != "\n") {
              +                if (line.length == 76 && line.match(/\=[\da-f]{2}$/i)) {
              +                    line = line.substr(0, line.length - 3);
              +                } else if (line.length == 76) {
              +                    line = line.substr(0, line.length - 1);
              +                }
              +                pos += line.length;
              +                line += "=\r\n";
              +            } else {
              +                pos += line.length;
              +            }
              +
              +            result += line;
              +        }
              +
              +        return result;
              +    },
              +    
              +};
              diff --git a/src/js/operations/Rotate.js b/src/js/operations/Rotate.js
              new file mode 100755
              index 00000000..eadad540
              --- /dev/null
              +++ b/src/js/operations/Rotate.js
              @@ -0,0 +1,206 @@
              +/**
              + * Bit rotation operations.
              + *
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @namespace
              + *
              + * @todo Support for UTF16
              + */
              +var Rotate = {
              +
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    ROTATE_AMOUNT: 1,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    ROTATE_WHOLE: false,
              +    
              +    /**
              +     * Runs rotation operations across the input data.
              +     *
              +     * @private
              +     * @param {byte_array} data
              +     * @param {number} amount
              +     * @param {function} algo - The rotation operation to carry out
              +     * @returns {byte_array}
              +     */
              +    _rot: function(data, amount, algo) {
              +        var result = [];
              +        for (var i = 0; i < data.length; i++) {
              +            var b = data[i];
              +            for (var j = 0; j < amount; j++) {
              +                b = algo(b);
              +            }
              +            result.push(b);
              +        }
              +        return result;
              +    },
              +    
              +    
              +    /**
              +     * Rotate right operation.
              +     *
              +     * @param {byte_array} input
              +     * @param {Object[]} args
              +     * @returns {byte_array}
              +     */
              +    run_rotr: function(input, args) {
              +        if (args[1]) {
              +            return Rotate._rotr_whole(input, args[0]);
              +        } else {
              +            return Rotate._rot(input, args[0], Rotate._rotr);
              +        }
              +    },
              +    
              +    
              +    /**
              +     * Rotate left operation.
              +     *
              +     * @param {byte_array} input
              +     * @param {Object[]} args
              +     * @returns {byte_array}
              +     */
              +    run_rotl: function(input, args) {
              +        if (args[1]) {
              +            return Rotate._rotl_whole(input, args[0]);
              +        } else {
              +            return Rotate._rot(input, args[0], Rotate._rotl);
              +        }
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    ROT13_AMOUNT: 13,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    ROT13_LOWERCASE: true,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    ROT13_UPPERCASE: true,
              +    
              +    /**
              +     * ROT13 operation.
              +     *
              +     * @param {byte_array} input
              +     * @param {Object[]} args
              +     * @returns {byte_array}
              +     */
              +    run_rot13: function(input, args) {
              +        var amount = args[2],
              +            output = input,
              +            chr,
              +            rot13_lowercase = args[0],
              +            rot13_upperacse = args[1];
              +            
              +        if (amount) {
              +            if (amount < 0) {
              +                amount = 26 - (Math.abs(amount) % 26);
              +            }
              +            
              +            for (var i = 0; i < input.length; i++) {
              +                chr = input[i];
              +                if (rot13_upperacse && chr >= 65 && chr <= 90) { // Upper case
              +                    chr = (chr - 65 + amount) % 26;
              +                    output[i] = chr + 65;
              +                } else if (rot13_lowercase && chr >= 97 && chr <= 122) { // Lower case
              +                    chr = (chr - 97 + amount) % 26;
              +                    output[i] = chr + 97;
              +                }
              +            }
              +        }
              +        return output;
              +    },
              +    
              +    
              +    /**
              +     * Rotate right bitwise op.
              +     *
              +     * @private
              +     * @param {byte} b
              +     * @returns {byte}
              +     */
              +    _rotr: function(b) {
              +        var bit = (b & 1) << 7;
              +        return (b >> 1) | bit;
              +    },
              +    
              +    
              +    /**
              +     * Rotate left bitwise op.
              +     *
              +     * @private
              +     * @param {byte} b
              +     * @returns {byte}
              +     */
              +    _rotl: function(b) {
              +        var bit = (b >> 7) & 1;
              +        return ((b << 1) | bit) & 0xFF;
              +    },
              +    
              +    
              +    /**
              +     * Rotates a byte array to the right by a specific amount as a whole, so that bits are wrapped
              +     * from the end of the array to the beginning.
              +     *
              +     * @private
              +     * @param {byte_array} data
              +     * @param {number} amount
              +     * @returns {byte_array}
              +     */
              +    _rotr_whole: function(data, amount) {
              +        var carry_bits = 0,
              +            new_byte,
              +            result = [];
              +        
              +        amount = amount % 8;
              +        for (var i = 0; i < data.length; i++) {
              +            var old_byte = data[i] >>> 0;
              +            new_byte = (old_byte >> amount) | carry_bits;
              +            carry_bits = (old_byte & (Math.pow(2, amount)-1)) << (8-amount);
              +            result.push(new_byte);
              +        }
              +        result[0] |= carry_bits;
              +        return result;
              +    },
              +    
              +    
              +    /**
              +     * Rotates a byte array to the left by a specific amount as a whole, so that bits are wrapped
              +     * from the beginning of the array to the end.
              +     *
              +     * @private
              +     * @param {byte_array} data
              +     * @param {number} amount
              +     * @returns {byte_array}
              +     */
              +    _rotl_whole: function(data, amount) {
              +        var carry_bits = 0,
              +            new_byte,
              +            result = [];
              +            
              +        amount = amount % 8;
              +        for (var i = data.length-1; i >= 0; i--) {
              +            var old_byte = data[i];
              +            new_byte = ((old_byte << amount) | carry_bits) & 0xFF;
              +            carry_bits = (old_byte >> (8-amount)) & (Math.pow(2, amount)-1);
              +            result[i] = (new_byte);
              +        }
              +        result[data.length-1] = result[data.length-1] | carry_bits;
              +        return result;
              +    },
              +
              +};
              diff --git a/src/js/operations/SeqUtils.js b/src/js/operations/SeqUtils.js
              new file mode 100755
              index 00000000..fd04b757
              --- /dev/null
              +++ b/src/js/operations/SeqUtils.js
              @@ -0,0 +1,220 @@
              +/**
              + * Sequence utility operations.
              + *
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @namespace
              + */
              +var SeqUtils = {
              +
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    DELIMITER_OPTIONS: ["Line feed", "CRLF", "Space", "Comma", "Semi-colon", "Colon", "Nothing (separate chars)"],
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    SORT_REVERSE: false,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    SORT_ORDER: ["Alphabetical (case sensitive)", "Alphabetical (case insensitive)", "IP address"],
              +    
              +    /**
              +     * Sort operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_sort: function (input, args) {
              +        var delim = Utils.char_rep[args[0]],
              +            sort_reverse = args[1],
              +            order = args[2],
              +            sorted = input.split(delim);
              +            
              +        if (order == "Alphabetical (case sensitive)") {
              +            sorted = sorted.sort();
              +        } else if (order == "Alphabetical (case insensitive)") {
              +            sorted = sorted.sort(SeqUtils._case_insensitive_sort);
              +        } else if (order == "IP address") {
              +            sorted = sorted.sort(SeqUtils._ip_sort);
              +        }
              +            
              +        if (sort_reverse) sorted.reverse();
              +        return sorted.join(delim);
              +    },
              +    
              +    
              +    /**
              +     * Unique operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_unique: function (input, args) {
              +        var delim = Utils.char_rep[args[0]];
              +        return input.split(delim).unique().join(delim);
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    SEARCH_TYPE: ["Regex", "Extended (\\n, \\t, \\x...)", "Simple string"],
              +    
              +    /**
              +     * Count occurrences operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {number}
              +     */
              +    run_count: function(input, args) {
              +        var search = args[0].string,
              +            type = args[0].option;
              +            
              +        if (type == "Regex" && search) {
              +            try {
              +                var regex = new RegExp(search, "gi"),
              +                    matches = input.match(regex);
              +                return matches.length;
              +            } catch(err) {
              +                return 0;
              +            }
              +        } else if (search) {
              +            if (type.indexOf("Extended") === 0) {
              +                search = Utils.parse_escaped_chars(search);
              +            }
              +            return input.count(search);
              +        } else {
              +            return 0;
              +        }
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    REVERSE_BY: ["Character", "Line"],
              +    
              +    /**
              +     * Reverse operation.
              +     *
              +     * @param {byte_array} input
              +     * @param {Object[]} args
              +     * @returns {byte_array}
              +     */
              +    run_reverse: function (input, args) {
              +        if (args[0] == "Line") {
              +            var lines = [],
              +                line = [],
              +                result = [];
              +            for (var i = 0; i < input.length; i++) {
              +                if (input[i] == 0x0a) {
              +                    lines.push(line);
              +                    line = [];
              +                } else {
              +                    line.push(input[i]);
              +                }
              +            }
              +            lines.push(line);
              +            lines.reverse();
              +            for (i = 0; i < lines.length; i++) {
              +                result = result.concat(lines[i]);
              +                result.push(0x0a);
              +            }
              +            return result.slice(0, input.length);
              +        } else {
              +            return input.reverse();
              +        }
              +    },
              +    
              +    
              +    /**
              +     * Add line numbers operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_add_line_numbers: function(input, args) {
              +        var lines = input.split("\n"),
              +            output = "",
              +            width = lines.length.toString().length;
              +            
              +        for (var n = 0; n < lines.length; n++) {
              +            output += Utils.pad((n+1).toString(), width, " ") + " " + lines[n] + "\n";
              +        }
              +        return output.slice(0, output.length-1);
              +    },
              +    
              +    
              +    /**
              +     * Remove line numbers operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_remove_line_numbers: function(input, args) {
              +        return input.replace(/^[ \t]{0,5}\d+[\s:|\-,.)\]]/gm, "");
              +    },
              +    
              +    
              +    /**
              +     * Expand alphabet range operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_expand_alph_range: function(input, args) {
              +        return Utils.expand_alph_range(input).join(args[0]);
              +    },
              +    
              +    
              +    /**
              +     * Comparison operation for sorting of strings ignoring case.
              +     *
              +     * @private
              +     * @param {string} a
              +     * @param {string} b
              +     * @returns {number}
              +     */
              +    _case_insensitive_sort: function(a, b) {
              +        return a.toLowerCase().localeCompare(b.toLowerCase());
              +    },
              +    
              +    
              +    /**
              +     * Comparison operation for sorting of IPv4 addresses.
              +     *
              +     * @private
              +     * @param {string} a
              +     * @param {string} b
              +     * @returns {number}
              +     */
              +    _ip_sort: function(a, b) {
              +        var a_ = a.split("."),
              +            b_ = b.split(".");
              +        
              +        a_ = a_[0] * 0x1000000 + a_[1] * 0x10000 + a_[2] * 0x100 + a_[3] * 1;
              +        b_ = b_[0] * 0x1000000 + b_[1] * 0x10000 + b_[2] * 0x100 + b_[3] * 1;
              +        
              +        if (isNaN(a_) && !isNaN(b_)) return 1;
              +        if (!isNaN(a_) && isNaN(b_)) return -1;
              +        if (isNaN(a_) && isNaN(b_)) return a.localeCompare(b);
              +        
              +        return a_ - b_;
              +    },
              +    
              +};
              diff --git a/src/js/operations/StrUtils.js b/src/js/operations/StrUtils.js
              new file mode 100755
              index 00000000..f2bf3706
              --- /dev/null
              +++ b/src/js/operations/StrUtils.js
              @@ -0,0 +1,512 @@
              +/* globals JsDiff */
              +
              +/**
              + * String utility operations.
              + *
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @namespace
              + */
              +var StrUtils = {
              +
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    REGEX_PRE_POPULATE: [
              +        {
              +            name: "User defined",
              +            value: ""
              +        },
              +        {
              +            name: "IPv4 address",
              +            value: "(?:(?:\\d|[01]?\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d|\\d)(?:\\/\\d{1,2})?"
              +        },
              +        {
              +            name: "IPv6 address",
              +            value: "((?=.*::)(?!.*::.+::)(::)?([\\dA-Fa-f]{1,4}:(:|\\b)|){5}|([\\dA-Fa-f]{1,4}:){6})((([\\dA-Fa-f]{1,4}((?!\\3)::|:\\b|(?![\\dA-Fa-f])))|(?!\\2\\3)){2}|(((2[0-4]|1\\d|[1-9])?\\d|25[0-5])\\.?\\b){4})"
              +        },
              +        {
              +            name: "Email address",
              +            value: "(\\w[-.\\w]*)@([-\\w]+(?:\\.[-\\w]+)*)\\.([A-Za-z]{2,4})"
              +        },
              +        {
              +            name: "URL",
              +            value: "([A-Za-z]+://)([-\\w]+(?:\\.\\w[-\\w]*)+)(:\\d+)?(/[^.!,?;\"\\x27<>()\\[\\]{}\\s\\x7F-\\xFF]*(?:[.!,?]+[^.!,?;\"\\x27<>()\\[\\]{}\\s\\x7F-\\xFF]+)*)?"
              +        },
              +        {
              +            name: "Domain",
              +            value: "(?:(https?):\\/\\/)?([-\\w.]+)\\.(com|net|org|biz|info|co|uk|onion|int|mobi|name|edu|gov|mil|eu|ac|ae|af|de|ca|ch|cn|cy|es|gb|hk|il|in|io|tv|me|nl|no|nz|ro|ru|tr|us|az|ir|kz|uz|pk)+"
              +        },
              +        {
              +            name: "Windows file path",
              +            value: "([A-Za-z]):\\\\((?:[A-Za-z\\d][A-Za-z\\d\\- \\x27_\\(\\)]{0,61}\\\\?)*[A-Za-z\\d][A-Za-z\\d\\- \\x27_\\(\\)]{0,61})(\\.[A-Za-z\\d]{1,6})?"
              +        },
              +        {
              +            name: "UNIX file path",
              +            value: "(?:/[A-Za-z\\d.][A-Za-z\\d\\-.]{0,61})+"
              +        },
              +        {
              +            name: "MAC address",
              +            value: "[A-Fa-f\\d]{2}(?:[:-][A-Fa-f\\d]{2}){5}"
              +        },
              +        {
              +            name: "Date (yyyy-mm-dd)",
              +            value: "((?:19|20)\\d\\d)[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])"
              +        },
              +        {
              +            name: "Date (dd/mm/yyyy)",
              +            value: "(0[1-9]|[12][0-9]|3[01])[- /.](0[1-9]|1[012])[- /.]((?:19|20)\\d\\d)"
              +        },
              +        {
              +            name: "Date (mm/dd/yyyy)",
              +            value: "(0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])[- /.]((?:19|20)\\d\\d)"
              +        },
              +        {
              +            name: "Strings",
              +            value: "[A-Za-z\\d/\\-:.,_$%\\x27\"()<>= !\\[\\]{}@]{4,}"
              +        },
              +    ],
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    REGEX_CASE_INSENSITIVE: true,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    REGEX_MULTILINE_MATCHING: true,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    OUTPUT_FORMAT: ["Highlight matches", "List matches", "List capture groups", "List matches with capture groups"],
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    DISPLAY_TOTAL: false,
              +    
              +    /**
              +     * Regular expression operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {html}
              +     */
              +    run_regex: function(input, args) {
              +        var user_regex = args[1],
              +            i = args[2],
              +            m = args[3],
              +            display_total = args[4],
              +            output_format = args[5],
              +            modifiers = "g";
              +        
              +        if (i) modifiers += "i";
              +        if (m) modifiers += "m";
              +        
              +        if (user_regex && user_regex != "^" && user_regex != "$") {
              +            try {
              +                var regex = new RegExp(user_regex, modifiers);
              +                
              +                switch (output_format) {
              +                    case "Highlight matches":
              +                        return StrUtils._regex_highlight(input, regex, display_total);
              +                    case "List matches":
              +                        return Utils.escape_html(StrUtils._regex_list(input, regex, display_total, true, false));
              +                    case "List capture groups":
              +                        return Utils.escape_html(StrUtils._regex_list(input, regex, display_total, false, true));
              +                    case "List matches with capture groups":
              +                        return Utils.escape_html(StrUtils._regex_list(input, regex, display_total, true, true));
              +                    default:
              +                        return "Error: Invalid output format";
              +                }
              +            } catch (err) {
              +                return "Invalid regex. Details: " + err.message;
              +            }
              +        } else {
              +            return Utils.escape_html(input);
              +        }
              +    },
              +
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    CASE_SCOPE: ["All", "Word", "Sentence", "Paragraph"],
              +    
              +    /**
              +     * To Upper case operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_upper: function (input, args) {
              +        var scope = args[0];
              +        
              +        switch (scope) {
              +            case "Word":
              +                return input.replace(/(\b\w)/gi, function(m) {
              +                    return m.toUpperCase();
              +                });
              +            case "Sentence":
              +                return input.replace(/(?:\.|^)\s*(\b\w)/gi, function(m) {
              +                    return m.toUpperCase();
              +                });
              +            case "Paragraph":
              +                return input.replace(/(?:\n|^)\s*(\b\w)/gi, function(m) {
              +                    return m.toUpperCase();
              +                });
              +            case "All":
              +                /* falls through */
              +            default:
              +                return input.toUpperCase();
              +        }
              +    },
              +    
              +    
              +    /**
              +     * To Upper case operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_lower: function (input, args) {
              +        return input.toLowerCase();
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    SEARCH_TYPE: ["Regex", "Extended (\\n, \\t, \\x...)", "Simple string"],
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    FIND_REPLACE_GLOBAL : true,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    FIND_REPLACE_CASE : false,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    FIND_REPLACE_MULTILINE : true,
              +    
              +    /**
              +     * Find / Replace operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_find_replace: function(input, args) {
              +        var find = args[0].string,
              +            type = args[0].option,
              +            replace = args[1],
              +            g = args[2],
              +            i = args[3],
              +            m = args[4],
              +            modifiers = "";
              +            
              +        if (g) modifiers += "g";
              +        if (i) modifiers += "i";
              +        if (m) modifiers += "m";
              +        
              +        if (type == "Regex") {
              +            find = new RegExp(find, modifiers);
              +        } else if (type.indexOf("Extended") === 0) {
              +            find = Utils.parse_escaped_chars(find);
              +        }
              +        
              +        return input.replace(find, replace, modifiers);
              +        // Non-standard addition of flags in the third argument. This will work in Firefox but
              +        // probably nowhere else. The purpose is to allow global matching when the `find` parameter
              +        // is just a string.
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    SPLIT_DELIM: ",",
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    DELIMITER_OPTIONS: ["Line feed", "CRLF", "Space", "Comma", "Semi-colon", "Colon", "Nothing (separate chars)"],
              +    
              +    /**
              +     * Split operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_split: function(input, args) {
              +        var split_delim = args[0] || StrUtils.SPLIT_DELIM,
              +            join_delim = Utils.char_rep[args[1]],
              +            sections = input.split(split_delim);
              +            
              +        return sections.join(join_delim);
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    DIFF_SAMPLE_DELIMITER: "\\n\\n",
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    DIFF_BY: ["Character", "Word", "Line", "Sentence", "CSS", "JSON"],
              +    
              +    /**
              +     * Diff operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {html}
              +     */
              +    run_diff: function(input, args) {
              +        var sample_delim = args[0],
              +            diff_by = args[1],
              +            show_added = args[2],
              +            show_removed = args[3],
              +            ignore_whitespace = args[4],
              +            samples = input.split(sample_delim),
              +            output = "",
              +            diff;
              +            
              +        if (!samples || samples.length != 2) {
              +            return "Incorrect number of samples, perhaps you need to modify the sample delimiter or add more samples?";
              +        }
              +        
              +        switch (diff_by) {
              +            case "Character":
              +                diff = JsDiff.diffChars(samples[0], samples[1]);
              +                break;
              +            case "Word":
              +                if (ignore_whitespace) {
              +                    diff = JsDiff.diffWords(samples[0], samples[1]);
              +                } else {
              +                    diff = JsDiff.diffWordsWithSpace(samples[0], samples[1]);
              +                }
              +                break;
              +            case "Line":
              +                if (ignore_whitespace) {
              +                    diff = JsDiff.diffTrimmedLines(samples[0], samples[1]);
              +                } else {
              +                    diff = JsDiff.diffLines(samples[0], samples[1]);
              +                }
              +                break;
              +            case "Sentence":
              +                diff = JsDiff.diffSentences(samples[0], samples[1]);
              +                break;
              +            case "CSS":
              +                diff = JsDiff.diffCss(samples[0], samples[1]);
              +                break;
              +            case "JSON":
              +                diff = JsDiff.diffJson(samples[0], samples[1]);
              +                break;
              +            default:
              +                return "Invalid 'Diff by' option.";
              +        }
              +        
              +        for (var i = 0; i < diff.length; i++) {
              +            if (diff[i].added) {
              +                if (show_added) output += "<span class='hlgreen'>" + Utils.escape_html(diff[i].value) + "</span>";
              +            } else if (diff[i].removed) {
              +                if (show_removed) output += "<span class='hlred'>" + Utils.escape_html(diff[i].value) + "</span>";
              +            } else {
              +                output += Utils.escape_html(diff[i].value);
              +            }
              +        }
              +        
              +        return output;
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    OFF_CHK_SAMPLE_DELIMITER: "\\n\\n",
              +    
              +    /**
              +     * Offset checker operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {html}
              +     */
              +    run_offset_checker: function(input, args) {
              +        var sample_delim = args[0],
              +            samples = input.split(sample_delim),
              +            outputs = [],
              +            i = 0,
              +            s = 0,
              +            match = false,
              +            in_match = false,
              +            chr;
              +            
              +        if (!samples || samples.length < 2) {
              +            return "Not enough samples, perhaps you need to modify the sample delimiter or add more data?";
              +        }
              +        
              +        // Initialise output strings
              +        for (s = 0; s < samples.length; s++) {
              +            outputs[s] = "";
              +        }
              +        
              +        // Loop through each character in the first sample
              +        for (i = 0; i < samples[0].length; i++) {
              +            chr = samples[0][i];
              +            match = false;
              +            
              +            // Loop through each sample to see if the chars are the same
              +            for (s = 1; s < samples.length; s++) {
              +                if (samples[s][i] != chr) {
              +                    match = false;
              +                    break;
              +                }
              +                match = true;
              +            }
              +            
              +            // Write output for each sample
              +            for (s = 0; s < samples.length; s++) {
              +                if (samples[s].length <= i) {
              +                    if (in_match) outputs[s] += "</span>";
              +                    if (s == samples.length - 1) in_match = false;
              +                    continue;
              +                }
              +                
              +                if (match && !in_match) {
              +                    outputs[s] += "<span class='hlgreen'>" + Utils.escape_html(samples[s][i]);
              +                    if (samples[s].length == i + 1) outputs[s] += "</span>";
              +                    if (s == samples.length - 1) in_match = true;
              +                } else if (!match && in_match) {
              +                    outputs[s] += "</span>" + Utils.escape_html(samples[s][i]);
              +                    if (s == samples.length - 1) in_match = false;
              +                } else {
              +                    outputs[s] += Utils.escape_html(samples[s][i]);
              +                    if (in_match && samples[s].length == i + 1) {
              +                        outputs[s] += "</span>";
              +                        if (samples[s].length - 1 != i) in_match = false;
              +                    }
              +                }
              +                
              +                if (samples[0].length - 1 == i) {
              +                    if (in_match) outputs[s] += "</span>";
              +                    outputs[s] += Utils.escape_html(samples[s].substring(i + 1));
              +                }
              +            }
              +        }
              +        
              +        return outputs.join(sample_delim);
              +    },
              +    
              +    
              +    /**
              +     * Parse escaped string operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_parse_escaped_string: function(input, args) {
              +        return Utils.parse_escaped_chars(input);
              +    },
              +    
              +    
              +    /**
              +     * Adds HTML highlights to matches within a string.
              +     *
              +     * @private
              +     * @param {string} input
              +     * @param {RegExp} regex
              +     * @param {boolean} display_total
              +     * @returns {string}
              +     */
              +    _regex_highlight: function(input, regex, display_total) {
              +        var output = "",
              +            m,
              +            hl = 1,
              +            i = 0,
              +            total = 0;
              +        
              +        while (!!(m = regex.exec(input))) {
              +            // Add up to match
              +            output += Utils.escape_html(input.slice(i, m.index));
              +            
              +            // Add match with highlighting
              +            output += "<span class='hl"+hl+"'>" + Utils.escape_html(m[0]) + "</span>";
              +            
              +            // Switch highlight
              +            hl = hl == 1 ? 2 : 1;
              +            
              +            i = regex.lastIndex;
              +            total++;
              +        }
              +        
              +        // Add all after final match
              +        output += Utils.escape_html(input.slice(i, input.length));
              +        
              +        if (display_total)
              +            output = "Total found: " + total + "\n\n" + output;
              +
              +        return output;
              +    },
              +    
              +    
              +    /**
              +     * Creates a string listing the matches within a string.
              +     *
              +     * @private
              +     * @param {string} input
              +     * @param {RegExp} regex
              +     * @param {boolean} display_total
              +     * @param {boolean} matches - Display full match
              +     * @param {boolean} capture_groups - Display each of the capture groups separately
              +     * @returns {string}
              +     */
              +    _regex_list: function(input, regex, display_total, matches, capture_groups) {
              +        var output = "",
              +            total = 0,
              +            match;
              +            
              +        while (!!(match = regex.exec(input))) {
              +            total++;
              +            if (matches) {
              +                output += match[0] + "\n";
              +            }
              +            if (capture_groups) {
              +                for (var i = 1; i < match.length; i++) {
              +                    if (matches) {
              +                        output += "  Group " + i + ": ";
              +                    }
              +                    output += match[i] + "\n";
              +                }
              +            }
              +        }
              +        
              +        if (display_total)
              +            output = "Total found: " + total + "\n\n" + output;
              +            
              +        return output;
              +    },
              +    
              +};
              diff --git a/src/js/operations/Tidy.js b/src/js/operations/Tidy.js
              new file mode 100755
              index 00000000..e003b06f
              --- /dev/null
              +++ b/src/js/operations/Tidy.js
              @@ -0,0 +1,238 @@
              +/**
              + * Tidy operations.
              + *
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @namespace
              + */
              +var Tidy = {
              +
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    REMOVE_SPACES : true,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    REMOVE_CARIAGE_RETURNS : true,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    REMOVE_LINE_FEEDS : true,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    REMOVE_TABS : true,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    REMOVE_FORM_FEEDS : true,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    REMOVE_FULL_STOPS : false,
              +    
              +    /**
              +     * Remove whitespace operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_remove_whitespace: function (input, args) {
              +        var remove_spaces = args[0],
              +            remove_cariage_returns = args[1],
              +            remove_line_feeds = args[2],
              +            remove_tabs = args[3],
              +            remove_form_feeds = args[4],
              +            remove_full_stops = args[5],
              +            data = input;
              +            
              +        if (remove_spaces) data = data.replace(/ /g, "");
              +        if (remove_cariage_returns) data = data.replace(/\r/g, "");
              +        if (remove_line_feeds) data = data.replace(/\n/g, "");
              +        if (remove_tabs) data = data.replace(/\t/g, "");
              +        if (remove_form_feeds) data = data.replace(/\f/g, "");
              +        if (remove_full_stops) data = data.replace(/\./g, "");
              +        return data;
              +    },
              +    
              +    
              +    /**
              +     * Remove null bytes operation.
              +     *
              +     * @param {byte_array} input
              +     * @param {Object[]} args
              +     * @returns {byte_array}
              +     */
              +    run_remove_nulls: function (input, args) {
              +        var output = [];
              +        for (var i = 0; i < input.length; i++) {
              +            if (input[i] !== 0) output.push(input[i]);
              +        }
              +        return output;
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    APPLY_TO_EACH_LINE : false,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    DROP_START : 0,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    DROP_LENGTH : 5,
              +    
              +    /**
              +     * Drop bytes operation.
              +     *
              +     * @param {byte_array} input
              +     * @param {Object[]} args
              +     * @returns {byte_array}
              +     */
              +    run_drop_bytes: function(input, args) {
              +        var start = args[0],
              +            length = args[1],
              +            apply_to_each_line = args[2];
              +            
              +        if (start < 0 || length < 0)
              +            throw "Error: Invalid value";
              +            
              +        if (!apply_to_each_line)
              +            return input.slice(0, start).concat(input.slice(start+length, input.length));
              +            
              +        // Split input into lines
              +        var lines = [],
              +            line = [];
              +            
              +        for (var i = 0; i < input.length; i++) {
              +            if (input[i] == 0x0a) {
              +                lines.push(line);
              +                line = [];
              +            } else {
              +                line.push(input[i]);
              +            }
              +        }
              +        lines.push(line);
              +        
              +        var output = [];
              +        for (i = 0; i < lines.length; i++) {
              +            output = output.concat(lines[i].slice(0, start).concat(lines[i].slice(start+length, lines[i].length)));
              +            output.push(0x0a);
              +        }
              +        return output.slice(0, output.length-1);
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    TAKE_START: 0,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    TAKE_LENGTH: 5,
              +    
              +    /**
              +     * Take bytes operation.
              +     *
              +     * @param {byte_array} input
              +     * @param {Object[]} args
              +     * @returns {byte_array}
              +     */
              +    run_take_bytes: function(input, args) {
              +        var start = args[0],
              +            length = args[1],
              +            apply_to_each_line = args[2];
              +            
              +        if (start < 0 || length < 0)
              +            throw "Error: Invalid value";
              +            
              +        if (!apply_to_each_line)
              +            return input.slice(start, start+length);
              +            
              +        // Split input into lines
              +        var lines = [],
              +            line = [];
              +            
              +        for (var i = 0; i < input.length; i++) {
              +            if (input[i] == 0x0a) {
              +                lines.push(line);
              +                line = [];
              +            } else {
              +                line.push(input[i]);
              +            }
              +        }
              +        lines.push(line);
              +        
              +        var output = [];
              +        for (i = 0; i < lines.length; i++) {
              +            output = output.concat(lines[i].slice(start, start+length));
              +            output.push(0x0a);
              +        }
              +        return output.slice(0, output.length-1);
              +    },
              +    
              +    
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    PAD_POSITION : ["Start", "End"],
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    PAD_LENGTH : 5,
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    PAD_CHAR : " ",
              +    
              +    /**
              +     * Pad lines operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_pad: function(input, args) {
              +        var position = args[0],
              +            len = args[1],
              +            chr = args[2],
              +            lines = input.split("\n"),
              +            output = "",
              +            i = 0;
              +            
              +        if (position == "Start") {
              +            for (i = 0; i < lines.length; i++) {
              +                output += Utils.pad_left(lines[i], lines[i].length+len, chr) + "\n";
              +            }
              +        } else if (position == "End") {
              +            for (i = 0; i < lines.length; i++) {
              +                output += Utils.pad_right(lines[i], lines[i].length+len, chr) + "\n";
              +            }
              +        }
              +        
              +        return output.slice(0, output.length-1);
              +    },
              +    
              +};
              diff --git a/src/js/operations/URL.js b/src/js/operations/URL.js
              new file mode 100755
              index 00000000..6734f4c0
              --- /dev/null
              +++ b/src/js/operations/URL.js
              @@ -0,0 +1,130 @@
              +/* globals unescape */
              +
              +/**
              + * URL operations.
              + * Namespace is appended with an underscore to prevent overwriting the global URL object.
              + *
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @namespace
              + */
              +var URL_ = {
              +
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    ENCODE_ALL: false,
              +    
              +    /**
              +     * URL Encode operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_to: function(input, args) {
              +        var encode_all = args[0];
              +        return encode_all ? URL_._encode_all_chars(input) : encodeURI(input);
              +    },
              +    
              +    
              +    /**
              +     * URL Decode operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_from: function(input, args) {
              +        var data = input.replace(/\+/g, "%20");
              +        try {
              +            return decodeURIComponent(data);
              +        } catch(err) {
              +            return unescape(data);
              +        }
              +    },
              +    
              +    
              +    /**
              +     * Parse URI operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_parse: function(input, args) {
              +        var a = document.createElement("a");
              +        
              +        // Overwrite base href which will be the current CyberChef URL to reduce confusion.
              +        a.href = "http://example.com/";
              +        a.href = input;
              +        
              +        if (a.protocol) {
              +            var output = "";
              +            if (a.hostname != window.location.hostname) {
              +                output = "Protocol:\t" + a.protocol + "\n";
              +                if (a.hostname) output += "Hostname:\t" + a.hostname + "\n";
              +                if (a.port) output += "Port:\t\t" + a.port + "\n";
              +            }
              +            
              +            if (a.pathname) {
              +                var pathname = a.pathname;
              +                if (pathname.indexOf(window.location.pathname) === 0)
              +                    pathname = pathname.replace(window.location.pathname, "");
              +                if (pathname)
              +                    output += "Path name:\t" + pathname + "\n";
              +            }
              +            
              +            if (a.hash) {
              +                output += "Hash:\t\t" + a.hash + "\n";
              +            }
              +            
              +            if (a.search) {
              +                output += "Arguments:\n";
              +                var args_ = (a.search.slice(1, a.search.length)).split("&");
              +                var split_args = [], padding = 0;
              +                for (var i = 0; i < args_.length; i++) {
              +                    split_args.push(args_[i].split("="));
              +                    padding = (split_args[i][0].length > padding) ? split_args[i][0].length : padding;
              +                }
              +                for (i = 0; i < split_args.length; i++) {
              +                    output += "\t" + Utils.pad_right(split_args[i][0], padding);
              +                    if (split_args[i].length > 1 && split_args[i][1].length)
              +                        output += " = " + split_args[i][1] + "\n";
              +                    else output += "\n";
              +                }
              +            }
              +                    
              +            return output;
              +        }
              +        
              +        return "Invalid URI";
              +    },
              +    
              +    
              +    /**
              +     * URL encodes additional special characters beyond the standard set.
              +     *
              +     * @private
              +     * @param {string} str
              +     * @returns {string}
              +     */
              +    _encode_all_chars: function(str) {
              +        //TODO Do this programatically
              +        return encodeURIComponent(str)
              +            .replace(/!/g, "%21")
              +            .replace(/#/g, "%23")
              +            .replace(/'/g, "%27")
              +            .replace(/\(/g, "%28")
              +            .replace(/\)/g, "%29")
              +            .replace(/\*/g, "%2A")
              +            .replace(/\-/g, "%2D")
              +            .replace(/\./g, "%2E")
              +            .replace(/_/g, "%5F")
              +            .replace(/~/g, "%7E");
              +    },
              +    
              +};
              diff --git a/src/js/operations/UUID.js b/src/js/operations/UUID.js
              new file mode 100755
              index 00000000..a58fb45b
              --- /dev/null
              +++ b/src/js/operations/UUID.js
              @@ -0,0 +1,39 @@
              +/**
              + * UUID operations.
              + *
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @namespace
              + */
              +var UUID = {
              +
              +    /**
              +     * Generate UUID operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_generate_v4: function(input, args) {
              +        if (typeof(window.crypto) !== 'undefined' && typeof(window.crypto.getRandomValues) !== 'undefined') {
              +            var buf = new Uint32Array(4),
              +                i = 0;
              +            window.crypto.getRandomValues(buf);
              +            return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
              +                var r = (buf[i >> 3] >> ((i % 8) * 4)) & 0xf,
              +                    v = c === "x" ? r : (r & 0x3 | 0x8);
              +                i++;
              +                return v.toString(16);
              +            });
              +        } else {
              +            return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
              +                var r = Math.random() * 16 | 0,
              +                    v = c === "x" ? r : (r & 0x3 | 0x8);
              +                return v.toString(16);
              +            });
              +        }
              +    },
              +
              +};
              diff --git a/src/js/operations/Unicode.js b/src/js/operations/Unicode.js
              new file mode 100755
              index 00000000..6b5a00d4
              --- /dev/null
              +++ b/src/js/operations/Unicode.js
              @@ -0,0 +1,62 @@
              +/**
              + * Unicode operations.
              + *
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @namespace
              + */
              +var Unicode = {
              +
              +    /**
              +     * @constant
              +     * @default
              +     */
              +    PREFIXES: ["\\u", "%u", "U+"],
              +
              +    /**
              +     * Unescape Unicode Characters operation.
              +     *
              +     * @param {string} input
              +     * @param {Object[]} args
              +     * @returns {string}
              +     */
              +    run_unescape: function(input, args) {
              +        var prefix = Unicode._prefix_to_regex[args[0]],
              +            regex = new RegExp(prefix+"([a-f\\d]{4,6})", "ig"),
              +            output = "",
              +            m,
              +            i = 0;
              +        
              +        while (!!(m = regex.exec(input))) {
              +            // Add up to match
              +            output += input.slice(i, m.index);
              +            i = m.index;
              +            
              +            // Add match
              +            output += Utils.chr(parseInt(m[1], 16));
              +            
              +            i = regex.lastIndex;
              +        }
              +        
              +        // Add all after final match
              +        output += input.slice(i, input.length);
              +        
              +        return output;
              +    },
              +    
              +    
              +    /**
              +     * Lookup table to add prefixes to unicode delimiters so that they can be used in a regex.
              +     *
              +     * @private
              +     * @constant
              +     */
              +    _prefix_to_regex: {
              +        "\\u": "\\\\u",
              +        "%u": "%u",
              +        "U+": "U\\+"
              +    },
              +
              +};
              diff --git a/src/js/views/html/ControlsWaiter.js b/src/js/views/html/ControlsWaiter.js
              new file mode 100755
              index 00000000..9d5113be
              --- /dev/null
              +++ b/src/js/views/html/ControlsWaiter.js
              @@ -0,0 +1,340 @@
              +/**
              + * Waiter to handle events related to the CyberChef controls (i.e. Bake, Step, Save, Load etc.)
              + *
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @constructor
              + * @param {HTMLApp} app - The main view object for CyberChef.
              + * @param {Manager} manager - The CyberChef event manager.
              + */
              +var ControlsWaiter = function(app, manager) {
              +    this.app = app;
              +    this.manager = manager;
              +};
              +
              +
              +/**
              + * Adjusts the display properties of the control buttons so that they fit within the current width
              + * without wrapping or overflowing.
              + */
              +ControlsWaiter.prototype.adjust_width = function() {
              +    var controls       = document.getElementById("controls"),
              +        step           = document.getElementById("step"),
              +        clr_breaks     = document.getElementById("clr-breaks"),
              +        save_img       = document.querySelector("#save img"),
              +        load_img       = document.querySelector("#load img"),
              +        step_img       = document.querySelector("#step img"),
              +        clr_recip_img  = document.querySelector("#clr-recipe img"),
              +        clr_breaks_img = document.querySelector("#clr-breaks img");
              +    
              +    if (controls.clientWidth < 470) {
              +        step.childNodes[1].nodeValue = " Step";
              +    } else {
              +        step.childNodes[1].nodeValue = " Step through";
              +    }
              +        
              +    if (controls.clientWidth < 400) {
              +        save_img.style.display = "none";
              +        load_img.style.display = "none";
              +        step_img.style.display = "none";
              +        clr_recip_img.style.display = "none";
              +        clr_breaks_img.style.display = "none";
              +    } else {
              +        save_img.style.display = "inline";
              +        load_img.style.display = "inline";
              +        step_img.style.display = "inline";
              +        clr_recip_img.style.display = "inline";
              +        clr_breaks_img.style.display = "inline";
              +    }
              +    
              +    if (controls.clientWidth < 330) {
              +        clr_breaks.childNodes[1].nodeValue = " Clear breaks";
              +    } else {
              +        clr_breaks.childNodes[1].nodeValue = " Clear breakpoints";
              +    }
              +};
              +
              +
              +/**
              + * Checks or unchecks the Auto Bake checkbox based on the given value.
              + *
              + * @param {boolean} value - The new value for Auto Bake.
              + */
              +ControlsWaiter.prototype.set_auto_bake = function(value) {
              +    var auto_bake_checkbox = document.getElementById("auto-bake");
              +    
              +    if (auto_bake_checkbox.checked != value) {
              +        auto_bake_checkbox.click();
              +    }
              +};
              +
              +
              +/**
              + * Handler to trigger baking.
              + */
              +ControlsWaiter.prototype.bake_click = function() {
              +    this.app.bake();
              +    $("#output-text").selectRange(0);
              +};
              +
              +
              +/**
              + * Handler for the 'Step through' command. Executes the next step of the recipe.
              + */
              +ControlsWaiter.prototype.step_click = function() {
              +    this.app.bake(true);
              +    $("#output-text").selectRange(0);
              +};
              +
              +
              +/**
              + * Handler for changes made to the Auto Bake checkbox.
              + */
              +ControlsWaiter.prototype.auto_bake_change = function() {
              +    var auto_bake_label    = document.getElementById("auto-bake-label"),
              +        auto_bake_checkbox = document.getElementById("auto-bake");
              +        
              +    this.app.auto_bake_ = auto_bake_checkbox.checked;
              +    
              +    if (auto_bake_checkbox.checked) {
              +        auto_bake_label.classList.remove("btn-default");
              +        auto_bake_label.classList.add("btn-success");
              +    } else {
              +        auto_bake_label.classList.remove("btn-success");
              +        auto_bake_label.classList.add("btn-default");
              +    }
              +};
              +
              +
              +/**
              + * Handler for the 'Clear recipe' command. Removes all operations from the recipe.
              + */
              +ControlsWaiter.prototype.clear_recipe_click = function() {
              +    this.manager.recipe.clear_recipe();
              +};
              +
              +
              +/**
              + * Handler for the 'Clear breakpoints' command. Removes all breakpoints from operations in the
              + * recipe.
              + */
              +ControlsWaiter.prototype.clear_breaks_click = function() {
              +    var bps = document.querySelectorAll("#rec_list li.operation .breakpoint");
              +    
              +    for (var i = 0; i < bps.length; i++) {
              +        bps[i].setAttribute("break", "false");
              +        bps[i].classList.remove("breakpoint-selected");
              +    }
              +};
              +
              +
              +/**
              + * Populates the save disalog box with a URL incorporating the recipe and input.
              + *
              + * @param {Object[]} [recipe_config] - The recipe configuration object array.
              + */
              +ControlsWaiter.prototype.initialise_save_link = function(recipe_config) {
              +    recipe_config = recipe_config || this.app.get_recipe_config();
              +    
              +    var recipe_str = JSON.stringify(recipe_config),
              +        input_str = Utils.to_base64(this.app.get_input()),
              +        include_recipe = document.getElementById("save-link-recipe-checkbox").checked,
              +        include_input = document.getElementById("save-link-input-checkbox").checked,
              +        save_link_el = document.getElementById("save-link"),
              +        save_link = this.generate_state_url(include_recipe, include_input, recipe_config);
              +    
              +    save_link_el.innerHTML = Utils.truncate(save_link, 120);
              +    save_link_el.setAttribute("href", save_link);
              +};
              +
              +
              +/**
              + * Generates a URL containing the current recipe and input state.
              + *
              + * @param {boolean} include_recipe - Whether to include the recipe in the URL.
              + * @param {boolean} include_input - Whether to include the input in the URL.
              + * @param {Object[]} [recipe_config] - The recipe configuration object array.
              + * @returns {string}
              + */
              +ControlsWaiter.prototype.generate_state_url = function(include_recipe, include_input, recipe_config) {
              +    recipe_config = recipe_config || this.app.get_recipe_config();
              +    
              +    var link = window.location.protocol + "//" +
              +                window.location.host +
              +                window.location.pathname,
              +        recipe_str = JSON.stringify(recipe_config),
              +        input_str = Utils.to_base64(this.app.get_input(), "A-Za-z0-9+/"); // B64 alphabet with no padding
              +        
              +    include_recipe = include_recipe && (recipe_config.length > 0);
              +    include_input = include_input && (input_str.length > 0) && (input_str.length < 8000);
              +
              +    if (include_recipe) {
              +        link += "?recipe=" + encodeURIComponent(recipe_str);
              +    }
              +    
              +    if (include_recipe && include_input) {
              +        link += "&input=" + encodeURIComponent(input_str);
              +    } else if (include_input) {
              +        link += "?input=" + encodeURIComponent(input_str);
              +    }
              +    
              +    return link;
              +};
              +
              +
              +/**
              + * Handler for changes made to the save dialog text area. Re-initialises the save link.
              + */
              +ControlsWaiter.prototype.save_text_change = function() {
              +    try {
              +        var recipe_config = JSON.parse(document.getElementById("save-text").value);
              +        this.initialise_save_link(recipe_config);
              +    } catch(err) {}
              +};
              +
              +
              +/**
              + * Handler for the 'Save' command. Pops up the save dialog box.
              + */
              +ControlsWaiter.prototype.save_click = function() {
              +    var recipe_config = this.app.get_recipe_config();
              +    var recipe_str = JSON.stringify(recipe_config).replace(/},{/g, '},\n{');
              +    document.getElementById("save-text").value = recipe_str;
              +    
              +    this.initialise_save_link(recipe_config);
              +    $("#save-modal").modal();
              +};
              +
              +
              +/**
              + * Handler for the save link recipe checkbox change event.
              + */
              +ControlsWaiter.prototype.slr_check_change = function() {
              +    this.initialise_save_link();
              +};
              +
              +
              +/**
              + * Handler for the save link input checkbox change event.
              + */
              +ControlsWaiter.prototype.sli_check_change = function() {
              +    this.initialise_save_link();
              +};
              +
              +
              +/**
              + * Handler for the 'Load' command. Pops up the load dialog box.
              + */
              +ControlsWaiter.prototype.load_click = function() {
              +    this.populate_load_recipes_list();
              +    $("#load-modal").modal();
              +};
              +
              +
              +/**
              + * Saves the recipe specified in the save textarea to local storage.
              + */
              +ControlsWaiter.prototype.save_button_click = function() {
              +    var recipe_name = document.getElementById("save-name").value,
              +        recipe_str  = document.getElementById("save-text").value;
              +    
              +    if (!recipe_name) {
              +        this.app.alert("Please enter a recipe name", "danger", 2000);
              +        return;
              +    }
              +    
              +    var saved_recipes = localStorage.saved_recipes ?
              +            JSON.parse(localStorage.saved_recipes) : [],
              +        recipe_id = localStorage.recipe_id || 0;
              +    
              +    saved_recipes.push({
              +        id: ++recipe_id,
              +        name: recipe_name,
              +        recipe: recipe_str
              +    });
              +    
              +    localStorage.saved_recipes = JSON.stringify(saved_recipes);
              +    localStorage.recipe_id = recipe_id;
              +    
              +    this.app.alert("Recipe saved as \"" + recipe_name + "\".", "success", 2000);
              +};
              +
              +
              +/**
              + * Populates the list of saved recipes in the load dialog box from local storage.
              + */
              +ControlsWaiter.prototype.populate_load_recipes_list = function() {
              +    var load_name_el = document.getElementById("load-name");
              +        
              +    // Remove current recipes from select
              +    var i = load_name_el.options.length;
              +    while (i--) {
              +        load_name_el.remove(i);
              +    }
              +
              +    // Add recipes to select
              +    var saved_recipes = localStorage.saved_recipes ?
              +            JSON.parse(localStorage.saved_recipes) : [];
              +    
              +    for (i = 0; i < saved_recipes.length; i++) {
              +        var opt = document.createElement("option");
              +        opt.value = saved_recipes[i].id;
              +        opt.innerHTML = saved_recipes[i].name;
              +        
              +        load_name_el.appendChild(opt);
              +    }
              +    
              +    // Populate textarea with first recipe
              +    document.getElementById("load-text").value = saved_recipes.length ? saved_recipes[0].recipe : "";
              +};
              +
              +
              +/**
              + * Removes the currently selected recipe from local storage.
              + */
              +ControlsWaiter.prototype.load_delete_click = function() {
              +    var id = document.getElementById("load-name").value,
              +        saved_recipes = localStorage.saved_recipes ?
              +            JSON.parse(localStorage.saved_recipes) : [];
              +        
              +    saved_recipes = saved_recipes.filter(function(r) {
              +        return r.id != id;
              +    });
              +    
              +    localStorage.saved_recipes = JSON.stringify(saved_recipes);
              +    this.populate_load_recipes_list();
              +};
              +
              +
              +/**
              + * Displays the selected recipe in the load text box.
              + */
              +ControlsWaiter.prototype.load_name_change = function(e) {
              +    var el = e.target,
              +        saved_recipes = localStorage.saved_recipes ?
              +            JSON.parse(localStorage.saved_recipes) : [],
              +        id = parseInt(el.value, 10);
              +        
              +    var recipe = saved_recipes.filter(function(r) {
              +        return r.id == id;
              +    })[0];
              +    
              +    document.getElementById("load-text").value = recipe.recipe;
              +};
              +
              +
              +/**
              + * Loads the selected recipe and populates the Recipe with its operations.
              + */
              +ControlsWaiter.prototype.load_button_click = function() {
              +    try {
              +        var recipe_config = JSON.parse(document.getElementById("load-text").value);
              +        this.app.set_recipe_config(recipe_config);
              +
              +        $("#rec_list [data-toggle=popover]").popover();
              +    } catch(e) {
              +        this.app.alert("Invalid recipe", "danger", 2000);
              +    }
              +};
              diff --git a/src/js/views/html/HTMLApp.js b/src/js/views/html/HTMLApp.js
              new file mode 100755
              index 00000000..fbd497ea
              --- /dev/null
              +++ b/src/js/views/html/HTMLApp.js
              @@ -0,0 +1,667 @@
              +/* globals Split */
              +
              +/**
              + * HTML view for CyberChef responsible for building the web page and dealing with all user
              + * interactions.
              + *
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @constructor
              + * @param {CatConf[]} categories - The list of categories and operations to be populated.
              + * @param {Object.<string, OpConf>} operations - The list of operation configuration objects.
              + * @param {String[]} default_favourites - A list of default favourite operations.
              + * @param {Object} options - Default setting for app options.
              + */
              +var HTMLApp = function(categories, operations, default_favourites, default_options) {
              +    this.categories  = categories;
              +    this.operations  = operations;
              +    this.dfavourites = default_favourites;
              +    this.doptions    = default_options;
              +    this.options     = Utils.extend({}, default_options);
              +    
              +    this.chef        = new Chef();
              +    this.manager     = new Manager(this);
              +    
              +    this.auto_bake_  = false;
              +    this.progress    = 0;
              +    this.ing_id      = 0;
              +    
              +    window.chef      = this.chef;
              +};
              +
              +
              +/**
              + * This function sets up the stage and creates listeners for all events.
              + *
              + * @fires Manager#appstart
              + */
              +HTMLApp.prototype.setup = function() {
              +    document.dispatchEvent(this.manager.appstart);
              +    this.initialise_splitter();
              +    this.load_local_storage();
              +    this.populate_operations_list();
              +    this.manager.setup();
              +    this.reset_layout();
              +    this.set_compile_message();
              +    this.load_URI_params();
              +};
              +
              +
              +/**
              + * An error handler for displaying the error to the user.
              + *
              + * @param {Error} err
              + */
              +HTMLApp.prototype.handle_error = function(err) {
              +    console.error(err);
              +    var msg = err.display_str || err.toString();
              +    this.alert(msg, "danger", this.options.error_timeout, !this.options.show_errors);
              +};
              +
              +
              +/**
              + * Calls the Chef to bake the current input using the current recipe.
              + *
              + * @param {boolean} [step] - Set to true if we should only execute one operation instead of the
              + *   whole recipe.
              + */
              +HTMLApp.prototype.bake = function(step) {
              +    var response;
              +    
              +    try {
              +        response = this.chef.bake(
              +            this.get_input(),         // The user's input
              +            this.get_recipe_config(), // The configuration of the recipe
              +            this.options,             // Options set by the user
              +            this.progress,            // The current position in the recipe
              +            step                      // Whether or not to take one step or execute the whole recipe
              +        );
              +    } catch (err) {
              +        this.handle_error(err);
              +    } finally {
              +        if (!response) return;
              +        
              +        if (response.error) {
              +            this.handle_error(response.error);
              +        }
              +        this.options  = response.options;
              +        this.dish_str = response.type == "html" ? Utils.strip_html_tags(response.result, true) : response.result;
              +        this.progress = response.progress;
              +        this.manager.recipe.update_breakpoint_indicator(response.progress);
              +        this.manager.output.set(response.result, response.type, response.duration);
              +        
              +        // If baking took too long, disable auto-bake
              +        if (response.duration > this.options.auto_bake_threshold && this.auto_bake_) {
              +            this.manager.controls.set_auto_bake(false);
              +            this.alert("Baking took longer than " + this.options.auto_bake_threshold +
              +                "ms, Auto Bake has been disabled.", "warning", 5000);
              +        }
              +    }
              +};
              +
              +
              +/**
              + * Runs Auto Bake if it is set.
              + */
              +HTMLApp.prototype.auto_bake = function() {
              +    if (this.auto_bake_) {
              +        this.bake();
              +    }
              +};
              +
              +
              +/**
              + * Runs a silent bake forcing the browser to load and cache all the relevant JavaScript code needed
              + * to do a real bake.
              + *
              + * The output will not be modified (hence "silent" bake). This will only actually execute the
              + * recipe if auto-bake is enabled, otherwise it will just load the recipe, ingredients and dish.
              + *
              + * @returns {number} - The number of miliseconds it took to run the silent bake.
              + */
              +HTMLApp.prototype.silent_bake = function() {
              +    var start_time = new Date().getTime(),
              +        recipe_config = this.get_recipe_config();
              +    
              +    if (this.auto_bake_) {
              +        this.chef.silent_bake(recipe_config);
              +    }
              +    
              +    return new Date().getTime() - start_time;
              +};
              +
              +
              +/**
              + * Gets the user's input data.
              + *
              + * @returns {string}
              + */
              +HTMLApp.prototype.get_input = function() {
              +    var input = this.manager.input.get();
              +    
              +    // Save to session storage in case we need to restore it later
              +    sessionStorage.setItem("input_length", input.length);
              +    sessionStorage.setItem("input", input);
              +    
              +    return input;
              +};
              +
              +
              +/**
              + * Sets the user's input data.
              + *
              + * @param {string} input - The string to set the input to
              + */
              +HTMLApp.prototype.set_input = function(input) {
              +    sessionStorage.setItem("input_length", input.length);
              +    sessionStorage.setItem("input", input);
              +    this.manager.input.set(input);
              +};
              +
              +
              +/**
              + * Populates the operations accordion list with the categories and operations specified in the
              + * view constructor.
              + *
              + * @fires Manager#oplistcreate
              + */
              +HTMLApp.prototype.populate_operations_list = function() {
              +    // Move edit button away before we overwrite it
              +    document.body.appendChild(document.getElementById("edit-favourites"));
              +    
              +    var html = "";
              +    
              +    for (var i = 0; i < this.categories.length; i++) {
              +        var cat_conf = this.categories[i],
              +            selected = i === 0,
              +            cat = new HTMLCategory(cat_conf.name, selected);
              +        
              +        for (var j = 0; j < cat_conf.ops.length; j++) {
              +            var op_name = cat_conf.ops[j],
              +                op = new HTMLOperation(op_name, this.operations[op_name], this, this.manager);
              +            cat.add_operation(op);
              +        }
              +        
              +        html += cat.to_html();
              +    }
              +    
              +    document.getElementById("categories").innerHTML = html;
              +    
              +    var op_lists = document.querySelectorAll("#categories .op_list");
              +    
              +    for (i = 0; i < op_lists.length; i++) {
              +        op_lists[i].dispatchEvent(this.manager.oplistcreate);
              +    }
              +    
              +    // Add edit button to first category (Favourites)
              +    document.querySelector("#categories a").appendChild(document.getElementById("edit-favourites"));
              +};
              +
              +
              +/**
              + * Sets up the adjustable splitter to allow the user to resize areas of the page.
              + */
              +HTMLApp.prototype.initialise_splitter = function() {
              +    Split(["#operations", "#recipe", "#IO"], {
              +        sizes: [20, 30, 50],
              +        minSize: [240, 325, 500],
              +        gutterSize: 4,
              +        onDrag: this.manager.controls.adjust_width.bind(this.manager.controls)
              +    });
              +    
              +    Split(["#input", "#output"], {
              +        direction: "vertical",
              +        gutterSize: 4,
              +    });
              +    
              +    this.reset_layout();
              +};
              +
              +
              +/**
              + * Loads the information previously saved to the HTML5 local storage object so that user options
              + * and favourites can be restored.
              + */
              +HTMLApp.prototype.load_local_storage = function() {
              +    // Load options
              +    var l_options;
              +    if (localStorage.options !== undefined) {
              +        l_options = JSON.parse(localStorage.options);
              +    }
              +    this.manager.options.load(l_options);
              +    
              +    // Load favourites
              +    this.load_favourites();
              +};
              +
              +
              +/**
              + * Loads the user's favourite operations from the HTML5 local storage object and populates the
              + * Favourites category with them.
              + * If the user currently has no saved favourites, the defaults from the view constructor are used.
              + */
              +HTMLApp.prototype.load_favourites = function() {
              +    var favourites = localStorage.favourites &&
              +        localStorage.favourites.length > 2 ?
              +        JSON.parse(localStorage.favourites) :
              +        this.dfavourites;
              +        
              +    favourites = this.valid_favourites(favourites);
              +    this.save_favourites(favourites);
              +    
              +    var fav_cat = this.categories.filter(function(c) {
              +        return c.name == "Favourites";
              +    })[0];
              +    
              +    if (fav_cat) {
              +        fav_cat.ops = favourites;
              +    } else {
              +        this.categories.unshift({
              +            name: "Favourites",
              +            ops: favourites
              +        });
              +    }
              +};
              +
              +
              +/**
              + * Filters the list of favourite operations that the user had stored and removes any that are no
              + * longer available. The user is notified if this is the case.
              + 
              + * @param {string[]} favourites - A list of the user's favourite operations
              + * @returns {string[]} A list of the valid favourites
              + */
              +HTMLApp.prototype.valid_favourites = function(favourites) {
              +    var valid_favs = [];
              +    for (var i = 0; i < favourites.length; i++) {
              +        if (this.operations.hasOwnProperty(favourites[i])) {
              +            valid_favs.push(favourites[i]);
              +        } else {
              +            this.alert("The operation \"" + favourites[i] + "\" is no longer " +
              +                "available. It has been removed from your favourites.", "info");
              +        }
              +    }
              +    return valid_favs;
              +};
              +
              +
              +/**
              + * Saves a list of favourite operations to the HTML5 local storage object.
              + *
              + * @param {string[]} favourites - A list of the user's favourite operations
              + */
              +HTMLApp.prototype.save_favourites = function(favourites) {
              +    localStorage.setItem("favourites", JSON.stringify(this.valid_favourites(favourites)));
              +};
              +
              +
              +/**
              + * Resets favourite operations back to the default as specified in the view constructor and
              + * refreshes the operation list.
              + */
              +HTMLApp.prototype.reset_favourites = function() {
              +    this.save_favourites(this.dfavourites);
              +    this.load_favourites();
              +    this.populate_operations_list();
              +    this.manager.recipe.initialise_operation_drag_n_drop();
              +};
              +
              +
              +/**
              + * Adds an operation to the user's favourites.
              + *
              + * @param {string} name - The name of the operation
              + */
              +HTMLApp.prototype.add_favourite = function(name) {
              +    var favourites = JSON.parse(localStorage.favourites);
              +
              +    if (favourites.indexOf(name) >= 0) {
              +        this.alert("'" + name + "' is already in your favourites", "info", 2000);
              +        return;
              +    }
              +    
              +    favourites.push(name);
              +    this.save_favourites(favourites);
              +    this.load_favourites();
              +    this.populate_operations_list();
              +    this.manager.recipe.initialise_operation_drag_n_drop();
              +};
              +
              +
              +/**
              + * Checks for input and recipe in the URI parameters and loads them if present.
              + */
              +HTMLApp.prototype.load_URI_params = function() {
              +    // Load query string from URI
              +    this.query_string = (function(a) {
              +        if (a === "") return {};
              +        var b = {};
              +        for (var i = 0; i < a.length; i++) {
              +            var p = a[i].split('=');
              +            if (p.length != 2) {
              +                b[a[i]] = true;
              +            } else {
              +                b[p[0]] = decodeURIComponent(p[1].replace(/\+/g, " "));
              +            }
              +        }
              +        return b;
              +    })(window.location.search.substr(1).split('&'));
              +    
              +    // Turn off auto-bake while loading
              +    var auto_bake_val = this.auto_bake_;
              +    this.auto_bake_ = false;
              +    
              +    // Read in recipe from query string
              +    if (this.query_string.recipe) {
              +        try {
              +            var recipe_config = JSON.parse(this.query_string.recipe);
              +            this.set_recipe_config(recipe_config);
              +        } catch(err) {}
              +    } else if (this.query_string.op) {
              +        // If there's no recipe, look for single operations
              +        this.manager.recipe.clear_recipe();
              +        try {
              +            this.manager.recipe.add_operation(this.query_string.op);
              +        } catch(err) {
              +            // If no exact match, search for nearest match and add that
              +            var matched_ops = this.manager.ops.filter_operations(this.query_string.op, false);
              +            if (matched_ops.length) {
              +                this.manager.recipe.add_operation(matched_ops[0].name);
              +            }
              +            
              +            // Populate search with the string
              +            var search = document.getElementById("search");
              +            
              +            search.value = this.query_string.op;
              +            search.dispatchEvent(new Event("search"));
              +        }
              +    }
              +    
              +    // Read in input data from query string
              +    if (this.query_string.input) {
              +        try {
              +            var input_data = Utils.from_base64(this.query_string.input);
              +            this.set_input(input_data);
              +        } catch(err) {}
              +    }
              +    
              +    // Restore auto-bake state
              +    this.auto_bake_ = auto_bake_val;
              +    this.auto_bake();
              +};
              +
              +
              +/**
              + * Returns the next ingredient ID and increments it for next time.
              + *
              + * @returns {number}
              + */
              +HTMLApp.prototype.next_ing_id = function() {
              +    return this.ing_id++;
              +};
              +
              +
              +/**
              + * Gets the current recipe configuration.
              + *
              + * @returns {Object[]}
              + */
              +HTMLApp.prototype.get_recipe_config = function() {
              +    var recipe_config = this.manager.recipe.get_config();
              +    sessionStorage.setItem("recipe_config", JSON.stringify(recipe_config));
              +    return recipe_config;
              +};
              +
              +
              +/**
              + * Given a recipe configuration, sets the recipe to that configuration.
              + *
              + * @param {Object[]} recipe_config - The recipe configuration
              + */
              +HTMLApp.prototype.set_recipe_config = function(recipe_config) {
              +    sessionStorage.setItem("recipe_config", JSON.stringify(recipe_config));
              +    document.getElementById("rec_list").innerHTML = null;
              +    
              +    for (var i = 0; i < recipe_config.length; i++) {
              +        var item = this.manager.recipe.add_operation(recipe_config[i].op);
              +        
              +        // Populate arguments
              +        var args = item.querySelectorAll(".arg");
              +        for (var j = 0; j < args.length; j++) {
              +            if (args[j].getAttribute("type") == "checkbox") {
              +                // checkbox
              +                args[j].checked = recipe_config[i].args[j];
              +            } else if (args[j].classList.contains("toggle-string")) {
              +                // toggle_string
              +                args[j].value = recipe_config[i].args[j].string;
              +                args[j].previousSibling.children[0].innerHTML = recipe_config[i].args[j].option +
              +                    " <span class='caret'></span>";
              +            } else {
              +                // all others
              +                args[j].value = recipe_config[i].args[j];
              +            }
              +        }
              +        
              +        // Set disabled and breakpoint
              +        if (recipe_config[i].disabled) {
              +            item.querySelector(".disable-icon").click();
              +        }
              +        if (recipe_config[i].breakpoint) {
              +            item.querySelector(".breakpoint").click();
              +        }
              +        
              +        this.progress = 0;
              +    }
              +};
              +
              +
              +/**
              + * Resets the splitter positions to default.
              + */
              +HTMLApp.prototype.reset_layout = function() {
              +    document.getElementById("operations").style.width = "calc(20% - 2px)";
              +    document.getElementById("recipe").style.width = "calc(30% - 4px)";
              +    document.getElementById("IO").style.width = "calc(50% - 2px)";
              +    document.getElementById("input").style.height = "calc(50% - 2px)";
              +    document.getElementById("output").style.height = "calc(50% - 2px)";
              +    
              +    this.manager.controls.adjust_width();
              +};
              +
              +
              +/**
              + * Sets the compile message.
              + */
              +HTMLApp.prototype.set_compile_message = function() {
              +    // Display time since last build and compile message
              +    var now = new Date(),
              +        time_since_compile = Utils.fuzzy_time(now.getTime() - window.compile_time),
              +        compile_info = "<span style=\"font-weight: normal\">Last build: " +
              +            time_since_compile.substr(0,1).toUpperCase() + time_since_compile.substr(1) + " ago";
              +            
              +    if (window.compile_message !== "") {
              +        compile_info += " - " + window.compile_message;
              +    }
              +    
              +    compile_info += "</span>";
              +    document.getElementById("notice").innerHTML = compile_info;
              +};
              +
              +
              +/**
              + * Pops up a message to the user and writes it to the console log.
              + *
              + * @param {string} str - The message to display (HTML supported)
              + * @param {string} style - The colour of the popup
              + *     "danger"  = red
              + *     "warning" = amber
              + *     "info"    = blue
              + *     "success" = green
              + * @param {number} timeout - The number of milliseconds before the popup closes automatically
              + *     0 for never (until the user closes it)
              + * @param {boolean} [silent=false] - Don't show the message in the popup, only print it to the
              + *     console
              + *
              + * @example
              + * // Pops up a red box with the message "[current time] Error: Something has gone wrong!"
              + * // that will need to be dismissed by the user.
              + * this.alert("Error: Something has gone wrong!", "danger", 0);
              + *
              + * // Pops up a blue information box with the message "[current time] Happy Christmas!"
              + * // that will disappear after 5 seconds.
              + * this.alert("Happy Christmas!", "info", 5000);
              + */
              +HTMLApp.prototype.alert = function(str, style, timeout, silent) {
              +    var time = new Date();
              +    
              +    console.log("[" + time.toLocaleString() + "] " + str);
              +    if (silent) return;
              +    
              +    style = style || "danger";
              +    timeout = timeout || 0;
              +    
              +    var alert_el = document.getElementById("alert"),
              +        alert_content = document.getElementById("alert-content");
              +    
              +    alert_el.classList.remove("alert-danger");
              +    alert_el.classList.remove("alert-warning");
              +    alert_el.classList.remove("alert-info");
              +    alert_el.classList.remove("alert-success");
              +    alert_el.classList.add("alert-" + style);
              +    
              +    // If the box hasn't been closed, append to it rather than replacing
              +    if (alert_el.style.display == "block") {
              +        alert_content.innerHTML += 
              +            "<br><br>[" + time.toLocaleTimeString() + "] " + str;
              +    } else {
              +        alert_content.innerHTML =
              +            "[" + time.toLocaleTimeString() + "] " + str;
              +    }
              +    
              +    // Stop the animation if it is in progress
              +    $("#alert").stop();
              +    alert_el.style.display = "block";
              +    alert_el.style.opacity = 1;
              +    
              +    if (timeout > 0) {
              +        clearTimeout(this.alert_timeout);
              +        this.alert_timeout = setTimeout(function(){
              +            $("#alert").slideUp(100);
              +        }, timeout);
              +    }
              +};
              +
              +
              +/**
              + * Pops up a box asking the user a question and sending the answer to a specified callback function.
              + *
              + * @param {string} title - The title of the box
              + * @param {string} body - The question (HTML supported)
              + * @param {function} callback - A function accepting one boolean argument which handles the
              + *   response e.g. function(answer) {...}
              + * @param {Object} [scope=this] - The object to bind to the callback function
              + *
              + * @example
              + * // Pops up a box asking if the user would like a cookie. Prints the answer to the console.
              + * this.confirm("Question", "Would you like a cookie?", function(answer) {console.log(answer);});
              + */
              +HTMLApp.prototype.confirm = function(title, body, callback, scope) {
              +    scope = scope || this;
              +    document.getElementById("confirm-title").innerHTML = title;
              +    document.getElementById("confirm-body").innerHTML = body;
              +    document.getElementById("confirm-modal").style.display = "block";
              +    
              +    this.confirm_closed = false;
              +    $("#confirm-modal").modal()
              +        .one("show.bs.modal", function(e) {
              +            this.confirm_closed = false;
              +        }.bind(this))
              +        .one("click", "#confirm-yes", function() {
              +            this.confirm_closed = true;
              +            callback.bind(scope)(true);
              +            $("#confirm-modal").modal("hide");
              +        }.bind(this))
              +        .one("hide.bs.modal", function(e) {
              +            if (!this.confirm_closed)
              +                callback.bind(scope)(false);
              +            this.confirm_closed = true;
              +        }.bind(this));
              +};
              +
              +
              +/**
              + * Handler for the alert close button click event.
              + * Closes the alert box.
              + */
              +HTMLApp.prototype.alert_close_click = function() {
              +    document.getElementById("alert").style.display = "none";
              +};
              +
              +
              +/**
              + * Handler for CyerChef statechange events.
              + * Fires whenever the input or recipe changes in any way.
              + *
              + * @listens Manager#statechange
              + * @param {event} e
              + */
              +HTMLApp.prototype.state_change = function(e) {
              +    this.auto_bake();
              +    
              +    // Update the current history state (not creating a new one)
              +    if (this.options.update_url) {
              +        this.last_state_url = this.manager.controls.generate_state_url(true, true);
              +        window.history.replaceState({}, "CyberChef", this.last_state_url);
              +    }
              +};
              +
              +
              +/**
              + * Handler for the history popstate event.
              + * Reloads parameters from the URL.
              + *
              + * @param {event} e
              + */
              +HTMLApp.prototype.pop_state = function(e) {
              +    if (window.location.href.split("#")[0] !== this.last_state_url) {
              +        this.load_URI_params();
              +    }
              +};
              +
              +
              +/**
              + * Function to call an external API from this view.
              + */
              +HTMLApp.prototype.call_api = function(url, type, data, data_type, content_type) {
              +    type = type || "POST";
              +    data = data || {};
              +    data_type = data_type || undefined;
              +    content_type = content_type || "application/json";
              +    
              +    var response = null,
              +        success = false;
              +    
              +    $.ajax({
              +        url: url,
              +        async: false,
              +        type: type,
              +        data: data,
              +        dataType: data_type,
              +        contentType: content_type,
              +        success: function(data) {
              +            success = true;
              +            response = data;
              +        },
              +        error: function(data) {
              +            success = false;
              +            response = data;
              +        },
              +    });
              +    
              +    return {
              +        success: success,
              +        response: response
              +    };
              +};
              diff --git a/src/js/views/html/HTMLCategory.js b/src/js/views/html/HTMLCategory.js
              new file mode 100755
              index 00000000..83909d50
              --- /dev/null
              +++ b/src/js/views/html/HTMLCategory.js
              @@ -0,0 +1,50 @@
              +/**
              + * Object to handle the creation of operation categories.
              + *
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @constructor
              + * @param {string} name - The name of the category.
              + * @param {boolean} selected - Whether this category is pre-selected or not.
              + */
              +var HTMLCategory = function(name, selected) {
              +    this.name = name;
              +    this.selected = selected;
              +    this.op_list = [];
              +};
              +
              +
              +/**
              + * Adds an operation to this category.
              + *
              + * @param {HTMLOperation} operation - The operation to add.
              + */
              +HTMLCategory.prototype.add_operation = function(operation) {
              +    this.op_list.push(operation);
              +};
              +
              +
              +/**
              + * Renders the category and all operations within it in HTML.
              + *
              + * @returns {string}
              + */
              +HTMLCategory.prototype.to_html = function() {
              +    var cat_name = "cat" + this.name.replace(/[\s/-:_]/g, "");
              +    var html = "<div class='panel category'>\
              +        <a class='category-title' data-toggle='collapse'\
              +            data-parent='#categories' href='#" + cat_name + "'>\
              +            " + this.name + "\
              +        </a>\
              +        <div id='" + cat_name + "' class='panel-collapse collapse\
              +        " + (this.selected ? " in" : "") + "'><ul class='op_list'>";
              +    
              +    for (var i = 0; i < this.op_list.length; i++) {
              +        html += this.op_list[i].to_stub_html();
              +    }
              +    
              +    html += "</ul></div></div>";
              +    return html;
              +};
              diff --git a/src/js/views/html/HTMLIngredient.js b/src/js/views/html/HTMLIngredient.js
              new file mode 100755
              index 00000000..b5a28259
              --- /dev/null
              +++ b/src/js/views/html/HTMLIngredient.js
              @@ -0,0 +1,212 @@
              +/**
              + * Object to handle the creation of operation ingredients.
              + *
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @constructor
              + * @param {Object} config - The configuration object for this ingredient.
              + * @param {HTMLApp} app - The main view object for CyberChef.
              + * @param {Manager} manager - The CyberChef event manager.
              + */
              +var HTMLIngredient = function(config, app, manager) {
              +    this.app = app;
              +    this.manager = manager;
              +    
              +    this.name = config.name;
              +    this.type = config.type;
              +    this.value = config.value;
              +    this.disabled = config.disabled || false;
              +    this.disable_args = config.disable_args || false;
              +    this.placeholder = config.placeholder || false;
              +    this.target = config.target;
              +    this.toggle_values = config.toggle_values;
              +    this.id = "ing-" + this.app.next_ing_id();
              +};
              +
              +
              +/**
              + * Renders the ingredient in HTML.
              + *
              + * @returns {string}
              + */
              +HTMLIngredient.prototype.to_html = function() {
              +    var inline = (this.type == "boolean" ||
              +                  this.type == "number" ||
              +                  this.type == "option" ||
              +                  this.type == "short_string" ||
              +                  this.type == "binary_short_string"),
              +        html = inline ? "" : "<div class='clearfix'>&nbsp;</div>",
              +        i, m;
              +    
              +    html += "<div class='arg-group" + (inline ? " inline-args" : "") +
              +        (this.type == "text" ? " arg-group-text" : "") + "'><label class='arg-label' for='" +
              +        this.id + "'>" + this.name + "</label>";
              +    
              +    switch (this.type) {
              +        case "string":
              +        case "binary_string":
              +        case "byte_array":
              +            html += "<input type='text' id='" + this.id + "' class='arg arg-input' arg_name='" +
              +                this.name + "' value='" + this.value + "'" +
              +                (this.disabled ? " disabled='disabled'" : "") +
              +                (this.placeholder ? " placeholder='" + this.placeholder + "'" : "") + ">";
              +            break;
              +        case "short_string":
              +        case "binary_short_string":
              +            html += "<input type='text' id='" + this.id +
              +                "'class='arg arg-input short-string' arg_name='" + this.name + "'value='" +
              +                this.value + "'" + (this.disabled ? " disabled='disabled'" : "") +
              +                (this.placeholder ? " placeholder='" + this.placeholder + "'" : "") + ">";
              +            break;
              +        case "toggle_string":
              +            html += "<div class='input-group'><div class='input-group-btn'>\
              +                <button type='button' class='btn btn-default dropdown-toggle' data-toggle='dropdown'\
              +                aria-haspopup='true' aria-expanded='false'" +
              +                (this.disabled ? " disabled='disabled'" : "") + ">" + this.toggle_values[0] +
              +                " <span class='caret'></span></button><ul class='dropdown-menu'>";
              +            for (i = 0; i < this.toggle_values.length; i++) {
              +                html += "<li><a href='#'>" + this.toggle_values[i] + "</a></li>";
              +            }
              +            html += "</ul></div><input type='text' class='arg arg-input toggle-string'" +
              +                (this.disabled ? " disabled='disabled'" : "") +
              +                (this.placeholder ? " placeholder='" + this.placeholder + "'" : "") + "></div>";
              +            break;
              +        case "number":
              +            html += "<input type='number' id='" + this.id + "'class='arg arg-input' arg_name='" +
              +                this.name + "'value='" + this.value + "'" +
              +                (this.disabled ? " disabled='disabled'" : "") +
              +                (this.placeholder ? " placeholder='" + this.placeholder + "'" : "") + ">";
              +            break;
              +        case "boolean":
              +            html += "<input type='checkbox' id='" + this.id + "'class='arg' arg_name='" +
              +                this.name + "'" + (this.value ? " checked='checked' " : "") +
              +                (this.disabled ? " disabled='disabled'" : "") + ">";
              +            
              +            if (this.disable_args) {
              +                this.manager.add_dynamic_listener("#" + this.id, "click", this.toggle_disable_args, this);
              +            }
              +            break;
              +        case "option":
              +            html += "<select class='arg' id='" + this.id + "'arg_name='" + this.name + "'" +
              +                (this.disabled ? " disabled='disabled'" : "") + ">";
              +            for (i = 0; i < this.value.length; i++) {
              +                if (!!(m = this.value[i].match(/\[([a-z0-9 -()^]+)\]/i))) {
              +                    html += "<optgroup label='" + m[1] + "'>";
              +                } else if (!!(m = this.value[i].match(/\[\/([a-z0-9 -()^]+)\]/i))) {
              +                    html += "</optgroup>";
              +                } else {
              +                    html += "<option>" + this.value[i] + "</option>";
              +                }
              +            }
              +            html += "</select>";
              +            break;
              +        case "populate_option":
              +            html += "<select class='arg' id='" + this.id + "'arg_name='" + this.name + "'" +
              +                (this.disabled ? " disabled='disabled'" : "") + ">";
              +            for (i = 0; i < this.value.length; i++) {
              +                if (!!(m = this.value[i].name.match(/\[([a-z0-9 -()^]+)\]/i))) {
              +                    html += "<optgroup label='" + m[1] + "'>";
              +                } else if (!!(m = this.value[i].name.match(/\[\/([a-z0-9 -()^]+)\]/i))) {
              +                    html += "</optgroup>";
              +                } else {
              +                    html += "<option populate-value='" + this.value[i].value + "'>" +
              +                        this.value[i].name + "</option>";
              +                }
              +            }
              +            html += "</select>";
              +            
              +            this.manager.add_dynamic_listener("#" + this.id, "change", this.populate_option_change, this);
              +            break;
              +        case "editable_option":
              +            html += "<div class='editable-option'>";
              +            html += "<select class='editable-option-select' id='sel-" + this.id + "'" +
              +                (this.disabled ? " disabled='disabled'" : "") + ">";
              +            for (i = 0; i < this.value.length; i++) {
              +                html += "<option value='" + this.value[i].value + "'>" + this.value[i].name + "</option>";
              +            }
              +            html += "</select>";
              +            html += "<input class='arg arg-input editable-option-input' id='" + this.id +
              +                "'arg_name='" + this.name + "'" + " value='" + this.value[0].value + "'" +
              +                (this.disabled ? " disabled='disabled'" : "") +
              +                (this.placeholder ? " placeholder='" + this.placeholder + "'" : "") + ">";
              +            html += "</div>";
              +            
              +            
              +            this.manager.add_dynamic_listener("#sel-" + this.id, "change", this.editable_option_change, this);
              +            break;
              +        case "text":
              +            html += "<textarea id='" + this.id + "' class='arg' arg_name='" +
              +                this.name + "'" + (this.disabled ? " disabled='disabled'" : "") +
              +                (this.placeholder ? " placeholder='" + this.placeholder + "'" : "") + ">" +
              +                this.value + "</textarea>";
              +            break;
              +        default:
              +            break;
              +    }
              +    html += "</div>";
              +    
              +    return html;
              +};
              +
              +
              +/**
              + * Handler for argument disable toggle.
              + * Toggles disabled state for all arguments in the disable_args list for this ingredient.
              + *
              + * @param {event} e
              + */
              +HTMLIngredient.prototype.toggle_disable_args = function(e) {
              +    var el = e.target,
              +        op = el.parentNode.parentNode,
              +        args = op.querySelectorAll(".arg-group"),
              +        els;
              +        
              +    for (var i = 0; i < this.disable_args.length; i++) {
              +        els = args[this.disable_args[i]].querySelectorAll("input, select, button");
              +        
              +        for (var j = 0; j < els.length; j++) {
              +            if (els[j].getAttribute("disabled")) {
              +                els[j].removeAttribute("disabled");
              +            } else {
              +                els[j].setAttribute("disabled", "disabled");
              +            }
              +        }
              +    }
              +    
              +    this.manager.recipe.ing_change();
              +};
              +
              +
              +/**
              + * Handler for populate option changes.
              + * Populates the relevant argument with the specified value.
              + *
              + * @param {event} e
              + */
              +HTMLIngredient.prototype.populate_option_change = function(e) {
              +    var el = e.target,
              +        op = el.parentNode.parentNode,
              +        target = op.querySelectorAll(".arg-group")[this.target].querySelector("input, select, textarea");
              +
              +    target.value = el.childNodes[el.selectedIndex].getAttribute("populate-value");
              +    
              +    this.manager.recipe.ing_change();
              +};
              +
              +
              +/**
              + * Handler for editable option changes.
              + * Populates the input box with the selected value.
              + *
              + * @param {event} e
              + */
              +HTMLIngredient.prototype.editable_option_change = function(e) {
              +    var select = e.target,
              +        input = select.nextSibling;
              +
              +    input.value = select.childNodes[select.selectedIndex].value;
              +    
              +    this.manager.recipe.ing_change();
              +};
              diff --git a/src/js/views/html/HTMLOperation.js b/src/js/views/html/HTMLOperation.js
              new file mode 100755
              index 00000000..1bf9849d
              --- /dev/null
              +++ b/src/js/views/html/HTMLOperation.js
              @@ -0,0 +1,114 @@
              +/**
              + * Object to handle the creation of operations.
              + *
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @constructor
              + * @param {string} name - The name of the operation.
              + * @param {Object} config - The configuration object for this operation.
              + * @param {HTMLApp} app - The main view object for CyberChef.
              + * @param {Manager} manager - The CyberChef event manager.
              + */
              +var HTMLOperation = function(name, config, app, manager) {
              +    this.app         = app;
              +    this.manager     = manager;
              +    
              +    this.name        = name;
              +    this.description = config.description;
              +    this.manual_bake = config.manual_bake || false;
              +    this.config      = config;
              +    this.ing_list    = [];
              +    
              +    for (var i = 0; i < config.args.length; i++) {
              +        var ing = new HTMLIngredient(config.args[i], this.app, this.manager);
              +        this.ing_list.push(ing);
              +    }
              +};
              +
              +
              +/**
              + * @constant
              + */
              +HTMLOperation.INFO_ICON = "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAByElEQVR4XqVTzWoaYRQ9KZJmoVaS1J1QiYTIuOgqi9lEugguQhYhdGs3hTyAi0CWJTvJIks30ZBNsimUtlqkVLoQCuJsphRriyFjabWtEyf/Rv3iWcwwymTlgQuH851z5hu43wRGkEwmXwCIA4hiGAUAmUQikQbhEHwyGCWVSglVVUW73RYmyKnxjB56ncJ6NpsVxHGrI/ZLuniVb3DIqQmCHnrNkgcggNeSJPlisRgyJR2b737j/TcDsQUPwv6H5NR4BnroZcb6Z16N2PvyX6yna9Z8qp6JQ0Uf0ughmGHWBSAuyzJqrQ7eqKewY/dzE363C71e39LoWQq5wUwul4uzIBoIBHD01RgyrkZ8eDbvwUWnj623v2DHx4qB51IAzLIAXq8XP/7W0bUVVJtXWIk8wvlN364TA+/1IDMLwmWK/Hq3axmhaBdoGLeklm73ElaBYRgIzkyifHIOO4QQJKM3oJcZq6CgaVp0OTyHw9K/kQI4FiyHfdC0n2CWe5ApFosIPZ7C2tNpXpcDOehGyD/FIbd0euhlhllzFxRzC3fydbG4XRYbB9/tQ41n9m1U7l3lyp9LkfygiZeZCoecmtMqj/+Yxn7Od3v0j50qCO3zAAAAAElFTkSuQmCC";
              +/**
              + * @constant
              + */
              +HTMLOperation.REMOVE_ICON = "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABwklEQVR42qRTPU8CQRB9K2CCMRJ6NTQajOUaqfxIbLCRghhjQixosLAgFNBQ3l8wsabxLxBJbCyVUBiMCVQEQkOEKBbCnefM3p4eohWXzM3uvHlv52b2hG3bmOWZw4yPn1/XQkCQ9wFxcgZZ0QLKpifpN8Z1n1L13griBBjHhYK0nMT4b+wom53ClAAFQacZJ/m8rNfrSOZy0vxJjPP6IJ2WzWYTO6mUwiwtILiJJSHUKVSWkchkZK1WQzQaxU2pVGUglkjIbreLUCiEx0qlStlFCpfPiPstYDtVKJH9ZFI2Gw1FGA6H6LTbCAaDeGu1FJl6UuYjpwTGzucokZW1NfnS66kyfT4fXns9RaZmlgNcuhZQU+jowLzuOK/HgwEW3E5ZlhLXVWKk11P3wNYNWw+HZdA0sUgx1zjGmD05nckx0ilGjBJdUq3fr7K5e8bGf43RdL7fOPSQb4lI8SLbrUfkUIuY32VTI1bJn5BqDnh4Dodt9ryPUDzyD7aquWoKQohl2i9sAbubwPkTcHkP3FHsg+yT+7sN7G0AF3Xg6sHB3onbdgWWKBDQg/BcTuVt51dQA/JrnIcyIu6rmPV3/hJgACPc0BMEYTg+AAAAAElFTkSuQmCC";
              +
              +
              +/**
              + * Renders the operation in HTML as a stub operation with no ingredients.
              + *
              + * @returns {string}
              + */
              +HTMLOperation.prototype.to_stub_html = function(remove_icon) {
              +    var html = "<li class='operation'";
              +    
              +    if (this.description) {
              +        html += " data-container='body' data-toggle='popover' data-placement='auto right'\
              +            data-content=\"" + this.description + "\" data-html='true' data-trigger='hover'";
              +    }
              +    
              +    html += ">" + this.name;
              +    
              +    if (remove_icon) {
              +        html += "<img src='data:image/png;base64," + HTMLOperation.REMOVE_ICON +
              +            "' class='op-icon remove-icon'>";
              +    }
              +    
              +    if (this.description) {
              +        html += "<img src='data:image/png;base64," + HTMLOperation.INFO_ICON + "' class='op-icon'>";
              +    }
              +    
              +    html += "</li>";
              +    
              +    return html;
              +};
              +
              +
              +/**
              + * Renders the operation in HTML as a full operation with ingredients.
              + *
              + * @returns {string}
              + */
              +HTMLOperation.prototype.to_full_html = function() {
              +    var html = "<div class='arg-title'>" + this.name + "</div>";
              +
              +    for (var i = 0; i < this.ing_list.length; i++) {
              +        html += this.ing_list[i].to_html();
              +    }
              +    
              +    html += "<div class='recip-icons'>\
              +        <div class='breakpoint' title='Set breakpoint' break='false'></div>\
              +        <div class='disable-icon recip-icon' title='Disable operation'\
              +            disabled='false'></div>";
              +    
              +    html += "</div>\
              +        <div class='clearfix'>&nbsp;</div>";
              +        
              +    return html;
              +};
              +
              +
              +/**
              + * Highlights the searched string in the name and description of the operation.
              + *
              + * @param {string} search_str
              + * @param {number} name_pos - The position of the search string in the operation name
              + * @param {number} desc_pos - The position of the search string in the operation description
              + */
              +HTMLOperation.prototype.highlight_search_string = function(search_str, name_pos, desc_pos) {
              +    if (name_pos >= 0) {
              +        this.name = this.name.slice(0, name_pos) + "<b><u>" +
              +            this.name.slice(name_pos, name_pos + search_str.length) + "</u></b>" +
              +            this.name.slice(name_pos + search_str.length);
              +    }
              +    
              +    if (this.description && desc_pos >= 0) {
              +        this.description = this.description.slice(0, desc_pos) + "<b><u>" +
              +            this.description.slice(desc_pos, desc_pos + search_str.length) + "</u></b>" +
              +            this.description.slice(desc_pos + search_str.length);
              +    }
              +};
              diff --git a/src/js/views/html/HighlighterWaiter.js b/src/js/views/html/HighlighterWaiter.js
              new file mode 100755
              index 00000000..da7d1c5f
              --- /dev/null
              +++ b/src/js/views/html/HighlighterWaiter.js
              @@ -0,0 +1,506 @@
              +/**
              + * Waiter to handle events related to highlighting in CyberChef.
              + *
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @constructor
              + * @param {HTMLApp} app - The main view object for CyberChef.
              + */
              +var HighlighterWaiter = function(app) {
              +    this.app = app;
              +    
              +    this.mouse_button_down = false;
              +    this.mouse_target = null;
              +};
              +
              +
              +/**
              + * HighlighterWaiter data type enum for the input.
              + * @readonly
              + * @enum
              + */
              +HighlighterWaiter.INPUT  = 0;
              +/**
              + * HighlighterWaiter data type enum for the output.
              + * @readonly
              + * @enum
              + */
              +HighlighterWaiter.OUTPUT = 1;
              +
              +
              +/**
              + * Determines if the current text selection is running backwards or forwards.
              + * StackOverflow answer id: 12652116
              + *
              + * @private
              + * @returns {boolean}
              + */
              +HighlighterWaiter.prototype._is_selection_backwards = function() {
              +    var backwards = false,
              +        sel = window.getSelection();
              +        
              +    if (!sel.isCollapsed) {
              +        var range = document.createRange();
              +        range.setStart(sel.anchorNode, sel.anchorOffset);
              +        range.setEnd(sel.focusNode, sel.focusOffset);
              +        backwards = range.collapsed;
              +        range.detach();
              +    }
              +    return backwards;
              +};
              +
              +
              +/**
              + * Calculates the text offset of a position in an HTML element, ignoring HTML tags.
              + *
              + * @private
              + * @param {element} node - The parent HTML node.
              + * @param {number} offset - The offset since the last HTML element.
              + * @returns {number}
              + */
              +HighlighterWaiter.prototype._get_output_html_offset = function(node, offset) {
              +    var sel = window.getSelection(),
              +        range = document.createRange();
              +        
              +    range.selectNodeContents(document.getElementById("output-html"));
              +    range.setEnd(node, offset);
              +    sel.removeAllRanges();
              +    sel.addRange(range);
              +    
              +    return sel.toString().length;
              +};
              +
              +
              +/**
              + * Gets the current selection offsets in the output HTML, ignoring HTML tags.
              + *
              + * @private
              + * @returns {Object} pos
              + * @returns {number} pos.start
              + * @returns {number} pos.end
              + */
              +HighlighterWaiter.prototype._get_output_html_selection_offsets = function() {
              +    var sel = window.getSelection(),
              +        range,
              +        start = 0,
              +        end = 0,
              +        backwards = false;
              +    
              +    if (sel.rangeCount) {
              +        range = sel.getRangeAt(sel.rangeCount - 1);
              +        backwards = this._is_selection_backwards();
              +        start = this._get_output_html_offset(range.startContainer, range.startOffset);
              +        end = this._get_output_html_offset(range.endContainer, range.endOffset);
              +        sel.removeAllRanges();
              +        sel.addRange(range);
              +        
              +        if (backwards) {
              +            // If selecting backwards, reverse the start and end offsets for the selection to
              +            // prevent deselecting as the drag continues.
              +            sel.collapseToEnd();
              +            sel.extend(sel.anchorNode, range.startOffset);
              +        }
              +    }
              +    
              +    return {
              +        start: start,
              +        end: end
              +    };
              +};
              +
              +
              +/**
              + * Handler for input scroll events.
              + * Scrolls the highlighter pane to match the input textarea position.
              + *
              + * @param {event} e
              + */
              +HighlighterWaiter.prototype.input_scroll = function(e) {
              +    var el = e.target;
              +    document.getElementById("input-highlighter").scrollTop = el.scrollTop;
              +    document.getElementById("input-highlighter").scrollLeft = el.scrollLeft;
              +};
              +
              +
              +/**
              + * Handler for output scroll events.
              + * Scrolls the highlighter pane to match the output textarea position.
              + *
              + * @param {event} e
              + */
              +HighlighterWaiter.prototype.output_scroll = function(e) {
              +    var el = e.target;
              +    document.getElementById("output-highlighter").scrollTop = el.scrollTop;
              +    document.getElementById("output-highlighter").scrollLeft = el.scrollLeft;
              +};
              +
              +
              +/**
              + * Handler for input mousedown events.
              + * Calculates the current selection info, and highlights the corresponding data in the output.
              + *
              + * @param {event} e
              + */
              +HighlighterWaiter.prototype.input_mousedown = function(e) {
              +    this.mouse_button_down = true;
              +    this.mouse_target = HighlighterWaiter.INPUT;
              +    this.remove_highlights();
              +    
              +    var el = e.target,
              +        start = el.selectionStart,
              +        end = el.selectionEnd;
              +    
              +    if (start !== 0 || end !== 0) {
              +        document.getElementById("input-selection-info").innerHTML = this.selection_info(start, end);
              +        this.highlight_output([{start: start, end: end}]);
              +    }
              +};
              +
              +
              +/**
              + * Handler for output mousedown events.
              + * Calculates the current selection info, and highlights the corresponding data in the input.
              + *
              + * @param {event} e
              + */
              +HighlighterWaiter.prototype.output_mousedown = function(e) {
              +    this.mouse_button_down = true;
              +    this.mouse_target = HighlighterWaiter.OUTPUT;
              +    this.remove_highlights();
              +    
              +    var el = e.target,
              +        start = el.selectionStart,
              +        end = el.selectionEnd;
              +    
              +    if (start !== 0 || end !== 0) {
              +        document.getElementById("output-selection-info").innerHTML = this.selection_info(start, end);
              +        this.highlight_input([{start: start, end: end}]);
              +    }
              +};
              +
              +
              +/**
              + * Handler for output HTML mousedown events.
              + * Calculates the current selection info.
              + *
              + * @param {event} e
              + */
              +HighlighterWaiter.prototype.output_html_mousedown = function(e) {
              +    this.mouse_button_down = true;
              +    this.mouse_target = HighlighterWaiter.OUTPUT;
              +    
              +    var sel = this._get_output_html_selection_offsets();
              +    if (sel.start !== 0 || sel.end !== 0) {
              +        document.getElementById("output-selection-info").innerHTML = this.selection_info(sel.start, sel.end);
              +    }
              +};
              +
              +
              +/**
              + * Handler for input mouseup events.
              + *
              + * @param {event} e
              + */
              +HighlighterWaiter.prototype.input_mouseup = function(e) {
              +    this.mouse_button_down = false;
              +};
              +
              +
              +/**
              + * Handler for output mouseup events.
              + *
              + * @param {event} e
              + */
              +HighlighterWaiter.prototype.output_mouseup = function(e) {
              +    this.mouse_button_down = false;
              +};
              +
              +
              +/**
              + * Handler for output HTML mouseup events.
              + *
              + * @param {event} e
              + */
              +HighlighterWaiter.prototype.output_html_mouseup = function(e) {
              +    this.mouse_button_down = false;
              +};
              +
              +
              +/**
              + * Handler for input mousemove events.
              + * Calculates the current selection info, and highlights the corresponding data in the output.
              + *
              + * @param {event} e
              + */
              +HighlighterWaiter.prototype.input_mousemove = function(e) {
              +    // Check that the left mouse button is pressed
              +    if (!this.mouse_button_down ||
              +        e.which != 1 ||
              +        this.mouse_target != HighlighterWaiter.INPUT)
              +        return;
              +    
              +    var el = e.target,
              +        start = el.selectionStart,
              +        end = el.selectionEnd;
              +
              +    if (start !== 0 || end !== 0) {
              +        document.getElementById("input-selection-info").innerHTML = this.selection_info(start, end);
              +        this.highlight_output([{start: start, end: end}]);
              +    }
              +};
              +
              +
              +/**
              + * Handler for output mousemove events.
              + * Calculates the current selection info, and highlights the corresponding data in the input.
              + *
              + * @param {event} e
              + */
              +HighlighterWaiter.prototype.output_mousemove = function(e) {
              +    // Check that the left mouse button is pressed
              +    if (!this.mouse_button_down ||
              +        e.which != 1 ||
              +        this.mouse_target != HighlighterWaiter.OUTPUT)
              +        return;
              +    
              +    var el = e.target,
              +        start = el.selectionStart,
              +        end = el.selectionEnd;
              +    
              +    if (start !== 0 || end !== 0) {
              +        document.getElementById("output-selection-info").innerHTML = this.selection_info(start, end);
              +        this.highlight_input([{start: start, end: end}]);
              +    }
              +};
              +
              +
              +/**
              + * Handler for output HTML mousemove events.
              + * Calculates the current selection info.
              + *
              + * @param {event} e
              + */
              +HighlighterWaiter.prototype.output_html_mousemove = function(e) {
              +    // Check that the left mouse button is pressed
              +    if (!this.mouse_button_down ||
              +        e.which != 1 ||
              +        this.mouse_target != HighlighterWaiter.OUTPUT)
              +        return;
              +    
              +    var sel = this._get_output_html_selection_offsets();
              +    if (sel.start !== 0 || sel.end !== 0) {
              +        document.getElementById("output-selection-info").innerHTML = this.selection_info(sel.start, sel.end);
              +    }
              +};
              +
              +
              +/**
              + * Given start and end offsets, writes the HTML for the selection info element with the correct
              + * padding.
              + *
              + * @param {number} start - The start offset.
              + * @param {number} end - The end offset.
              + * @returns {string}
              + */
              +HighlighterWaiter.prototype.selection_info = function(start, end) {
              +    var width = end.toString().length;
              +    width = width < 2 ? 2 : width;
              +    var start_str = Utils.pad(start.toString(), width, " ").replace(/ /g, "&nbsp;"),
              +        end_str   = Utils.pad(end.toString(), width, " ").replace(/ /g, "&nbsp;"),
              +        len_str   = Utils.pad((end-start).toString(), width, " ").replace(/ /g, "&nbsp;");
              +        
              +    return "start: " + start_str + "<br>end: " + end_str + "<br>length: " + len_str;
              +};
              +
              +
              +/**
              + * Removes highlighting and selection information.
              + */
              +HighlighterWaiter.prototype.remove_highlights = function() {
              +    document.getElementById("input-highlighter").innerHTML = "";
              +    document.getElementById("output-highlighter").innerHTML = "";
              +    document.getElementById("input-selection-info").innerHTML = "";
              +    document.getElementById("output-selection-info").innerHTML = "";
              +};
              +
              +
              +/**
              + * Generates a list of all the highlight functions assigned to operations in the recipe, if the 
              + * entire recipe supports highlighting.
              + *
              + * @returns {Object[]} highlights
              + * @returns {function} highlights[].f
              + * @returns {function} highlights[].b
              + * @returns {Object[]} highlights[].args
              + */
              +HighlighterWaiter.prototype.generate_highlight_list = function() {
              +    var recipe_config = this.app.get_recipe_config(),
              +        highlights = [];
              +    
              +    for (var i = 0; i < recipe_config.length; i++) {
              +        if (recipe_config[i].disabled) continue;
              +        
              +        // If any breakpoints are set, do not attempt to highlight
              +        if (recipe_config[i].breakpoint) return false;
              +        
              +        var op = this.app.operations[recipe_config[i].op];
              +        
              +        // If any of the operations do not support highlighting, fail immediately.
              +        if (op.highlight === false || op.highlight === undefined) return false;
              +        
              +        highlights.push({
              +            f: op.highlight,
              +            b: op.highlight_reverse,
              +            args: recipe_config[i].args
              +        });
              +    }
              +    
              +    return highlights;
              +};
              +
              +
              +/**
              + * Highlights the given offsets in the output.
              + * We will only highlight if:
              + *     - input hasn't changed since last bake
              + *     - last bake was a full bake
              + *     - all operations in the recipe support highlighting
              + *
              + * @param {Object} pos - The position object for the highlight.
              + * @param {number} pos.start - The start offset.
              + * @param {number} pos.end - The end offset.
              + */
              +HighlighterWaiter.prototype.highlight_output = function(pos) {
              +    var highlights = this.generate_highlight_list();
              +
              +    if (!highlights || !this.app.auto_bake_) {
              +        return false;
              +    }
              +
              +    for (var i = 0; i < highlights.length; i++) {
              +        // Remove multiple highlights before processing again
              +        pos = [pos[0]];
              +        
              +        if (typeof highlights[i].f == "function") {
              +            pos = highlights[i].f(pos, highlights[i].args);
              +        }
              +    }
              +    
              +    document.getElementById("output-selection-info").innerHTML = this.selection_info(pos[0].start, pos[0].end);
              +    this.highlight(
              +        document.getElementById("output-text"),
              +        document.getElementById("output-highlighter"),
              +        pos);
              +};
              +
              +
              +/**
              + * Highlights the given offsets in the input.
              + * We will only highlight if:
              + *     - input hasn't changed since last bake
              + *     - last bake was a full bake
              + *     - all operations in the recipe support highlighting
              + *
              + * @param {Object} pos - The position object for the highlight.
              + * @param {number} pos.start - The start offset.
              + * @param {number} pos.end - The end offset.
              + */
              +HighlighterWaiter.prototype.highlight_input = function(pos) {
              +    var highlights = this.generate_highlight_list();
              +    
              +    if (!highlights || !this.app.auto_bake_) {
              +        return false;
              +    }
              +
              +    for (var i = 0; i < highlights.length; i++) {
              +        // Remove multiple highlights before processing again
              +        pos = [pos[0]];
              +        
              +        if (typeof highlights[i].b == "function") {
              +            pos = highlights[i].b(pos, highlights[i].args);
              +        }
              +    }
              +    
              +    document.getElementById("input-selection-info").innerHTML = this.selection_info(pos[0].start, pos[0].end);
              +    this.highlight(
              +        document.getElementById("input-text"),
              +        document.getElementById("input-highlighter"),
              +        pos);
              +};
              +
              +
              +/**
              + * Adds the relevant HTML to the specified highlight element such that highlighting appears
              + * underneath the correct offset.
              + *
              + * @param {element} textarea - The input or output textarea.
              + * @param {element} highlighter - The input or output highlighter element.
              + * @param {Object} pos - The position object for the highlight.
              + * @param {number} pos.start - The start offset.
              + * @param {number} pos.end - The end offset.
              + */
              +HighlighterWaiter.prototype.highlight = function(textarea, highlighter, pos) {
              +    if (!this.app.options.show_highlighter) return false;
              +    if (!this.app.options.attempt_highlight) return false;
              +    
              +    // Check if there is a carriage return in the output dish as this will not
              +    // be displayed by the HTML textarea and will mess up highlighting offsets.
              +    if (!this.app.dish_str || this.app.dish_str.indexOf("\r") >= 0) return false;
              +    
              +    var start_placeholder = "[start_highlight]",
              +        start_placeholder_regex = /\[start_highlight\]/g,
              +        end_placeholder = "[end_highlight]",
              +        end_placeholder_regex = /\[end_highlight\]/g,
              +        text = textarea.value;
              +    
              +    // Put placeholders in position
              +    // If there's only one value, select that
              +    // If there are multiple, ignore the first one and select all others
              +    if (pos.length == 1) {
              +        if (pos[0].end < pos[0].start) return;
              +        text = text.slice(0, pos[0].start) +
              +            start_placeholder + text.slice(pos[0].start, pos[0].end) + end_placeholder +
              +            text.slice(pos[0].end, text.length);
              +    } else {
              +        // O(n^2) - Can anyone improve this without overwriting placeholders?
              +        var result = "",
              +            end_placed = true;
              +            
              +        for (var i = 0; i < text.length; i++) {
              +            for (var j = 1; j < pos.length; j++) {
              +                if (pos[j].end < pos[j].start) continue;
              +                if (pos[j].start == i) {
              +                    result += start_placeholder;
              +                    end_placed = false;
              +                }
              +                if (pos[j].end == i) {
              +                    result += end_placeholder;
              +                    end_placed = true;
              +                }
              +            }
              +            result += text[i];
              +        }
              +        if (!end_placed) result += end_placeholder;
              +        text = result;
              +    }
              +    
              +    var css_class = "hl1";
              +    //if (colour) css_class += "-"+colour;
              +    
              +    // Remove HTML tags
              +    text = text.replace(/&/g, "&amp;")
              +                .replace(/</g, "&lt;")
              +                .replace(/>/g, "&gt;")
              +                .replace(/\n/g, "&#10;")
              +                // Convert placeholders to tags
              +                .replace(start_placeholder_regex, "<span class=\""+css_class+"\">")
              +                .replace(end_placeholder_regex, "</span>") + "&nbsp;";
              +    
              +    // Adjust width to allow for scrollbars
              +    highlighter.style.width = textarea.clientWidth + "px";
              +    highlighter.innerHTML = text;
              +    highlighter.scrollTop = textarea.scrollTop;
              +    highlighter.scrollLeft = textarea.scrollLeft;
              +};
              diff --git a/src/js/views/html/InputWaiter.js b/src/js/views/html/InputWaiter.js
              new file mode 100755
              index 00000000..d6b7821c
              --- /dev/null
              +++ b/src/js/views/html/InputWaiter.js
              @@ -0,0 +1,217 @@
              +/**
              + * Waiter to handle events related to the input.
              + *
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @constructor
              + * @param {HTMLApp} app - The main view object for CyberChef.
              + * @param {Manager} manager - The CyberChef event manager.
              + */
              +var InputWaiter = function(app, manager) {
              +    this.app = app;
              +    this.manager = manager;
              +    
              +    // Define keys that don't change the input so we don't have to autobake when they are pressed
              +    this.bad_keys = [
              +        16, //Shift
              +        17, //Ctrl
              +        18, //Alt
              +        19, //Pause
              +        20, //Caps
              +        27, //Esc
              +        33,34,35,36, //PgUp, PgDn, End, Home
              +        37,38,39,40, //Directional
              +        44, //PrntScrn
              +        91,92, //Win
              +        93, //Context
              +        112,113,114,115,116,117,118,119,120,121,122,123, //F1-12
              +        144, //Num
              +        145, //Scroll
              +    ];
              +};
              +
              +
              +/**
              + * Gets the user's input from the input textarea.
              + *
              + * @returns {string}
              + */
              +InputWaiter.prototype.get = function() {
              +    return document.getElementById("input-text").value;
              +};
              +
              +
              +/**
              + * Sets the input in the input textarea.
              + *
              + * @param {string} input
              + *
              + * @fires Manager#statechange
              + */
              +InputWaiter.prototype.set = function(input) {
              +    document.getElementById("input-text").value = input;
              +    window.dispatchEvent(this.manager.statechange);
              +};
              +
              +
              +/**
              + * Displays information about the input.
              + *
              + * @param {number} length - The length of the current input string
              + * @param {number} lines - The number of the lines in the current input string
              + */
              +InputWaiter.prototype.set_input_info = function(length, lines) {
              +    var width = length.toString().length;
              +    width = width < 2 ? 2 : width;
              +    
              +    var length_str = Utils.pad(length.toString(), width, " ").replace(/ /g, "&nbsp;");
              +    var lines_str  = Utils.pad(lines.toString(), width, " ").replace(/ /g, "&nbsp;");
              +        
              +    document.getElementById("input-info").innerHTML = "length: " + length_str + "<br>lines: " + lines_str;
              +};
              +
              +
              +/**
              + * Handler for input scroll events.
              + * Scrolls the highlighter pane to match the input textarea position and updates history state.
              + *
              + * @param {event} e
              + *
              + * @fires Manager#statechange
              + */
              +InputWaiter.prototype.input_change = function(e) {
              +    // Remove highlighting from input and output panes as the offsets might be different now
              +    this.manager.highlighter.remove_highlights();
              +    
              +    // Reset recipe progress as any previous processing will be redundant now
              +    this.app.progress = 0;
              +    
              +    // Update the input metadata info
              +    var input_text = this.get(),
              +        lines = input_text.count("\n") + 1;
              +        
              +    this.set_input_info(input_text.length, lines);
              +    
              +    
              +    if (this.bad_keys.indexOf(e.keyCode) < 0) {
              +        // Fire the statechange event as the input has been modified
              +        window.dispatchEvent(this.manager.statechange);
              +    }
              +};
              +
              +
              +/**
              + * Handler for input dragover events.
              + * Gives the user a visual cue to show that items can be dropped here.
              + *
              + * @param {event} e
              + */
              +InputWaiter.prototype.input_dragover = function(e) {
              +    // This will be set if we're dragging an operation
              +    if (e.dataTransfer.effectAllowed === "move")
              +        return false;
              +    
              +    e.stopPropagation();
              +    e.preventDefault();
              +    e.target.classList.add("dropping-file");
              +};
              +
              +
              +/**
              + * Handler for input dragleave events.
              + * Removes the visual cue.
              + *
              + * @param {event} e
              + */
              +InputWaiter.prototype.input_dragleave = function(e) {
              +    e.stopPropagation();
              +    e.preventDefault();
              +    e.target.classList.remove("dropping-file");
              +};
              +
              +
              +/**
              + * Handler for input drop events.
              + * Loads the dragged data into the input textarea.
              + *
              + * @param {event} e
              + */
              +InputWaiter.prototype.input_drop = function(e) {
              +    // This will be set if we're dragging an operation
              +    if (e.dataTransfer.effectAllowed === "move")
              +        return false;
              +    
              +    e.stopPropagation();
              +    e.preventDefault();
              +    
              +    var el = e.target,
              +        file = e.dataTransfer.files[0],
              +        text = e.dataTransfer.getData("Text"),
              +        reader = new FileReader(),
              +        input_charcode = "",
              +        offset = 0,
              +        CHUNK_SIZE = 20480; // 20KB
              +    
              +    var set_input = function() {
              +        if (input_charcode.length > 100000 && this.app.auto_bake_) {
              +            this.manager.controls.set_auto_bake(false);
              +            this.app.alert("Turned off Auto Bake as the input is large", "warning", 5000);
              +        }
              +        
              +        this.set(input_charcode);
              +        var recipe_config = this.app.get_recipe_config();
              +        if (!recipe_config[0] || recipe_config[0].op != "From Hex") {
              +            recipe_config.unshift({op:"From Hex",args:["Space"]});
              +            this.app.set_recipe_config(recipe_config);
              +        }
              +        
              +        el.classList.remove("loading_file");
              +    }.bind(this);
              +    
              +    var seek = function() {
              +        if (offset >= file.size) {
              +            set_input();
              +            return;
              +        }
              +        el.value = "Processing... " + Math.round(offset / file.size * 100) + "%";
              +        var slice = file.slice(offset, offset + CHUNK_SIZE);
              +        reader.readAsArrayBuffer(slice);
              +    }.bind(this);
              +    
              +    reader.onload = function(e) {
              +        var data = new Uint8Array(reader.result);
              +        input_charcode += Utils.to_hex_fast(data);
              +        offset += CHUNK_SIZE;
              +        seek();
              +    }.bind(this);
              +    
              +    
              +    el.classList.remove("dropping-file");
              +    
              +    if (file) {
              +        el.classList.add("loading_file");
              +        seek();
              +    } else if (text) {
              +        this.set(text);
              +    }
              +};
              +
              +
              +/**
              + * Handler for clear IO events.
              + * Resets the input, output and info areas.
              + *
              + * @fires Manager#statechange
              + */
              +InputWaiter.prototype.clear_io_click = function() {
              +    this.manager.highlighter.remove_highlights();
              +    document.getElementById("input-text").value = "";
              +    document.getElementById("output-text").value = "";
              +    document.getElementById("input-info").innerHTML = "";
              +    document.getElementById("output-info").innerHTML = "";
              +    document.getElementById("input-selection-info").innerHTML = "";
              +    document.getElementById("output-selection-info").innerHTML = "";
              +    window.dispatchEvent(this.manager.statechange);
              +};
              diff --git a/src/js/views/html/Manager.js b/src/js/views/html/Manager.js
              new file mode 100755
              index 00000000..9c414d3c
              --- /dev/null
              +++ b/src/js/views/html/Manager.js
              @@ -0,0 +1,263 @@
              +/**
              + * This object controls the Waiters responsible for handling events from all areas of the app.
              + *
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @constructor
              + * @param {HTMLApp} app - The main view object for CyberChef.
              + */
              +var Manager = function(app) {
              +    this.app = app;
              +    
              +    // Define custom events
              +    /**
              +     * @event Manager#appstart
              +     */
              +    this.appstart = new CustomEvent("appstart", {bubbles: true});
              +    /**
              +     * @event Manager#operationadd
              +     */
              +    this.operationadd = new CustomEvent("operationadd", {bubbles: true});
              +    /**
              +     * @event Manager#operationremove
              +     */
              +    this.operationremove = new CustomEvent("operationremove", {bubbles: true});
              +    /**
              +     * @event Manager#oplistcreate
              +     */
              +    this.oplistcreate = new CustomEvent("oplistcreate", {bubbles: true});
              +    /**
              +     * @event Manager#statechange
              +     */
              +    this.statechange = new CustomEvent("statechange", {bubbles: true});
              +    
              +    // Define Waiter objects to handle various areas
              +    this.window      = new WindowWaiter(this.app);
              +    this.controls    = new ControlsWaiter(this.app, this);
              +    this.recipe      = new RecipeWaiter(this.app, this);
              +    this.ops         = new OperationsWaiter(this.app, this);
              +    this.input       = new InputWaiter(this.app, this);
              +    this.output      = new OutputWaiter(this.app, this);
              +    this.options     = new OptionsWaiter(this.app);
              +    this.highlighter = new HighlighterWaiter(this.app);
              +    this.seasonal    = new SeasonalWaiter(this.app, this);
              +    
              +    // Object to store dynamic handlers to fire on elements that may not exist yet
              +    this.dynamic_handlers = {};
              +    
              +    this.initialise_event_listeners();
              +};
              +
              +
              +/**
              + * Sets up the various components and listeners.
              + */
              +Manager.prototype.setup = function() {
              +    this.recipe.initialise_operation_drag_n_drop();
              +    this.controls.auto_bake_change();
              +    this.seasonal.load();
              +};
              +
              +
              +/**
              + * Main function to handle the creation of the event listeners.
              + */
              +Manager.prototype.initialise_event_listeners = function() {
              +    // Global
              +    window.addEventListener("resize", this.window.window_resize.bind(this.window));
              +    window.addEventListener("blur", this.window.window_blur.bind(this.window));
              +    window.addEventListener("focus", this.window.window_focus.bind(this.window));
              +    window.addEventListener("statechange", this.app.state_change.bind(this.app));
              +    window.addEventListener("popstate", this.app.pop_state.bind(this.app));
              +    
              +    // Controls
              +    document.getElementById("bake").addEventListener("click", this.controls.bake_click.bind(this.controls));
              +    document.getElementById("auto-bake").addEventListener("change", this.controls.auto_bake_change.bind(this.controls));
              +    document.getElementById("step").addEventListener("click", this.controls.step_click.bind(this.controls));
              +    document.getElementById("clr-recipe").addEventListener("click", this.controls.clear_recipe_click.bind(this.controls));
              +    document.getElementById("clr-breaks").addEventListener("click", this.controls.clear_breaks_click.bind(this.controls));
              +    document.getElementById("save").addEventListener("click", this.controls.save_click.bind(this.controls));
              +    document.getElementById("save-button").addEventListener("click", this.controls.save_button_click.bind(this.controls));
              +    document.getElementById("save-link-recipe-checkbox").addEventListener("change", this.controls.slr_check_change.bind(this.controls));
              +    document.getElementById("save-link-input-checkbox").addEventListener("change", this.controls.sli_check_change.bind(this.controls));
              +    document.getElementById("load").addEventListener("click", this.controls.load_click.bind(this.controls));
              +    document.getElementById("load-delete-button").addEventListener("click", this.controls.load_delete_click.bind(this.controls));
              +    document.getElementById("load-name").addEventListener("change", this.controls.load_name_change.bind(this.controls));
              +    document.getElementById("load-button").addEventListener("click", this.controls.load_button_click.bind(this.controls));
              +    this.add_multi_event_listener("#save-text", "keyup paste", this.controls.save_text_change, this.controls);
              +    
              +    // Operations
              +    this.add_multi_event_listener("#search", "keyup paste search", this.ops.search_operations, this.ops);
              +    this.add_dynamic_listener(".op_list li.operation", "dblclick", this.ops.operation_dblclick, this.ops);
              +    document.getElementById("edit-favourites").addEventListener("click", this.ops.edit_favourites_click.bind(this.ops));
              +    document.getElementById("save-favourites").addEventListener("click", this.ops.save_favourites_click.bind(this.ops));
              +    document.getElementById("reset-favourites").addEventListener("click", this.ops.reset_favourites_click.bind(this.ops));
              +    this.add_dynamic_listener(".op_list .op-icon", "mouseover", this.ops.op_icon_mouseover, this.ops);
              +    this.add_dynamic_listener(".op_list .op-icon", "mouseleave", this.ops.op_icon_mouseleave, this.ops);
              +    this.add_dynamic_listener(".op_list", "oplistcreate", this.ops.op_list_create, this.ops);
              +    this.add_dynamic_listener("li.operation", "operationadd", this.recipe.op_add.bind(this.recipe));
              +    
              +    // Recipe
              +    this.add_dynamic_listener(".arg", "keyup", this.recipe.ing_change, this.recipe);
              +    this.add_dynamic_listener(".arg", "change", this.recipe.ing_change, this.recipe);
              +    this.add_dynamic_listener(".disable-icon", "click", this.recipe.disable_click, this.recipe);
              +    this.add_dynamic_listener(".breakpoint", "click", this.recipe.breakpoint_click, this.recipe);
              +    this.add_dynamic_listener("#rec_list li.operation", "dblclick", this.recipe.operation_dblclick, this.recipe);
              +    this.add_dynamic_listener("#rec_list li.operation > div", "dblclick", this.recipe.operation_child_dblclick, this.recipe);
              +    this.add_dynamic_listener("#rec_list .input-group .dropdown-menu a", "click", this.recipe.dropdown_toggle_click, this.recipe);
              +    this.add_dynamic_listener("#rec_list", "operationremove", this.recipe.op_remove.bind(this.recipe));
              +    
              +    // Input
              +    this.add_multi_event_listener("#input-text", "keyup paste", this.input.input_change, this.input);
              +    document.getElementById("reset-layout").addEventListener("click", this.app.reset_layout.bind(this.app));
              +    document.getElementById("clr-io").addEventListener("click", this.input.clear_io_click.bind(this.input));
              +    document.getElementById("input-text").addEventListener("dragover", this.input.input_dragover.bind(this.input));
              +    document.getElementById("input-text").addEventListener("dragleave", this.input.input_dragleave.bind(this.input));
              +    document.getElementById("input-text").addEventListener("drop", this.input.input_drop.bind(this.input));
              +    document.getElementById("input-text").addEventListener("scroll", this.highlighter.input_scroll.bind(this.highlighter));
              +    document.getElementById("input-text").addEventListener("mouseup", this.highlighter.input_mouseup.bind(this.highlighter));
              +    document.getElementById("input-text").addEventListener("mousemove", this.highlighter.input_mousemove.bind(this.highlighter));
              +    this.add_multi_event_listener("#input-text", "mousedown dblclick select",  this.highlighter.input_mousedown, this.highlighter);
              +    
              +    // Output
              +    document.getElementById("save-to-file").addEventListener("click", this.output.save_click.bind(this.output));
              +    document.getElementById("switch").addEventListener("click", this.output.switch_click.bind(this.output));
              +    document.getElementById("undo-switch").addEventListener("click", this.output.undo_switch_click.bind(this.output));
              +    document.getElementById("output-text").addEventListener("scroll", this.highlighter.output_scroll.bind(this.highlighter));
              +    document.getElementById("output-text").addEventListener("mouseup", this.highlighter.output_mouseup.bind(this.highlighter));
              +    document.getElementById("output-text").addEventListener("mousemove", this.highlighter.output_mousemove.bind(this.highlighter));
              +    document.getElementById("output-html").addEventListener("mouseup", this.highlighter.output_html_mouseup.bind(this.highlighter));
              +    document.getElementById("output-html").addEventListener("mousemove", this.highlighter.output_html_mousemove.bind(this.highlighter));
              +    this.add_multi_event_listener("#output-text", "mousedown dblclick select",  this.highlighter.output_mousedown, this.highlighter);
              +    this.add_multi_event_listener("#output-html", "mousedown dblclick select",  this.highlighter.output_html_mousedown, this.highlighter);
              +    
              +    // Options
              +    document.getElementById("options").addEventListener("click", this.options.options_click.bind(this.options));
              +    document.getElementById("reset-options").addEventListener("click", this.options.reset_options_click.bind(this.options));
              +    $(".option-item input:checkbox").on("switchChange.bootstrapSwitch", this.options.switch_change.bind(this.options));
              +    $(".option-item input:checkbox").on("switchChange.bootstrapSwitch", this.options.set_word_wrap.bind(this.options));
              +    this.add_dynamic_listener(".option-item input[type=number]", "keyup", this.options.number_change, this.options);
              +    this.add_dynamic_listener(".option-item input[type=number]", "change", this.options.number_change, this.options);
              +    this.add_dynamic_listener(".option-item select", "change", this.options.select_change, this.options);
              +    
              +    // Misc
              +    document.getElementById("alert-close").addEventListener("click", this.app.alert_close_click.bind(this.app));
              +};
              +
              +
              +/**
              + * Adds an event listener to each element in the specified group.
              + *
              + * @param {string} selector - A selector string for the element group to add the event to, see
              + *   this.get_all()
              + * @param {string} event_type - The event to listen for
              + * @param {function} callback - The function to execute when the event is triggered
              + * @param {Object} [scope=this] - The object to bind to the callback function
              + *
              + * @example
              + * // Calls the clickable function whenever any element with the .clickable class is clicked
              + * this.add_listeners(".clickable", "click", this.clickable, this);
              + */
              +Manager.prototype.add_listeners = function(selector, event_type, callback, scope) {
              +    scope = scope || this;
              +    [].forEach.call(document.querySelectorAll(selector), function(el) {
              +        el.addEventListener(event_type, callback.bind(scope));
              +    });
              +};
              +
              +
              +/**
              + * Adds multiple event listeners to the specified element.
              + *
              + * @param {string} selector - A selector string for the element to add the events to
              + * @param {string} event_types - A space-separated string of all the event types to listen for
              + * @param {function} callback - The function to execute when the events are triggered
              + * @param {Object} [scope=this] - The object to bind to the callback function
              + *
              + * @example
              + * // Calls the search function whenever the the keyup, paste or search events are triggered on the
              + * // search element
              + * this.add_multi_event_listener("search", "keyup paste search", this.search, this);
              + */
              +Manager.prototype.add_multi_event_listener = function(selector, event_types, callback, scope) {
              +    var evs = event_types.split(" ");
              +    for (var i = 0; i < evs.length; i++) {
              +        document.querySelector(selector).addEventListener(evs[i], callback.bind(scope));
              +    }
              +};
              +
              +
              +/**
              + * Adds multiple event listeners to each element in the specified group.
              + *
              + * @param {string} selector - A selector string for the element group to add the events to
              + * @param {string} event_types - A space-separated string of all the event types to listen for
              + * @param {function} callback - The function to execute when the events are triggered
              + * @param {Object} [scope=this] - The object to bind to the callback function
              + *
              + * @example
              + * // Calls the save function whenever the the keyup or paste events are triggered on any element
              + * // with the .saveable class
              + * this.add_multi_event_listener(".saveable", "keyup paste", this.save, this);
              + */
              +Manager.prototype.add_multi_event_listeners = function(selector, event_types, callback, scope) {
              +    var evs = event_types.split(" ");
              +    for (var i = 0; i < evs.length; i++) {
              +        this.add_listeners(selector, evs[i], callback, scope);
              +    }
              +};
              +
              +
              +/**
              + * Adds an event listener to the global document object which will listen on dynamic elements which
              + * may not exist in the DOM yet.
              + *
              + * @param {string} selector - A selector string for the element(s) to add the event to
              + * @param {string} event_type - The event(s) to listen for
              + * @param {function} callback - The function to execute when the event(s) is/are triggered
              + * @param {Object} [scope=this] - The object to bind to the callback function
              + *
              + * @example
              + * // Pops up an alert whenever any button is clicked, even if it is added to the DOM after this
              + * // listener is created
              + * this.add_dynamic_listener("button", "click", alert, this);
              + */
              +Manager.prototype.add_dynamic_listener = function(selector, event_type, callback, scope) {
              +    var event_config = {
              +        selector: selector,
              +        callback: callback.bind(scope || this)
              +    };
              +    
              +    if (this.dynamic_handlers.hasOwnProperty(event_type)) {
              +        // Listener already exists, add new handler to the appropriate list
              +        this.dynamic_handlers[event_type].push(event_config);
              +    } else {
              +        this.dynamic_handlers[event_type] = [event_config];
              +        // Set up listener for this new type
              +        document.addEventListener(event_type, this.dynamic_listener_handler.bind(this));
              +    }
              +};
              +
              +
              +/**
              + * Handler for dynamic events. This function is called for any dynamic event and decides which
              + * callback(s) to execute based on the type and selector.
              + *
              + * @param {Event} e - The event to be handled
              + */
              +Manager.prototype.dynamic_listener_handler = function(e) {
              +    var handlers = this.dynamic_handlers[e.type],
              +        matches = e.target.matches ||
              +            e.target.webkitMatchesSelector ||
              +            e.target.mozMatchesSelector ||
              +            e.target.msMatchesSelector ||
              +            e.target.oMatchesSelector;
              +    
              +    for (var i = 0; i < handlers.length; i++) {
              +        if (matches && e.target[matches.name](handlers[i].selector)) {
              +            handlers[i].callback(e);
              +        }
              +    }
              +};
              diff --git a/src/js/views/html/OperationsWaiter.js b/src/js/views/html/OperationsWaiter.js
              new file mode 100755
              index 00000000..4d796e6e
              --- /dev/null
              +++ b/src/js/views/html/OperationsWaiter.js
              @@ -0,0 +1,282 @@
              +/* globals Sortable */
              +
              +/**
              + * Waiter to handle events related to the operations.
              + *
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @constructor
              + * @param {HTMLApp} app - The main view object for CyberChef.
              + * @param {Manager} manager - The CyberChef event manager.
              + */
              +var OperationsWaiter = function(app, manager) {
              +    this.app = app;
              +    this.manager = manager;
              +    
              +    this.options = {};
              +    this.remove_intent = false;
              +};
              +
              +
              +/**
              + * Handler for search events.
              + * Finds operations which match the given search term and displays them under the search box.
              + *
              + * @param {event} e
              + */
              +OperationsWaiter.prototype.search_operations = function(e) {
              +    var ops, selected;
              +    
              +    if (e.type == "search") { // Search
              +        e.preventDefault();
              +        ops = document.querySelectorAll("#search-results li");
              +        if (ops.length) {
              +            selected = this.get_selected_op(ops);
              +            if (selected > -1) {
              +                this.manager.recipe.add_operation(ops[selected].innerHTML);
              +                this.app.auto_bake();
              +            }
              +        }
              +    }
              +    
              +    if (e.keyCode == 13) { // Return
              +        e.preventDefault();
              +    } else if (e.keyCode == 40) { // Down
              +        e.preventDefault();
              +        ops = document.querySelectorAll("#search-results li");
              +        if (ops.length) {
              +            selected = this.get_selected_op(ops);
              +            if (selected > -1) {
              +                ops[selected].classList.remove("selected-op");
              +            }
              +            if (selected == ops.length-1) selected = -1;
              +            ops[selected+1].classList.add("selected-op");
              +        }
              +    } else if (e.keyCode == 38) { // Up
              +        e.preventDefault();
              +        ops = document.querySelectorAll("#search-results li");
              +        if (ops.length) {
              +            selected = this.get_selected_op(ops);
              +            if (selected > -1) {
              +                ops[selected].classList.remove("selected-op");
              +            }
              +            if (selected === 0) selected = ops.length;
              +            ops[selected-1].classList.add("selected-op");
              +        }
              +    } else {
              +        var search_results_el = document.getElementById("search-results"),
              +            el = e.target,
              +            str = el.value;
              +        
              +        while (search_results_el.firstChild) {
              +            search_results_el.removeChild(search_results_el.firstChild);
              +        }
              +        
              +        $("#categories .in").collapse("hide");
              +        if (str) {
              +            var matched_ops = this.filter_operations(str, true),
              +                matched_ops_html = "";
              +            
              +            for (var i = 0; i < matched_ops.length; i++) {
              +                matched_ops_html += matched_ops[i].to_stub_html();
              +            }
              +            
              +            search_results_el.innerHTML = matched_ops_html;
              +            search_results_el.dispatchEvent(this.manager.oplistcreate);
              +        }
              +    }
              +};
              +
              +
              +/**
              + * Filters operations based on the search string and returns the matching ones.
              + *
              + * @param {string} search_str
              + * @param {boolean} highlight - Whether or not to highlight the matching string in the operation
              + *   name and description
              + * @returns {string[]}
              + */
              +OperationsWaiter.prototype.filter_operations = function(search_str, highlight) {
              +    var matched_ops = [],
              +        matched_descs = [];
              +    
              +    search_str = search_str.toLowerCase();
              +    
              +    for (var op_name in this.app.operations) {
              +        var op = this.app.operations[op_name],
              +            name_pos = op_name.toLowerCase().indexOf(search_str),
              +            desc_pos = op.description.toLowerCase().indexOf(search_str);
              +        
              +        if (name_pos >= 0 || desc_pos >= 0) {
              +            var operation = new HTMLOperation(op_name, this.app.operations[op_name], this.app, this.manager);
              +            if (highlight) {
              +                operation.highlight_search_string(search_str, name_pos, desc_pos);
              +            }
              +            
              +            if (name_pos < 0) {
              +                matched_ops.push(operation);
              +            } else {
              +                matched_descs.push(operation);
              +            }
              +        }
              +    }
              +    
              +    return matched_descs.concat(matched_ops);
              +};
              +
              +
              +/**
              + * Finds the operation which has been selected using keyboard shortcuts. This will have the class
              + * 'selected-op' set. Returns the index of the operation within the given list.
              + *
              + * @param {element[]} ops
              + * @returns {number}
              + */
              +OperationsWaiter.prototype.get_selected_op = function(ops) {
              +    for (var i = 0; i < ops.length; i++) {
              +        if (ops[i].classList.contains("selected-op")) {
              +            return i;
              +        }
              +    }
              +    return -1;
              +};
              +
              +
              +/**
              + * Handler for oplistcreate events.
              + *
              + * @listens Manager#oplistcreate
              + * @param {event} e
              + */
              +OperationsWaiter.prototype.op_list_create = function(e) {
              +    this.manager.recipe.create_sortable_seed_list(e.target);
              +    $("[data-toggle=popover]").popover();
              +};
              +
              +
              +/**
              + * Handler for operation doubleclick events.
              + * Adds the operation to the recipe and auto bakes.
              + *
              + * @param {event} e
              + */
              +OperationsWaiter.prototype.operation_dblclick = function(e) {
              +    var li = e.target;
              +    
              +    this.manager.recipe.add_operation(li.textContent);
              +    this.app.auto_bake();
              +};
              +
              +
              +/**
              + * Handler for edit favourites click events.
              + * Sets up the 'Edit favourites' pane and displays it.
              + *
              + * @param {event} e
              + */
              +OperationsWaiter.prototype.edit_favourites_click = function(e) {
              +    e.preventDefault();
              +    e.stopPropagation();
              +    
              +    // Add favourites to modal
              +    var fav_cat = this.app.categories.filter(function(c) {
              +        return c.name == "Favourites";
              +    })[0];
              +    
              +    var html = "";
              +    for (var i = 0; i < fav_cat.ops.length; i++) {
              +        var op_name = fav_cat.ops[i];
              +        var operation = new HTMLOperation(op_name, this.app.operations[op_name], this.app, this.manager);
              +        html += operation.to_stub_html(true);
              +    }
              +    
              +    var edit_favourites_list = document.getElementById("edit-favourites-list");
              +    edit_favourites_list.innerHTML = html;
              +    this.remove_intent = false;
              +    
              +    var editable_list = Sortable.create(edit_favourites_list, {
              +        filter: '.remove-icon',
              +        onFilter: function (evt) {
              +            var el = editable_list.closest(evt.item);
              +            if (el) {
              +                $(el).popover("destroy");
              +                el.parentNode.removeChild(el);
              +            }
              +        },
              +        onEnd: function(evt) {
              +            if (this.remove_intent) evt.item.remove();
              +        }.bind(this),
              +    });
              +    
              +    Sortable.utils.on(edit_favourites_list, "dragleave", function() {
              +         this.remove_intent = true;
              +    }.bind(this));
              +    
              +    Sortable.utils.on(edit_favourites_list, "dragover", function() {
              +         this.remove_intent = false;
              +    }.bind(this));
              +    
              +    $("#edit-favourites-list [data-toggle=popover]").popover();
              +    $("#favourites-modal").modal();
              +};
              +
              +
              +/**
              + * Handler for save favourites click events.
              + * Saves the selected favourites and reloads them.
              + */
              +OperationsWaiter.prototype.save_favourites_click = function() {
              +    var favourites_list = [],
              +        favs = document.querySelectorAll("#edit-favourites-list li");
              +    
              +    for (var i = 0; i < favs.length; i++) {
              +        favourites_list.push(favs[i].textContent);
              +    }
              +
              +    this.app.save_favourites(favourites_list);
              +    this.app.load_favourites();
              +    this.app.populate_operations_list();
              +    this.manager.recipe.initialise_operation_drag_n_drop();
              +};
              +
              +
              +/**
              + * Handler for reset favourites click events.
              + * Resets favourites to their defaults.
              + */
              +OperationsWaiter.prototype.reset_favourites_click = function() {
              +    this.app.reset_favourites();
              +};
              +
              +
              +/**
              + * Handler for op_icon mouseover events.
              + * Hides any popovers already showing on the operation so that there aren't two at once.
              + *
              + * @param {event} e
              + */
              +OperationsWaiter.prototype.op_icon_mouseover = function(e) {
              +    var op_el = e.target.parentNode;
              +    if (e.target.getAttribute("data-toggle") == "popover") {
              +        $(op_el).popover("hide");
              +    }
              +};
              +
              +
              +/**
              + * Handler for op_icon mouseleave events.
              + * If this icon created a popover and we're moving back to the operation element, display the
              + *   operation popover again.
              + *
              + * @param {event} e
              + */
              +OperationsWaiter.prototype.op_icon_mouseleave = function(e) {
              +    var op_el = e.target.parentNode,
              +        to_el = e.toElement || e.relatedElement;
              +    
              +    if (e.target.getAttribute("data-toggle") == "popover" && to_el === op_el) {
              +        $(op_el).popover("show");
              +    }
              +};
              diff --git a/src/js/views/html/OptionsWaiter.js b/src/js/views/html/OptionsWaiter.js
              new file mode 100755
              index 00000000..05d80185
              --- /dev/null
              +++ b/src/js/views/html/OptionsWaiter.js
              @@ -0,0 +1,132 @@
              +/**
              + * Waiter to handle events related to the CyberChef options.
              + *
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @constructor
              + * @param {HTMLApp} app - The main view object for CyberChef.
              + */
              +var OptionsWaiter = function(app) {
              +    this.app = app;
              +};
              +
              +
              +/**
              + * Loads options and sets values of switches and inputs to match them.
              + *
              + * @param {Object} options
              + */
              +OptionsWaiter.prototype.load = function(options) {
              +    $(".option-item input:checkbox").bootstrapSwitch({
              +        size: "small",
              +        animate: false,
              +    });
              +    
              +    for (var option in options) {
              +        this.app.options[option] = options[option];
              +    }
              +    
              +    // Set options to match object
              +    var cboxes = document.querySelectorAll("#options-body input[type=checkbox]");
              +    for (var i = 0; i < cboxes.length; i++) {
              +        $(cboxes[i]).bootstrapSwitch("state", this.app.options[cboxes[i].getAttribute("option")]);
              +    }
              +
              +    var nboxes = document.querySelectorAll("#options-body input[type=number]");
              +    for (i = 0; i < nboxes.length; i++) {
              +        nboxes[i].value = this.app.options[nboxes[i].getAttribute("option")];
              +        nboxes[i].dispatchEvent(new CustomEvent("change", {bubbles: true}));
              +    }
              +    
              +    var selects = document.querySelectorAll("#options-body select");
              +    for (i = 0; i < selects.length; i++) {
              +        selects[i].value = this.app.options[selects[i].getAttribute("option")];
              +        selects[i].dispatchEvent(new CustomEvent("change", {bubbles: true}));
              +    }
              +};
              +
              +
              +/**
              + * Handler for options click events.
              + * Dispays the options pane.
              + */
              +OptionsWaiter.prototype.options_click = function() {
              +    $("#options-modal").modal();
              +};
              +
              +
              +/**
              + * Handler for reset options click events.
              + * Resets options back to their default values.
              + */
              +OptionsWaiter.prototype.reset_options_click = function() {
              +    this.load(this.app.doptions);
              +};
              +
              +
              +/**
              + * Handler for switch change events.
              + * Modifies the option state and saves it to local storage.
              + *
              + * @param {event} e
              + * @param {boolean} state
              + */
              +OptionsWaiter.prototype.switch_change = function(e, state) {
              +    var el = e.target,
              +        option = el.getAttribute("option");
              +        
              +    this.app.options[option] = state;
              +    localStorage.setItem("options", JSON.stringify(this.app.options));
              +};
              +
              +
              +/**
              + * Handler for number change events.
              + * Modifies the option value and saves it to local storage.
              + *
              + * @param {event} e
              + */
              +OptionsWaiter.prototype.number_change = function(e) {
              +    var el = e.target,
              +        option = el.getAttribute("option");
              +        
              +    this.app.options[option] = parseInt(el.value, 10);
              +    localStorage.setItem("options", JSON.stringify(this.app.options));
              +};
              +
              +
              +/**
              + * Handler for select change events.
              + * Modifies the option value and saves it to local storage.
              + *
              + * @param {event} e
              + */
              +OptionsWaiter.prototype.select_change = function(e) {
              +    var el = e.target,
              +        option = el.getAttribute("option");
              +        
              +    this.app.options[option] = el.value;
              +    localStorage.setItem("options", JSON.stringify(this.app.options));
              +};
              +
              +
              +/**
              + * Sets or unsets word wrap on the input and output depending on the word_wrap option value.
              + */
              +OptionsWaiter.prototype.set_word_wrap = function() {
              +    document.getElementById("input-text").classList.remove("word-wrap");
              +    document.getElementById("output-text").classList.remove("word-wrap");
              +    document.getElementById("output-html").classList.remove("word-wrap");
              +    document.getElementById("input-highlighter").classList.remove("word-wrap");
              +    document.getElementById("output-highlighter").classList.remove("word-wrap");
              +    
              +    if (!this.app.options.word_wrap) {
              +        document.getElementById("input-text").classList.add("word-wrap");
              +        document.getElementById("output-text").classList.add("word-wrap");
              +        document.getElementById("output-html").classList.add("word-wrap");
              +        document.getElementById("input-highlighter").classList.add("word-wrap");
              +        document.getElementById("output-highlighter").classList.add("word-wrap");
              +    }
              +};
              diff --git a/src/js/views/html/OutputWaiter.js b/src/js/views/html/OutputWaiter.js
              new file mode 100755
              index 00000000..ea378293
              --- /dev/null
              +++ b/src/js/views/html/OutputWaiter.js
              @@ -0,0 +1,139 @@
              +/**
              + * Waiter to handle events related to the output.
              + *
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @constructor
              + * @param {HTMLApp} app - The main view object for CyberChef.
              + * @param {Manager} manager - The CyberChef event manager.
              + */
              +var OutputWaiter = function(app, manager) {
              +    this.app = app;
              +    this.manager = manager;
              +};
              +
              +
              +/**
              + * Gets the output string from the output textarea.
              + *
              + * @returns {string}
              + */
              +OutputWaiter.prototype.get = function() {
              +    return document.getElementById("output-text").value;
              +};
              +
              +
              +/**
              + * Sets the output in the output textarea.
              + *
              + * @param {string} data_str - The output string/HTML
              + * @param {string} type - The data type of the output
              + * @param {number} duration - The length of time (ms) it took to generate the output
              + */
              +OutputWaiter.prototype.set = function(data_str, type, duration) {
              +    var output_text = document.getElementById("output-text"),
              +        output_html = document.getElementById("output-html"),
              +        output_highlighter = document.getElementById("output-highlighter"),
              +        input_highlighter = document.getElementById("input-highlighter");
              +
              +    if (type == "html") {
              +        output_text.style.display = "none";
              +        output_html.style.display = "block";
              +        output_highlighter.display = "none";
              +        input_highlighter.display = "none";
              +        
              +        output_text.value = "";
              +        output_html.innerHTML = data_str;
              +        
              +        // Execute script sections
              +        var script_elements = output_html.querySelectorAll("script");
              +        for (var i = 0; i < script_elements.length; i++) {
              +            try {
              +                eval(script_elements[i].innerHTML); // jshint ignore:line
              +            } catch (err) {
              +                console.error(err);
              +            }
              +        }
              +    } else {
              +        output_text.style.display = "block";
              +        output_html.style.display = "none";
              +        output_highlighter.display = "block";
              +        input_highlighter.display = "block";
              +        
              +        output_text.value = Utils.printable(data_str, true);
              +        output_html.innerHTML = "";
              +    }
              +    
              +    this.manager.highlighter.remove_highlights();
              +    var lines = data_str.count("\n") + 1;
              +    this.set_output_info(data_str.length, lines, duration);
              +};
              +
              +
              +/**
              + * Displays information about the output.
              + *
              + * @param {number} length - The length of the current output string
              + * @param {number} lines - The number of the lines in the current output string
              + * @param {number} duration - The length of time (ms) it took to generate the output
              + */
              +OutputWaiter.prototype.set_output_info = function(length, lines, duration) {
              +    var width = length.toString().length;
              +    width = width < 4 ? 4 : width;
              +    
              +    var length_str = Utils.pad(length.toString(), width, " ").replace(/ /g, "&nbsp;");
              +    var lines_str  = Utils.pad(lines.toString(), width, " ").replace(/ /g, "&nbsp;");
              +    var time_str   = Utils.pad(duration.toString() + "ms", width, " ").replace(/ /g, "&nbsp;");
              +    
              +    document.getElementById("output-info").innerHTML = "time: " + time_str +
              +        "<br>length: " + length_str +
              +        "<br>lines: " + lines_str;
              +    document.getElementById("input-selection-info").innerHTML = "";
              +    document.getElementById("output-selection-info").innerHTML = "";
              +};
              +
              +
              +/**
              + * Handler for save click events.
              + * Saves the current output to a file, downloaded as a URL octet stream.
              + */
              +OutputWaiter.prototype.save_click = function() {
              +    var data = Utils.to_base64(this.app.dish_str),
              +        filename = window.prompt("Please enter a filename:", "download.dat");
              +        
              +    if (filename) {
              +        var el = document.createElement("a");
              +        el.setAttribute("href", "data:application/octet-stream;base64;charset=utf-8," + data);
              +        el.setAttribute("download", filename);
              +        
              +        // Firefox requires that the element be added to the DOM before it can be clicked
              +        el.style.display = "none";
              +        document.body.appendChild(el);
              +        
              +        el.click();
              +        el.remove();
              +    }
              +};
              +
              +
              +/**
              + * Handler for switch click events.
              + * Moves the current output into the input textarea.
              + */
              +OutputWaiter.prototype.switch_click = function() {
              +    this.switch_orig_data = this.manager.input.get();
              +    document.getElementById("undo-switch").disabled = false;
              +    this.app.set_input(this.app.dish_str);
              +};
              +
              +
              +/**
              + * Handler for undo switch click events.
              + * Removes the output from the input and replaces the input that was removed.
              + */
              +OutputWaiter.prototype.undo_switch_click = function() {
              +    this.app.set_input(this.switch_orig_data);
              +    document.getElementById("undo-switch").disabled = true;
              +};
              diff --git a/src/js/views/html/RecipeWaiter.js b/src/js/views/html/RecipeWaiter.js
              new file mode 100755
              index 00000000..1cf7be32
              --- /dev/null
              +++ b/src/js/views/html/RecipeWaiter.js
              @@ -0,0 +1,416 @@
              +/* globals Sortable */
              +
              +/**
              + * Waiter to handle events related to the recipe.
              + *
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @constructor
              + * @param {HTMLApp} app - The main view object for CyberChef.
              + * @param {Manager} manager - The CyberChef event manager.
              + */
              +var RecipeWaiter = function(app, manager) {
              +    this.app = app;
              +    this.manager = manager;
              +    this.remove_intent = false;
              +};
              +
              +
              +/**
              + * Sets up the drag and drop capability for operations in the operations and recipe areas.
              + */
              +RecipeWaiter.prototype.initialise_operation_drag_n_drop = function() {
              +    var rec_list = document.getElementById("rec_list"),
              +        op_lists = document.querySelectorAll(".category .op_list");
              +    
              +    
              +    // Recipe list
              +    Sortable.create(rec_list, {
              +        group: "recipe",
              +        sort: true,
              +        animation: 0,
              +        delay: 0,
              +        filter: ".arg-input,.arg", // Relies on commenting out a line in Sortable.js which calls evt.preventDefault()
              +        setData: function(dataTransfer, drag_el) {
              +            dataTransfer.setData("Text", drag_el.querySelector(".arg-title").textContent);
              +        },
              +        onEnd: function(evt) {
              +            if (this.remove_intent) {
              +                evt.item.remove();
              +                evt.target.dispatchEvent(this.manager.operationremove);
              +            }
              +        }.bind(this)
              +    });
              +    
              +    Sortable.utils.on(rec_list, "dragover", function() {
              +        this.remove_intent = false;
              +    }.bind(this));
              +    
              +    Sortable.utils.on(rec_list, "dragleave", function() {
              +        this.remove_intent = true;
              +        this.app.progress = 0;
              +    }.bind(this));
              +    
              +    // Favourites category
              +    document.querySelector("#categories a").addEventListener("dragover", this.fav_dragover.bind(this));
              +    document.querySelector("#categories a").addEventListener("dragleave", this.fav_dragleave.bind(this));
              +    document.querySelector("#categories a").addEventListener("drop", this.fav_drop.bind(this));
              +};
              +
              +
              +/**
              + * Creates a drag-n-droppable seed list of operations.
              + *
              + * @param {element} list_el - The list the initialise
              + */
              +RecipeWaiter.prototype.create_sortable_seed_list = function(list_el) {
              +    Sortable.create(list_el, {
              +        group: {
              +            name: "recipe",
              +            pull: "clone",
              +            put: false
              +        },
              +        sort: false,
              +        setData: function(dataTransfer, drag_el) {
              +            dataTransfer.setData("Text", drag_el.textContent);
              +        },
              +        onStart: function(evt) {
              +            $(evt.item).popover("destroy");
              +            evt.item.setAttribute("data-toggle", "popover-disabled");
              +        },
              +        onEnd: this.op_sort_end.bind(this)
              +    });
              +};
              +
              +
              +/**
              + * Handler for operation sort end events.
              + * Removes the operation from the list if it has been dropped outside. If not, adds it to the list
              + * at the appropriate place and initialises it.
              + *
              + * @fires Manager#operationadd
              + * @param {event} evt
              + */
              +RecipeWaiter.prototype.op_sort_end = function(evt) {
              +    if (this.remove_intent) {
              +        if (evt.item.parentNode.id == "rec_list") {
              +            evt.item.remove();
              +        }
              +        return;
              +    }
              +    
              +    // Reinitialise the popover on the original element in the ops list because for some reason it
              +    // gets destroyed and recreated.
              +    $(evt.clone).popover();
              +    $(evt.clone).children("[data-toggle=popover]").popover();
              +    
              +    if (evt.item.parentNode.id !== "rec_list") {
              +        return;
              +    }
              +    
              +    this.build_recipe_operation(evt.item);
              +    evt.item.dispatchEvent(this.manager.operationadd);
              +};
              +
              +
              +/**
              + * Handler for favourite dragover events.
              + * If the element being dragged is an operation, displays a visual cue so that the user knows it can
              + * be dropped here.
              + *
              + * @param {event} e
              + */
              +RecipeWaiter.prototype.fav_dragover = function(e) {
              +    if (e.dataTransfer.effectAllowed !== "move")
              +        return false;
              +    
              +    e.stopPropagation();
              +    e.preventDefault();
              +    if (e.target.className && e.target.className.indexOf("category-title") > -1) {
              +        // Hovering over the a
              +        e.target.classList.add("favourites-hover");
              +    } else if (e.target.parentNode.className && e.target.parentNode.className.indexOf("category-title") > -1) {
              +        // Hovering over the Edit button
              +        e.target.parentNode.classList.add("favourites-hover");
              +    } else if (e.target.parentNode.parentNode.className && e.target.parentNode.parentNode.className.indexOf("category-title") > -1) {
              +        // Hovering over the image on the Edit button
              +        e.target.parentNode.parentNode.classList.add("favourites-hover");
              +    }
              +};
              +
              +
              +/**
              + * Handler for favourite dragleave events.
              + * Removes the visual cue.
              + *
              + * @param {event} e
              + */
              +RecipeWaiter.prototype.fav_dragleave = function(e) {
              +    e.stopPropagation();
              +    e.preventDefault();
              +    document.querySelector("#categories a").classList.remove("favourites-hover");
              +};
              +
              +
              +/**
              + * Handler for favourite drop events.
              + * Adds the dragged operation to the favourites list.
              + *
              + * @param {event} e
              + */
              +RecipeWaiter.prototype.fav_drop = function(e) {
              +    e.stopPropagation();
              +    e.preventDefault();
              +    e.target.classList.remove("favourites-hover");
              +    
              +    var op_name = e.dataTransfer.getData("Text");
              +    this.app.add_favourite(op_name);
              +};
              +
              +
              +/**
              + * Handler for ingredient change events.
              + *
              + * @fires Manager#statechange
              + */
              +RecipeWaiter.prototype.ing_change = function() {
              +    window.dispatchEvent(this.manager.statechange);
              +};
              +
              +
              +/**
              + * Handler for disable click events.
              + * Updates the icon status.
              + *
              + * @fires Manager#statechange
              + * @param {event} e
              + */
              +RecipeWaiter.prototype.disable_click = function(e) {
              +    var icon = e.target;
              +    
              +    if (icon.getAttribute("disabled") == "false") {
              +        icon.setAttribute("disabled", "true");
              +        icon.classList.add("disable-icon-selected");
              +        icon.parentNode.parentNode.classList.add("disabled");
              +    } else {
              +        icon.setAttribute("disabled", "false");
              +        icon.classList.remove("disable-icon-selected");
              +        icon.parentNode.parentNode.classList.remove("disabled");
              +    }
              +    
              +    this.app.progress = 0;
              +    window.dispatchEvent(this.manager.statechange);
              +};
              +
              +
              +/**
              + * Handler for breakpoint click events.
              + * Updates the icon status.
              + *
              + * @fires Manager#statechange
              + * @param {event} e
              + */
              +RecipeWaiter.prototype.breakpoint_click = function(e) {
              +    var bp = e.target;
              +
              +    if (bp.getAttribute("break") == "false") {
              +        bp.setAttribute("break", "true");
              +        bp.classList.add("breakpoint-selected");
              +    } else {
              +        bp.setAttribute("break", "false");
              +        bp.classList.remove("breakpoint-selected");
              +    }
              +    
              +    window.dispatchEvent(this.manager.statechange);
              +};
              +
              +
              +/**
              + * Handler for operation doubleclick events.
              + * Removes the operation from the recipe and auto bakes.
              + *
              + * @fires Manager#statechange
              + * @param {event} e
              + */
              +RecipeWaiter.prototype.operation_dblclick = function(e) {
              +    e.target.remove();
              +    window.dispatchEvent(this.manager.statechange);
              +};
              +
              +
              +/**
              + * Handler for operation child doubleclick events.
              + * Removes the operation from the recipe.
              + *
              + * @fires Manager#statechange
              + * @param {event} e
              + */
              +RecipeWaiter.prototype.operation_child_dblclick = function(e) {
              +    e.target.parentNode.remove();
              +    window.dispatchEvent(this.manager.statechange);
              +};
              +
              +
              +/**
              + * Generates a configuration object to represent the current recipe.
              + *
              + * @returns {recipe_config}
              + */
              +RecipeWaiter.prototype.get_config = function() {
              +    var config = [], ingredients, ing_list, disabled, bp, item,
              +        operations = document.querySelectorAll("#rec_list li.operation");
              +    
              +    for (var i = 0; i < operations.length; i++) {
              +        ingredients = [];
              +        disabled = operations[i].querySelector(".disable-icon");
              +        bp = operations[i].querySelector(".breakpoint");
              +        ing_list = operations[i].querySelectorAll(".arg");
              +        
              +        for (var j = 0; j < ing_list.length; j++) {
              +            if (ing_list[j].getAttribute("type") == "checkbox") {
              +                // checkbox
              +                ingredients[j] = ing_list[j].checked;
              +            } else if (ing_list[j].classList.contains("toggle-string")) {
              +                // toggle_string
              +                ingredients[j] = {
              +                    option: ing_list[j].previousSibling.children[0].textContent.slice(0, -1),
              +                    string: ing_list[j].value
              +                };
              +            } else {
              +                // all others
              +                ingredients[j] = ing_list[j].value;
              +            }
              +        }
              +        
              +        item = {
              +            op: operations[i].querySelector(".arg-title").textContent,
              +            args: ingredients
              +        };
              +        
              +        if (disabled && disabled.getAttribute("disabled") == "true") {
              +            item.disabled = true;
              +        }
              +        
              +        if (bp && bp.getAttribute("break") == "true") {
              +            item.breakpoint = true;
              +        }
              +        
              +        config.push(item);
              +    }
              +    
              +    return config;
              +};
              +
              +
              +/**
              + * Moves or removes the breakpoint indicator in the recipe based on the position.
              + *
              + * @param {number} position
              + */
              +RecipeWaiter.prototype.update_breakpoint_indicator = function(position) {
              +    var operations = document.querySelectorAll("#rec_list li.operation");
              +    for (var i = 0; i < operations.length; i++) {
              +        if (i == position) {
              +            operations[i].classList.add("break");
              +        } else {
              +            operations[i].classList.remove("break");
              +        }
              +    }
              +};
              +
              +
              +/**
              + * Given an operation stub element, this function converts it into a full recipe element with
              + * arguments.
              + *
              + * @param {element} el - The operation stub element from the operations pane
              + */
              +RecipeWaiter.prototype.build_recipe_operation = function(el) {
              +    var op_name = el.textContent;
              +    var op = new HTMLOperation(op_name, this.app.operations[op_name], this.app, this.manager);
              +    el.innerHTML = op.to_full_html();
              +    
              +    if (this.app.operations[op_name].flow_control) {
              +        el.classList.add("flow-control-op");
              +    }
              +    
              +    // Disable auto-bake if this is a manual op - this should be moved to the 'operationadd'
              +    // handler after event restructuring
              +    if (op.manual_bake && this.app.auto_bake_) {
              +        this.manager.controls.set_auto_bake(false);
              +        this.app.alert("Auto-Bake is disabled by default when using this operation.", "info", 5000);
              +    }
              +};
              +
              +/**
              + * Adds the specified operation to the recipe.
              + *
              + * @fires Manager#operationadd
              + * @param {string} name - The name of the operation to add
              + * @returns {element}
              + */
              +RecipeWaiter.prototype.add_operation = function(name) {
              +    var item = document.createElement("li");
              +        item.classList.add("operation");
              +        item.innerHTML = name;
              +        this.build_recipe_operation(item);
              +        document.getElementById("rec_list").appendChild(item);
              +    
              +    item.dispatchEvent(this.manager.operationadd);
              +    return item;
              +};
              +
              +
              +/**
              + * Removes all operations from the recipe.
              + *
              + * @fires Manager#operationremove
              + */
              +RecipeWaiter.prototype.clear_recipe = function() {
              +    var rec_list = document.getElementById("rec_list");
              +    while (rec_list.firstChild) {
              +        rec_list.removeChild(rec_list.firstChild);
              +    }
              +    rec_list.dispatchEvent(this.manager.operationremove);
              +};
              +
              +
              +/**
              + * Handler for operation dropdown events from toggle_string arguments.
              + * Sets the selected option as the name of the button.
              + *
              + * @param {event} e
              + */
              +RecipeWaiter.prototype.dropdown_toggle_click = function(e) {
              +    var el = e.target,
              +        button = el.parentNode.parentNode.previousSibling;
              +        
              +    button.innerHTML = el.textContent + " <span class='caret'></span>";
              +    this.ing_change();
              +};
              +
              +
              +/**
              + * Handler for operationadd events.
              + *
              + * @listens Manager#operationadd
              + * @fires Manager#statechange
              + * @param {event} e
              + */
              +RecipeWaiter.prototype.op_add = function(e) {
              +    window.dispatchEvent(this.manager.statechange);
              +};
              +
              +
              +/**
              + * Handler for operationremove events.
              + *
              + * @listens Manager#operationremove
              + * @fires Manager#statechange
              + * @param {event} e
              + */
              +RecipeWaiter.prototype.op_remove = function(e) {
              +    window.dispatchEvent(this.manager.statechange);
              +};
              \ No newline at end of file
              diff --git a/src/js/views/html/SeasonalWaiter.js b/src/js/views/html/SeasonalWaiter.js
              new file mode 100755
              index 00000000..5198c2b4
              --- /dev/null
              +++ b/src/js/views/html/SeasonalWaiter.js
              @@ -0,0 +1,254 @@
              +/**
              + * Waiter to handle seasonal events and easter eggs.
              + *
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @constructor
              + * @param {HTMLApp} app - The main view object for CyberChef.
              + * @param {Manager} manager - The CyberChef event manager.
              + */
              +var SeasonalWaiter = function(app, manager) {
              +    this.app = app;
              +    this.manager = manager;
              +};
              +
              +
              +/**
              + * Loads all relevant items depending on the current date.
              + */
              +SeasonalWaiter.prototype.load = function() {
              +    var now = new Date();
              +    
              +    // Snowfall
              +    if (now.getMonth() == 11 && now.getDate() > 12) { // Dec 13 -> Dec 31
              +        this.app.options.snow = false;
              +        this.create_snow_option();
              +        this.manager.add_dynamic_listener(".option-item input:checkbox[option='snow']", "switchChange.bootstrapSwitch", this.let_it_snow, this);
              +        this.manager.add_window_listener("resize", this.let_it_snow, this);
              +        this.manager.add_listeners(".btn", "click", this.shake_off_snow, this);
              +        if (now.getDate() == 25) this.let_it_snow();
              +    }
              +    
              +    // SpiderChef
              +    // if (now.getMonth() == 3 && now.getDate() == 1) { // Apr 1
              +        // this.insert_spider_icons();
              +        // this.insert_spider_text();
              +    // }
              +    
              +    // Konami code
              +    this.kkeys = [];
              +    window.addEventListener("keydown", this.konami_code_listener.bind(this));
              +};
              +
              +
              +/**
              + * Replaces chef icons with spider icons.
              + * #spiderchef
              + */
              +SeasonalWaiter.prototype.insert_spider_icons = function() {
              +    var spider16 = "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB3UlEQVQ4y2NgGJaAmYGBgVnf0oKJgYGBobWtXamqqoYTn2I4CI+LTzM2NTulpKbu+vPHz2dV5RWlluZmi3j5+KqFJSSEzpw8uQPdAEYYIzo5Kfjrl28rWFlZzjAzMYuEBQao3Lh+g+HGvbsMzExMDN++fWf4/PXLBzY2tqYNK1f2+4eHM2xcuRLigsT09Igf3384MTExbf767etBI319jU8fPsi+//jx/72HDxh5uLkZ7ty7y/Dz1687Avz8n2UUFR3Z2NjOySoqfmdhYGBg+PbtuwI7O8e5H79+8X379t357PnzYo+ePP7y6cuXc9++f69nYGRsvf/w4XdtLS2R799/bBUWFHr57sP7Jbs3b/ZkzswvUP3165fZ7z9//r988WIVAyPDr8tXr576+u3bpb9//7YwMjKeV1dV41NWVGoVEhDgPH761DJREeHaz1+/lqlpafUx6+jrRfz4+fPy+w8fTu/fsf3uw7t3L39+//4cv7DwGQYGhpdPbt9m4BcRFlNWVJC4fuvWASszs4C379792Ldt2xZBUdEdDP5hYSqQGIjDGa965uYKCalpZQwMDAxhMTG9DAwMDLaurhIkJY7A8IgGBgYGBgd3Dz2yUpeFo6O4rasrA9T24ZRxAAMTwMpgEJwLAAAAAElFTkSuQmCC",
              +        spider32 = "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAACYVBMVEUAAAAcJSU2Pz85QkM9RUWEhIWMjI2MkJEcJSU2Pz85QkM9RUWWlpc9RUVXXl4cJSU2Pz85QkM8REU9RUVRWFh6ens9RUVCSkpNVFRdY2McJSU5QkM7REQ9RUVGTk5KUlJQVldcY2Rla2uTk5WampscJSVUWltZX2BrcHF1e3scJSUjLCw9RUVASEhFTU1HTk9bYWJeZGRma2xudHV1eHiZmZocJSUyOjpJUFFQVldSWlpTWVpXXl5YXl5rb3B9fX6RkZIcJSUmLy8tNTU9RUVFTU1IT1BOVldRV1hTWlp0enocJSUfKChJUFBWXV1hZ2hnbGwcJSVETExLUlJLU1NNVVVPVlZYXl9cY2RiaGlobW5rcXFyd3h0eHgcJSUpMTFDS0tQV1dRV1hSWFlWXF1bYWJma2tobW5uc3SsrK0cJSVJUFBMVFROVlZVW1xZX2BdYmNhZ2hjaGhla2tqcHBscHE4Pz9KUlJRWVlSWVlXXF1aYGFbYWFfZWZlampqbW4cJSUgKSkiKysuNjY0PD01PT07QkNES0tHTk5JUFBMUlNMU1NOU1ROVVVPVVZRVlZRV1dSWVlWXFxXXV5aX2BbYWFbYWJcYmJcYmNcY2RdYmNgZmZhZmdkaWpkampkamtlamtla2tma2tma2xnbG1obW5pbG1pb3Bqb3Brb3BtcXJudHVvcHFvcXJvc3NwcXNwdXVxc3RzeXl1eXp2eXl3ent6e3x+gYKAhISBg4SKi4yLi4yWlpeampudnZ6fn6CkpaanqKiur6+vr7C4uLm6urq6u7u8vLy9vb3Av8DR0dL2b74UAAAAgHRSTlMAEBAQEBAQECAgICAgMDBAQEBAQEBAUFBQUGBgYGBgYGBgYGBgcHBwcHCAgICAgICAgICAgICPj4+Pj4+Pj4+Pj5+fn5+fn5+fn5+vr6+vr6+/v7+/v7+/v7+/v7+/z8/Pz8/Pz8/Pz8/P39/f39/f39/f39/f7+/v7+/v7+/v78x6RlYAAAGBSURBVDjLY2AYWUCSgUGAk4GBTdlUhQebvP7yjIgCPQbWzBMnjx5wwJSX37Rwfm1isqj9/iPHTuxYlyeMJi+yunfptBkZOw/uWj9h3vatcycu8eRGlldb3Vsts3ph/cFTh7fN3bCoe2Vf8+TZoQhTvBa6REozVC7cuPvQnmULJm1e2z+308eyJieEBSLPXbKQIUqQIczk+N6eNaumtnZMaWhaHM89m8XVCqJA02Y5w0xmga6yfVsamtrN4xoXNzS0JTHkK3CXy4EVFMumcxUy2LbENTVkZfEzMDAudtJyTmNwS2XQreAFyvOlK9louDNVaXurmjkGgnTMkWDgXswtNouFISEX6Awv+RihQi5OcYY4DtVARpCCFCMGhiJ1hjwFBpagEAaWEpFoC0WQOCOjFMRRwXYMDB4BDLJ+QLYsg7GBGjtasLnEMjCIrWBgyAZ7058FI9x1SoFEnTCDsCyIhynPILYYSFgbYpUDA5bpQBluXzxpI1yYAbd2sCMYRhwAAHB9ZPztbuMUAAAAAElFTkSuQmCC",
              +        spider64 = "iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAJZUlEQVR42u1ZaXMU1xXlJ+gHpFITOy5sAcnIYCi2aIL2bTSSZrSP1NpHK41kISQBHgFaQIJBCMwi4TFUGYcPzggwEMcxHVGxQaag5QR/np/QP+Hmnsdr0hpmtEACwulb9aq7p7d3zz333Pt61q2zzTbbbLPNNttss80222yzzTbbVmu7MzKcJRWVkXjntqam6jyURPeGQqeTpqbOqp+evxC5dGlam5m5rE3PzGi8Hzx/4aLzbXDe09HdYxwZHaPc4mLFXVoW9pRXGNv3pDngeHlNLfE2Ljjj4xPOUGjSYKfpq6/+TLdv36bbX39Nt27epGvXvqSLl6bp3LlPtdOnz7jWrPNZ7kLCKCovp5bOTmP/4EHq6vmYMtzuSKbbbQCAHE8Rxd47MjrmuHjxkjF3/z4tLCzQkyc6PX78mB49ekQPHjygub/P0d27f6FrX/6JpqbO0YkT48E1R/sCr9cYHZ+gqrp64mPq+riXcoqKKC0vP9q6VyV/fQOiH+LrsPVY7z82PBKZnb1Bd+7cpfn5eQbgCT1hAADC/MN5uj83R99881eanZ2lL5gN/nrxjihAXwvOJ7l9vuiBQ4dF9LEtLC0V+2rv/ijTX6luaCS3rxT57wADAMTBQ4c9PIIDg4PBwYOHaHhklM5MnSWkwLff/o0+v3qVHv34Iz344QEDc4d8VVXUEAhQXXMzVdQqzKweKq6oABARzOGNOZ+Wl6fD6T25ubQrPT0E5xF93o82tbdjkkZ+iZfAAgbD6fZ6o339A8S0p7HjJ2h4eIQOHf6EujlV9nX3UOj0JDXzfXje+KlTdOPGDeF0T1+fGHg+2JSen08tHZ0CiPySEoPn8vq1IaOgIAzneQK0UzjcQd6qaqrlCVfV1+tpubnRnv5+2p2ZqYMF/oZGPTh0xLhy5Sr9wLn9j++/p5nLn9FxBoLZQJ1dKrkys6iYNeTExEnx3PqWFuF4W9deKq2upkEGCyzyMBC709MFC7r391Fjayv9MSdHZyCU1xJ5FjrNdN6VnU1KS4CjU4Yoh/m8CsezCguFJgAMV05ueP+BfhF5OL+gL9A/f/qJ7t3TaPLMFB09eoy6mTkMGg2PjTELOsS20OcTACgMKqJugqA0NtE7ycn0202b6A+ZmYIVAAKApGZlgRHB/0lqQPAqFEVE9hntM0R0ZblTzeswWdCeU8HAtYW+Uu0AUx+0f/jwoXD+56c/073v7tHU2XMiFbrUfVTNAtfL10FIAQL2QftsBrOEnavld5kg7E7PoF+99x79ev162rJrV9RMi6a2dvKUlQsR5uAgII7/ivMsbEE4g2hggjzC7LQL1OftovoO0WJKUn0gYEAn2hmMXo4QHIXQIfLfsfOXPwuLvB86cpQqamooyEzg1BLMwv04RkoE+B3B4BBBMHEcCwIP0N+ByJdUVhpgBJ7j4WvdANDjeTUglOaWEChfJF7uJzPX2HEPaj1vg7EAbHO5QnAeIPgqKvUB7gtAdbBgcvKMqOnc/NAIVwCcq21qElFnCgvaI9cBBFKhlSPbPzBIbbzduGULpWzfLkDAdZs++sgEwSlZqoIJMg2CzFSNGzODwdBfOi26+w4YTCm9LhDQwQDzdzguFf4FALjciTws8/u1yyx2N2/dovPnL9DRY8PkZ204xtuhoSM0wI7V8DEiirQCCHD+99u2CUdx3Lmvmz7kfemoGDgPEDr4HNKAf1MlAC4wgMGLWFJXQUrklZSEX6rLE2rOyDIQGlhgBUAyYFEZkm2vAGVi4qQ+x83M0389pevXr6OToy07d4qcR+krr/KzqpeJ/IfjGO+npDx3FCKHVPjd1q2LAMBI3ryZ9vL7U56BEzLfD80ACFba876OlGCQV9dAcT0Pyw7PgWij6zPP5Xt9EYgg+n3LosdVzdfz5CI8KY1LH31+5Yro9KanZwjHmPzmHTsoOeVDemfDBuE8dGVnWpqx3unUrE4CDLCAG64XAHB88IFgQV5xMY7DFmc16A6CZvnNBYYVcW+yKj0A/VHTsQ8dwMPNc6X+Gg0VIGbVpzYGWundjRujmGQWi9Eol7+TJ0/R2Nhx2sNlM9YJRPDdDRsM5DGPJB4KHOIhngHhAwixAGAAuDZ2lsuiYnFWBQOYrdEYNochilyiV6YHoH+rRNJkAG+fUw31PzU7Z1EFKPD69CIuQ1Bm6URoh8tFmVym3nc6rZOPyi0cD8HxeHPg3x2InNrbS79JTsYzNXmPuBclsO3ZvKwAOJEGsmI5rT0M+gSf3y9K5LIA1LUEIlL1k0AhCYBH5r9TCqBqib4D+c/1PyInGOThkvuaHCYALhlpbQWBMGR/4IpzTqlpbKQyf0045vdoe0zATHagSYMeWFMkbscnHRYPZjoFJaIiUkz9EJy15j/X3qCsAIqMcFjSWrNE1Iygg0fEmrtLzEUTdT/OhBFht9fHDVCbEUt3LJxi08B8Xj6vTDESriq9lVWqBECgHujqiqAUmufb1X3cfRXoluhjZWiwkOnSUcUS6ZD8LUmmhks6b5j1ezkAkAKZBe5QvPPcNBnoCawMwT66Qxk0R2xwwRAui2iSDGuaPDcubzo3EJq8wcx/9Vmk3QryH42QBQCFF0UagIiJtjX6DskIXTLEucJSHIIIMuO0BOcjn3A3ybU/lu5RCUBc5qA0Ih0Q2EWiCPRk7VfMNhjLW1zETic1tLYZDMKyuSsdfh5l6bwho5+0il4kyA0VohlNcF5FP8DlWo/VB16HYB2hJ0pzgIe2mcXxP2IOumPRY17U0tll8KIkZNb+sppafOxYkQPSaYfchyYoL9GMqWYpTLRIq1QUcT4O3aPQgqVqPwIOIMwDhzX6mQUFIQAgo+9MzcrWrML3mj6+YIKiFCZyhL87RqVQKrEskF+P1BUvfLCAkfRwoPUtq6l5o5+lZb5SolJo6oT8avTCl+c9OTmat6pKW8mLkvBpGzlvsiGuQr4ZEEwA1EQgoR/gNtxIxKBluz+OtMJiF31jHxqXBiAqAUj4WRxpADFM0DCFlv1khvX7Wol4vF4AIldVVxdZqlrIfiCYQPHDy6bAGv7nKYRVY6JewExZVAP+ey5Rv+Ba97aaUHMW5NauLmMZFkegBb/EP14d6NoS9QLWFSzWBmuZza8CQmSpXsAqmGtVy14VALWuuYWWy+W3OteXa4jwceQX6+BKG6J1/8+2VCNkm2222WabbbbZZpttttlmm22rt38DCdA0vq3bcAkAAAAASUVORK5CYII=";
              +    
              +    // Favicon
              +    document.querySelector("link[rel=icon]").setAttribute("href", "data:image/png;base64," + spider16);
              +    
              +    // Bake button
              +    document.querySelector("#bake img").setAttribute("src", "data:image/png;base64," + spider32);
              +    
              +    // About box
              +    document.querySelector(".about-img-left").setAttribute("src", "data:image/png;base64," + spider64);
              +};
              +
              +
              +/**
              + * Replaces all instances of the word "cyber" with "spider".
              + * #spiderchef
              + */
              +SeasonalWaiter.prototype.insert_spider_text = function() {
              +    // Title
              +    document.title = document.title.replace(/Cyber/g, "Spider");
              +    
              +    // Body
              +    SeasonalWaiter.tree_walk(document.body, function(node) {
              +        // process only text nodes
              +        if (node.nodeType == 3) {
              +            node.nodeValue = node.nodeValue.replace(/Cyber/g, "Spider");
              +        }
              +    }, true);
              +    
              +    // Bake button
              +    SeasonalWaiter.tree_walk(document.getElementById("bake-group"), function(node) {
              +        // process only text nodes
              +        if (node.nodeType == 3) {
              +            node.nodeValue = node.nodeValue.replace(/Bake/g, "Spin");
              +        }
              +    }, true);
              +    
              +    // Recipe title
              +    document.querySelector("#recipe .title").innerHTML = "Web";
              +};
              +
              +
              +/**
              + * Adds an option to make it snow.
              + * #letitsnow
              + */
              +SeasonalWaiter.prototype.create_snow_option = function() {
              +    var options_body = document.getElementById("options-body"),
              +        option_item = document.createElement("div");
              +    
              +    option_item.className = "option-item";
              +    option_item.innerHTML = 
              +        "<input type='checkbox' option='snow' checked />\
              +        Let it snow";
              +    options_body.appendChild(option_item);
              +    
              +    this.manager.options.load();
              +};
              +
              +
              +/**
              + * Initialises a snowstorm.
              + * #letitsnow
              + */
              +SeasonalWaiter.prototype.let_it_snow = function() {
              +    $(document).snowfall("clear");
              +    if (!this.app.options.snow) return;
              +    
              +    var options = {},
              +        firefox_version = navigator.userAgent.match(/Firefox\/(\d\d?)/);
              +    
              +    if (firefox_version && parseInt(firefox_version[1], 10) < 30) {
              +        // Firefox < 30
              +        options = {
              +            flakeCount : 10,
              +            flakeColor : '#fff',
              +            flakePosition: 'absolute',
              +            minSize : 1,
              +            maxSize : 2,
              +            minSpeed : 1,
              +            maxSpeed : 5,
              +            round : false,
              +            shadow : false,
              +            collection : false,
              +            collectionHeight : 20,
              +            deviceorientation : true
              +        };
              +    } else {
              +        // All other browsers
              +        options = {
              +            flakeCount : 35, //35
              +            flakeColor : '#fff',
              +            flakePosition: 'absolute',
              +            minSize : 5,
              +            maxSize : 8,
              +            minSpeed : 1,
              +            maxSpeed : 5,
              +            round : true,
              +            shadow : true,
              +            collection : ".btn",
              +            collectionHeight : 20,
              +            deviceorientation : true
              +        };
              +    }
              +    
              +    $(document).snowfall(options);
              +};
              +
              +/**
              + * When a button is clicked, shake the snow off that button.
              + * #letitsnow
              + */
              +SeasonalWaiter.prototype.shake_off_snow = function(e) {
              +    var el = e.target,
              +        rect = el.getBoundingClientRect(),
              +        canvases = document.querySelectorAll("canvas.snowfall-canvas"),
              +        canvas = null,
              +        remove_func = function() {
              +            ctx.clearRect(0, 0, canvas.width, canvas.height);
              +            $(this).fadeIn();
              +        };
              +    
              +    for (var i = 0; i < canvases.length; i++) {
              +        canvas = canvases[i];
              +        if (canvas.style.left == rect.left + "px" && canvas.style.top == (rect.top - 20) + "px") {
              +            var ctx = canvas.getContext("2d");
              +        
              +            $(canvas).fadeOut("slow", remove_func);
              +            break;
              +        }
              +    }
              +};
              +
              +
              +/**
              + * Listen for the Konami code sequence of keys. Turn the page upside down if they are all heard in
              + * sequence.
              + * #konamicode
              + */
              +SeasonalWaiter.prototype.konami_code_listener = function(e) {
              +    this.kkeys.push(e.keyCode);
              +    var konami = [38,38,40,40,37,39,37,39,66,65];
              +    for (var i = 0; i < this.kkeys.length; i++) {
              +        if (this.kkeys[i] != konami[i]) {
              +            this.kkeys = [];
              +            break;
              +        }
              +        if (i == konami.length - 1) {
              +            $("body").children().toggleClass("konami");
              +            this.kkeys = [];
              +        }
              +    }
              +};
              +
              +
              +/**
              + * Walks through the entire DOM starting at the specified element and operates on each node.
              + *
              + * @static
              + * @param {element} parent - The DOM node to start from
              + * @param {Function} fn - The callback function to operate on each node
              + * @param {booleam} all_nodes - Whether to operate on every node or not
              + */
              +SeasonalWaiter.tree_walk = (function() {
              +    // Create closure for constants
              +    var skipTags = {
              +        "SCRIPT": true, "IFRAME": true, "OBJECT": true, 
              +        "EMBED": true, "STYLE": true, "LINK": true, "META": true
              +    };
              +        
              +    return function(parent, fn, all_nodes) {
              +        var node = parent.firstChild;
              +        
              +        while (node && node != parent) {
              +            if (all_nodes || node.nodeType === 1) {
              +                if (fn(node) === false) {
              +                    return(false);
              +                }
              +            }
              +            // If it's an element &&
              +            //    has children &&
              +            //    has a tagname && is not in the skipTags list
              +            // then, we can enumerate children
              +            if (node.nodeType === 1 &&
              +                node.firstChild &&
              +                !(node.tagName && skipTags[node.tagName])) {
              +                node = node.firstChild;
              +            } else if (node.nextSibling) {
              +                node = node.nextSibling;
              +            } else {
              +                // No child and no nextsibling
              +                // Find parent that has a nextSibling
              +                while ((node = node.parentNode) != parent) {
              +                    if (node.nextSibling) {
              +                        node = node.nextSibling;
              +                        break;
              +                    }
              +                }
              +            }
              +        }
              +    };
              +})();
              diff --git a/src/js/views/html/WindowWaiter.js b/src/js/views/html/WindowWaiter.js
              new file mode 100755
              index 00000000..3f905b62
              --- /dev/null
              +++ b/src/js/views/html/WindowWaiter.js
              @@ -0,0 +1,52 @@
              +/**
              + * Waiter to handle events related to the window object.
              + *
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + *
              + * @constructor
              + * @param {HTMLApp} app - The main view object for CyberChef.
              + */
              +var WindowWaiter = function(app) {
              +    this.app = app;
              +};
              +
              +
              +/**
              + * Handler for window resize events.
              + * Resets the layout of CyberChef's panes after 200ms (so that continuous resizing doesn't cause
              + * continuous resetting).
              + */
              +WindowWaiter.prototype.window_resize = function() {
              +    clearTimeout(this.reset_layout_timeout);
              +    this.reset_layout_timeout = setTimeout(this.app.reset_layout.bind(this.app), 200);
              +};
              +
              +
              +/**
              + * Handler for window blur events.
              + * Saves the current time so that we can calculate how long the window was unfocussed for when
              + * focus is returned.
              + */
              +WindowWaiter.prototype.window_blur = function() {
              +    this.window_blur_time = new Date().getTime();
              +};
              +
              +
              +/**
              + * Handler for window focus events.
              + *
              + * When a browser tab is unfocused and the browser has to run lots of dynamic content in other
              + * tabs, it swaps out the memory for that tab.
              + * If the CyberChef tab has been unfocused for more than a minute, we run a silent bake which will
              + * force the browser to load and cache all the relevant JavaScript code needed to do a real bake.
              + * This will stop baking taking a long time when the CyberChef browser tab has been unfocused for
              + * a long time and the browser has swapped out all its memory.
              + */
              +WindowWaiter.prototype.window_focus = function() {
              +    var unfocused_time = new Date().getTime() - this.window_blur_time;
              +    if (unfocused_time > 60000) {
              +        this.app.silent_bake();
              +    }
              +};
              diff --git a/src/js/views/html/main.js b/src/js/views/html/main.js
              new file mode 100755
              index 00000000..71cbb7ad
              --- /dev/null
              +++ b/src/js/views/html/main.js
              @@ -0,0 +1,49 @@
              +/* globals moment */
              +
              +/**
              + * @author n1474335 [n1474335@gmail.com]
              + * @copyright Crown Copyright 2016
              + * @license Apache-2.0
              + */
              +
              +/**
              + * Main function used to build the CyberChef web app.
              + */
              +var main = function() {
              +    var default_favourites = [
              +        "To Base64",
              +        "From Base64",
              +        "To Hex",
              +        "From Hex",
              +        "To Hexdump",
              +        "From Hexdump",
              +        "URL Decode",
              +        "Regular expression",
              +        "Entropy",
              +        "Fork"
              +    ];
              +    
              +    var default_options = {
              +        update_url          : true,
              +        show_highlighter    : true,
              +        treat_as_utf8       : true,
              +        word_wrap           : true,
              +        show_errors         : true,
              +        error_timeout       : 4000,
              +        auto_bake_threshold : 200,
              +        attempt_highlight   : true,
              +        snow                : false,
              +    };
              +
              +    document.removeEventListener("DOMContentLoaded", main, false);
              +    window.app = new HTMLApp(Categories, OperationConfig, default_favourites, default_options);
              +    window.app.setup();
              +};
              +
              +// Fix issues with browsers that don't support console.log()
              +window.console = console || {log: function() {}, error: function() {}};
              +
              +window.compile_time = moment.tz("<%= grunt.template.today() %>", "ddd MMM D YYYY HH:mm:ss", "UTC").valueOf();
              +window.compile_message = "<%= compile_msg %>";
              +
              +document.addEventListener("DOMContentLoaded", main, false);
              diff --git a/src/static/.htaccess b/src/static/.htaccess
              new file mode 100755
              index 00000000..80626724
              --- /dev/null
              +++ b/src/static/.htaccess
              @@ -0,0 +1,50 @@
              +# Serve up .htm files as binary files rather than text/html.
              +# This allows cyberchef.htm to be downloaded rather than opened in the browser.
              +AddType application/octet-stream .htm
              +
              +# Fix Apache bug #45023 where "-gzip" is appended to all ETags, preventing 304 responses
              +<IfModule mod_headers.c>
              +    RequestHeader edit "If-None-Match" "^\"(.*)-gzip\"$" "\"$1\""
              +    Header edit "ETag" "^\"(.*[^g][^z][^i][^p])\"$" "\"$1-gzip\""
              +</IfModule>
              +
              +# Set gzip compression on all resources that support it
              +<IfModule mod_deflate.c>
              +    SetOutputFilter DEFLATE
              +</IfModule>
              +
              +# Set Expires headers on various resources
              +<IfModule mod_expires.c>
              +    ExpiresActive On
              +    
              +    # 10 minutes
              +    ExpiresDefault "access plus 600 seconds"
              +    
              +    # 30 days
              +    ExpiresByType image/x-icon "access plus 2592000 seconds"
              +    ExpiresByType image/jpeg "access plus 2592000 seconds"
              +    ExpiresByType image/png "access plus 2592000 seconds"
              +    ExpiresByType image/gif "access plus 2592000 seconds"
              +    
              +    # 7 days
              +    ExpiresByType text/css "access plus 604800 seconds"
              +    ExpiresByType text/javascript "access plus 604800 seconds"
              +    ExpiresByType application/javascript "access plus 604800 seconds"
              +    ExpiresByType text/html "access plus 604800 seconds"
              +</IfModule>
              +
              +# Set Cache-Control headers on various resources
              +<IfModule mod_headers.c>
              +    <FilesMatch "\\.(ico|jpe?g|png|gif)$">
              +        Header set Cache-Control "max-age=2592000, public"
              +    </FilesMatch>
              +    <FilesMatch "\\.(css)$">
              +        Header set Cache-Control "max-age=600, public"
              +    </FilesMatch>
              +    <FilesMatch "\\.(js)$">
              +        Header set Cache-Control "max-age=600, private, must-revalidate"
              +    </FilesMatch>
              +    <FilesMatch "\\.(x?html?)$">
              +        Header set Cache-Control "max-age=600, private, must-revalidate"
              +    </FilesMatch>
              +</IfModule>
              diff --git a/src/static/images/breakpoint-16x16.png b/src/static/images/breakpoint-16x16.png
              new file mode 100755
              index 00000000..336df401
              Binary files /dev/null and b/src/static/images/breakpoint-16x16.png differ
              diff --git a/src/static/images/bug-16x16.png b/src/static/images/bug-16x16.png
              new file mode 100755
              index 00000000..8098d345
              Binary files /dev/null and b/src/static/images/bug-16x16.png differ
              diff --git a/src/static/images/clean-16x16.png b/src/static/images/clean-16x16.png
              new file mode 100755
              index 00000000..b61e5668
              Binary files /dev/null and b/src/static/images/clean-16x16.png differ
              diff --git a/src/static/images/code-16x16.png b/src/static/images/code-16x16.png
              new file mode 100755
              index 00000000..a9b8870e
              Binary files /dev/null and b/src/static/images/code-16x16.png differ
              diff --git a/src/static/images/cook_female-32x32.png b/src/static/images/cook_female-32x32.png
              new file mode 100755
              index 00000000..0b00aa35
              Binary files /dev/null and b/src/static/images/cook_female-32x32.png differ
              diff --git a/src/static/images/cook_male-32x32.png b/src/static/images/cook_male-32x32.png
              new file mode 100755
              index 00000000..d881c9f8
              Binary files /dev/null and b/src/static/images/cook_male-32x32.png differ
              diff --git a/src/static/images/cyberchef-128x128.png b/src/static/images/cyberchef-128x128.png
              new file mode 100755
              index 00000000..2b8c71a0
              Binary files /dev/null and b/src/static/images/cyberchef-128x128.png differ
              diff --git a/src/static/images/cyberchef-16x16.png b/src/static/images/cyberchef-16x16.png
              new file mode 100755
              index 00000000..b847c10e
              Binary files /dev/null and b/src/static/images/cyberchef-16x16.png differ
              diff --git a/src/static/images/cyberchef-256x256.png b/src/static/images/cyberchef-256x256.png
              new file mode 100755
              index 00000000..61835a10
              Binary files /dev/null and b/src/static/images/cyberchef-256x256.png differ
              diff --git a/src/static/images/cyberchef-32x32.png b/src/static/images/cyberchef-32x32.png
              new file mode 100755
              index 00000000..640e4756
              Binary files /dev/null and b/src/static/images/cyberchef-32x32.png differ
              diff --git a/src/static/images/cyberchef-512x512.png b/src/static/images/cyberchef-512x512.png
              new file mode 100755
              index 00000000..f48cd49b
              Binary files /dev/null and b/src/static/images/cyberchef-512x512.png differ
              diff --git a/src/static/images/cyberchef-64x64.png b/src/static/images/cyberchef-64x64.png
              new file mode 100755
              index 00000000..5e5a4110
              Binary files /dev/null and b/src/static/images/cyberchef-64x64.png differ
              diff --git a/src/static/images/disable_deselected-16x16.png b/src/static/images/disable_deselected-16x16.png
              new file mode 100755
              index 00000000..0dcaf2b3
              Binary files /dev/null and b/src/static/images/disable_deselected-16x16.png differ
              diff --git a/src/static/images/disable_selected-16x16.png b/src/static/images/disable_selected-16x16.png
              new file mode 100755
              index 00000000..f47a0b95
              Binary files /dev/null and b/src/static/images/disable_selected-16x16.png differ
              diff --git a/src/static/images/download-24x24.png b/src/static/images/download-24x24.png
              new file mode 100755
              index 00000000..058e51b0
              Binary files /dev/null and b/src/static/images/download-24x24.png differ
              diff --git a/src/static/images/erase-16x16.png b/src/static/images/erase-16x16.png
              new file mode 100755
              index 00000000..bc6a3fa4
              Binary files /dev/null and b/src/static/images/erase-16x16.png differ
              diff --git a/src/static/images/favicon.ico b/src/static/images/favicon.ico
              new file mode 100755
              index 00000000..fa2deb03
              Binary files /dev/null and b/src/static/images/favicon.ico differ
              diff --git a/src/static/images/favourite-16x16.png b/src/static/images/favourite-16x16.png
              new file mode 100755
              index 00000000..f6b99459
              Binary files /dev/null and b/src/static/images/favourite-16x16.png differ
              diff --git a/src/static/images/favourite-24x24.png b/src/static/images/favourite-24x24.png
              new file mode 100755
              index 00000000..eb1b91be
              Binary files /dev/null and b/src/static/images/favourite-24x24.png differ
              diff --git a/src/static/images/help-16x16.png b/src/static/images/help-16x16.png
              new file mode 100755
              index 00000000..63a7069f
              Binary files /dev/null and b/src/static/images/help-16x16.png differ
              diff --git a/src/static/images/help-22x22.png b/src/static/images/help-22x22.png
              new file mode 100755
              index 00000000..ddea036d
              Binary files /dev/null and b/src/static/images/help-22x22.png differ
              diff --git a/src/static/images/info-16x16.png b/src/static/images/info-16x16.png
              new file mode 100755
              index 00000000..05f16291
              Binary files /dev/null and b/src/static/images/info-16x16.png differ
              diff --git a/src/static/images/layout-16x16.png b/src/static/images/layout-16x16.png
              new file mode 100755
              index 00000000..3ae4db42
              Binary files /dev/null and b/src/static/images/layout-16x16.png differ
              diff --git a/src/static/images/mail-16x16.png b/src/static/images/mail-16x16.png
              new file mode 100755
              index 00000000..6afab8a8
              Binary files /dev/null and b/src/static/images/mail-16x16.png differ
              diff --git a/src/static/images/open_yellow-16x16.png b/src/static/images/open_yellow-16x16.png
              new file mode 100755
              index 00000000..c849a9e4
              Binary files /dev/null and b/src/static/images/open_yellow-16x16.png differ
              diff --git a/src/static/images/open_yellow-24x24.png b/src/static/images/open_yellow-24x24.png
              new file mode 100755
              index 00000000..7ff52888
              Binary files /dev/null and b/src/static/images/open_yellow-24x24.png differ
              diff --git a/src/static/images/recycle-16x16.png b/src/static/images/recycle-16x16.png
              new file mode 100755
              index 00000000..faff7bf6
              Binary files /dev/null and b/src/static/images/recycle-16x16.png differ
              diff --git a/src/static/images/remove-16x16.png b/src/static/images/remove-16x16.png
              new file mode 100755
              index 00000000..b0cbfb64
              Binary files /dev/null and b/src/static/images/remove-16x16.png differ
              diff --git a/src/static/images/save-16x16.png b/src/static/images/save-16x16.png
              new file mode 100755
              index 00000000..c9df8df6
              Binary files /dev/null and b/src/static/images/save-16x16.png differ
              diff --git a/src/static/images/save-22x22.png b/src/static/images/save-22x22.png
              new file mode 100755
              index 00000000..51183947
              Binary files /dev/null and b/src/static/images/save-22x22.png differ
              diff --git a/src/static/images/save_as-16x16.png b/src/static/images/save_as-16x16.png
              new file mode 100755
              index 00000000..b5d4db8b
              Binary files /dev/null and b/src/static/images/save_as-16x16.png differ
              diff --git a/src/static/images/settings-22x22.png b/src/static/images/settings-22x22.png
              new file mode 100755
              index 00000000..89c7bf6a
              Binary files /dev/null and b/src/static/images/settings-22x22.png differ
              diff --git a/src/static/images/speech-16x16.png b/src/static/images/speech-16x16.png
              new file mode 100755
              index 00000000..5519c5d7
              Binary files /dev/null and b/src/static/images/speech-16x16.png differ
              diff --git a/src/static/images/stats-16x16.png b/src/static/images/stats-16x16.png
              new file mode 100755
              index 00000000..ebd41ef6
              Binary files /dev/null and b/src/static/images/stats-16x16.png differ
              diff --git a/src/static/images/step-16x16.png b/src/static/images/step-16x16.png
              new file mode 100755
              index 00000000..cea525a3
              Binary files /dev/null and b/src/static/images/step-16x16.png differ
              diff --git a/src/static/images/switch-16x16.png b/src/static/images/switch-16x16.png
              new file mode 100755
              index 00000000..4af699e7
              Binary files /dev/null and b/src/static/images/switch-16x16.png differ
              diff --git a/src/static/images/thumb_down-16x16.png b/src/static/images/thumb_down-16x16.png
              new file mode 100755
              index 00000000..69e6663c
              Binary files /dev/null and b/src/static/images/thumb_down-16x16.png differ
              diff --git a/src/static/images/thumb_up-16x16.png b/src/static/images/thumb_up-16x16.png
              new file mode 100755
              index 00000000..0279ee24
              Binary files /dev/null and b/src/static/images/thumb_up-16x16.png differ
              diff --git a/src/static/images/undo-16x16.png b/src/static/images/undo-16x16.png
              new file mode 100755
              index 00000000..a9ba0be9
              Binary files /dev/null and b/src/static/images/undo-16x16.png differ
              diff --git a/src/static/stats.txt b/src/static/stats.txt
              new file mode 100644
              index 00000000..455e65d8
              --- /dev/null
              +++ b/src/static/stats.txt
              @@ -0,0 +1,21 @@
              +202	source files
              +104190	lines
              +	size
              +
              +136	JavaScript source files
              +95118	lines
              +3.4M	size
              +
              +78	third party JavaScript source files
              +76377	lines
              +2.7M	size
              +
              +58	first party JavaScript source files
              +18741	lines
              +724K	size
              +
              +3.1M	uncompressed JavaScript size
              +1.7M	compressed JavaScript size
              +
              +15	categories
              +152	operations