1f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch# encoding: ASCII-8BIT 2f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 3f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch# iExploder - Generates bad HTML files to perform QA for web browsers. 4f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch# 5f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch# Copyright 2010 Thomas Stromberg - All Rights Reserved. 6f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch# 7f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch# Licensed under the Apache License, Version 2.0 (the "License"); 8f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch# you may not use this file except in compliance with the License. 9f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch# You may obtain a copy of the License at 10f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch# 11f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch# http://www.apache.org/licenses/LICENSE-2.0 12f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch# 13f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch# Unless required by applicable law or agreed to in writing, software 14f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch# distributed under the License is distributed on an "AS IS" BASIS, 15f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch# See the License for the specific language governing permissions and 17f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch# limitations under the License. 18f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 19f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochrequire 'cgi' 20f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochrequire 'yaml' 21f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 22f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochrequire './scanner.rb' 23f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochrequire './version.rb' 24f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 25f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch# Used to speed up subtest generation 26f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch$TEST_CACHE = {} 27f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 28f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch# Media extensions to proper mime type map (not that we always listen' 29f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch$MIME_MAP = { 30f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 'bmp' => 'image/bmp', 31f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 'gif' => 'image/gif', 32f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 'jpg' => 'image/jpeg', 33f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 'png' => 'image/png', 34f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 'svg' => 'image/svg+xml', 35f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 'tiff' => 'image/tiff', 36f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 'xbm' => 'image/xbm', 37f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 'ico' => 'image/x-icon', 38f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 'jng' => 'image/x-jng', 39f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 'xpm' => 'image/x-portable-pixmap', 40f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 'ogg' => 'audio/ogg', 41f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 'snd' => 'audio/basic', 42f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 'wav' => 'audio/wav' 43f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} 44f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 45f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch# These tags get src properties more often than others 46f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch$SRC_TAGS = ['img', 'audio', 'video', 'embed'] 47f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 48f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochclass IExploder 49f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch attr_accessor :test_num, :subtest_data, :lookup_mode, :random_mode, :cgi_url, :browser, :claimed_browser 50f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch attr_accessor :offset, :lines, :stop_num, :config 51f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 52f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch def initialize(config_path) 53f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch @config = YAML::load(File.open(config_path)) 54f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch @stop_num = nil 55f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch @subtest_data = nil 56f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch @test_num = 0 57f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch @cgi_url = '/iexploder.cgi' 58f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch @browser = 'UNKNOWN' 59f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch @claimed_browser = nil 60f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch readTagFiles() 61f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return nil 62f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 63f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 64f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch def setRandomSeed 65f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if @test_num > 0 66f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch srand(@test_num) 67f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch else 68f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch srand 69f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 70f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 71f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 72f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 73f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch def readTagFiles 74f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch # These if statements are so that mod_ruby doesn't have to reload the files 75f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch # each time 76f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch data_path = @config['mangle_data_path'] 77f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch @cssTags = readTagsDir("#{data_path}/css-properties") 78f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch @cssPseudoTags = readTagsDir("#{data_path}/css-pseudo") 79f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch @cssAtRules = readTagsDir("#{data_path}/css-atrules") 80f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch @htmlTags = readTagsDir("#{data_path}/html-tags") 81f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch @htmlAttr = readTagsDir("#{data_path}/html-attrs") 82f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch @htmlValues = readTagsDir("#{data_path}/html-values") 83f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch @cssValues = readTagsDir("#{data_path}/css-values") 84f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch @headerValues = readTagsDir("#{data_path}/headers") 85f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch @protocolValues = readTagsDir("#{data_path}/protocols") 86f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch @mimeTypes = readTagsDir("#{data_path}/mime-types") 87f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch @media = readMediaDir("#{data_path}/media") 88f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 89f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 90f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch def readTagsDir(directory) 91f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch values = [] 92f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch Dir.foreach(directory) { |filename| 93f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if File.file?(directory + "/" + filename) 94f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch values = values + readTagFile(directory + "/" + filename) 95f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 96f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } 97f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return values.uniq 98f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 99f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 100f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch def readMediaDir(directory) 101f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch data = {} 102f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch Dir.foreach(directory) { |filename| 103f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if File.file?(directory + "/" + filename) 104f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch (base, extension) = filename.split('.') 105f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch mime_type = $MIME_MAP[extension] 106f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch data[mime_type] = File.read(directory + "/" + filename) 107f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 108f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } 109f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return data 110f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 111f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 112f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch def readTagFile(filename) 113f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch list = Array.new 114f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch File.new(filename).readlines.each { |line| 115f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch line.chop! 116f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 117f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch # Don't include comments. 118f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (line !~ /^# /) && (line.length > 0) 119f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch list << line 120f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 121f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } 122f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return list 123f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 124f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 125f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 126f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch def generateHtmlValue(tag) 127f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch choice = rand(100) 128f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch tag = tag.sub('EXCLUDED_', '') 129f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if tag =~ /^on/ and choice < 90 130f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return generateHtmlValue('') + "()" 131f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch elsif tag == 'src' or tag == 'data' or tag == 'profile' and choice < 90 132f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return generateGarbageUrl(tag) 133f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 134f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 135f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch case choice 136f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when 0..50 then 137f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return @htmlValues[rand(@htmlValues.length)] 138f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when 51..75 139f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return generateGarbageNumber() 140f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when 76..85 141f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return generateGarbageValue() 142f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when 86..90 143f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return generateGarbageNumber() + ',' + generateGarbageNumber() 144f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when 91..98 145f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return generateGarbageUrl(tag) 146f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch else 147f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return generateOverflow() 148f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 149f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 150f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 151f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch def generateMediaUrl(tag) 152f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch mime_type = @media.keys[rand(@media.keys.length)] 153f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return generateTestUrl(@test_num, nil, nil, mime_type) 154f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 155f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 156f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch def generateGarbageUrl(tag) 157f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch choice = rand(100) 158f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch case choice 159f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when 0..30 160f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return generateMediaUrl(tag) 161f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when 31..50 162f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return @protocolValues[rand(@protocolValues.length)] + '%' + generateGarbageValue() 163f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when 51..60 164f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return @protocolValues[rand(@protocolValues.length)] + '//../' + generateGarbageValue() 165f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when 60..75 166f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return @protocolValues[rand(@protocolValues.length)] + '//' + generateGarbageValue() 167f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when 75..85 168f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return generateOverflow() + ":" + generateGarbageValue() 169f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when 86..97 170f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return generateGarbageValue() + ":" + generateOverflow() 171f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch else 172f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return generateOverflow() 173f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 174f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 175f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 176f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch def generateCssValue(property) 177f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch size_types = ['', 'em', 'px', '%', 'pt', 'pc', 'ex', 'in', 'cm', 'mm'] 178f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 179f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch choice = rand(100) 180f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch case choice 181f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when 0..50 then 182f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch # return the most likely scenario 183f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch case property.sub('EXCLUDED_', '') 184f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when /-image|content/ 185f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return 'url(' + generateGarbageUrl(property) + ')' 186f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when /-width|-radius|-spacing|margin|padding|height/ 187f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return generateGarbageValue() + size_types[rand(size_types.length)] 188f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when /-color/ 189f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return generateGarbageColor() 190f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when /-delay|-duration/ 191f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return generateGarbageValue() + 'ms' 192f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch else 193f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return @cssValues[rand(@cssValues.length)] 194f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 195f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when 51..75 then return generateGarbageNumber() 196f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when 76..85 then return 'url(' + generateGarbageUrl(property) + ')' 197f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when 85..98 then return generateGarbageValue() 198f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch else 199f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return generateOverflow() 200f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 201f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 202f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 203f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch def generateGarbageColor() 204f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch case rand(100) 205f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when 0..50 then return '#' + generateGarbageValue() 206f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when 51..70 then return 'rgb(' + generateGarbageNumber() + ',' + generateGarbageNumber() + ',' + generateGarbageNumber() + ')' 207f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when 71..98 then return 'rgb(' + generateGarbageNumber() + '%,' + generateGarbageNumber() + '%,' + generateGarbageNumber() + '%)' 208f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch else 209f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return generateOverflow() 210f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 211f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 212f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 213f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch def generateGarbageNumber() 214f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch choice = rand(100) 215f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch case choice 216f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when 0 then return '0' 217f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when 1..40 then return '9' * rand(100) 218f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when 41..60 then return '999999.' + rand(999999999999999999999).to_s 219f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when 61..80 then return '-' + ('9' * rand(100)) 220f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when 81..90 then return '-999999.' + rand(999999999999999999999).to_s 221f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when 91..98 then return generateGarbageText() 222f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch else 223f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return generateOverflow() 224f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 225f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 226f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 227f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch def generateGarbageValue() 228f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch case rand(100) 229f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when 0..30 then return rand(255).chr * rand(@config['buffer_overflow_length']) 230f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when 31..50 then return "%n" * 50 231f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when 51..65 then return ("&#" + rand(999999).to_s + ";") * rand(@config['max_garbage_text_size']) 232f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when 66..70 then 233f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch junk = [] 234f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 0.upto(rand(20)+1) do 235f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch junk << "\\x" + rand(65535).to_s(16) 236f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 237f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return junk.join('') * rand(@config['max_garbage_text_size']) 238f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when 71..99 then 239f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch junk = [] 240f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch chars = '%?!$#^0123456789ABCDEF%#./\&|;' 241f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 0.upto(rand(20)+1) do 242f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch junk << chars[rand(chars.length)].chr 243f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 244f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return junk.join('') * rand(@config['max_garbage_text_size']) 245f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 246f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 247f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 248f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch def generateOverflow() 249f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return rand(255).chr * (@config['buffer_overflow_length'] + rand(500)) 250f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 251f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 252f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch def generateGarbageText 253f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch case rand(100) 254f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when 0..70 then return 'X' * 129 255f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when 71..75 then return "%n" * 15 256f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when 76..85 then return ("&#" + rand(9999999999999).to_s + ";") * rand(@config['max_garbage_text_size']) 257f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when 86..90 then return generateGarbageValue() 258f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when 91..98 then return rand(255).chr * rand(@config['max_garbage_text_size']) 259f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch else 260f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return generateOverflow() 261f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 262f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 263f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 264f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch def isPropertyInBlacklist(properties) 265f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch # Format: [img, src] or [img, style, property] 266f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch blacklist_entries = [] 267f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if @config.has_key?('exclude') and @config['exclude'] 268f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch blacklist_entries << properties.join('.') 269f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch wildcard_property = properties.dup 270f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch wildcard_property[0] = '*' 271f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch blacklist_entries << wildcard_property.join('.') 272f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch blacklist_entries.each do |entry| 273f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if @config['exclude'].has_key?(entry) and @browser =~ /#{@config['exclude'][entry]}/ 274f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return true 275f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 276f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 277f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 278f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return false 279f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 280f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 281f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch def generateCssStyling(tag) 282f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch out = ' style="' 283f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 0.upto(rand(@config['properties_per_style_max'])) { 284f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch property = @cssTags[rand(@cssTags.length)] 285f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if isPropertyInBlacklist([tag, 'style', property]) 286f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch property = "EXCLUDED_#{property}" 287f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 288f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch out << property 289f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 290f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch # very small chance we let the tag run on. 291f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if rand(65) > 1 292f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch out << ": " 293f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 294f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 295f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch values = [] 296f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 0.upto(rand(@config['attributes_per_style_property_max'])) { 297f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch values << generateCssValue(property) 298f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } 299f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch out << values.join(' ') 300f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch # we almost always put the ; there. 301f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if rand(65) > 1 302f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch out << ";\n " 303f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 304f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } 305f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch out << "\"" 306f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return out 307f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 308f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 309f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch def mangleTag(tag, no_close_chance=false) 310f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if not no_close_chance and rand(100) < 15 311f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return "</" + tag + ">" 312f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 313f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch out = "<" + tag 314f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if rand(100) > 1 315f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch out << ' ' 316f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch else 317f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch out << generateOverflow() 318f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 319f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 320f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch attrNum = rand(@config['attributes_per_html_tag_max']) + 1 321f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch attrs = [] 322f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch # The HTML head tag does not have many useful attributes, but is always included in tests. 323f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if tag == 'head' and rand(100) < 75 324f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch case rand(3) 325f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when 0 then attrs << 'lang' 326f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when 1 then attrs << 'dir' 327f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when 2 then attrs << 'profile' 328f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 329f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 330f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch # 75% of the time, these tags get a src attribute 331f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if $SRC_TAGS.include?(tag) and rand(100) < 75 332f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if @config.has_key?('exclude') and @config['exclude'] and @config['exclude'].has_key?("#{tag}.src") 333f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch attrs << 'EXCLUDED_src' 334f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch else 335f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch attrs << 'src' 336f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 337f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 338f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 339f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch while attrs.length < attrNum 340f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch attribute = @htmlAttr[rand(@htmlAttr.length)] 341f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if isPropertyInBlacklist([tag, attribute]) 342f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch attribute = "EXCLUDED_#{attribute}" 343f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 344f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch attrs << attribute 345f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 346f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 347f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch # Add a few HTML attributes 348f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch for attr in attrs 349f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch out << attr 350f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if rand(100) > 1 351f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch out << '=' 352f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 353f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (rand(100) >= 50) 354f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch quoted = 1 355f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch out << "\"" 356f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch else 357f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch quoted = nil 358f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 359f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch out << generateHtmlValue(attr) 360f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if quoted 361f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if rand(100) >= 10 362f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch out << "\"" 363f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 364f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 365f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if rand(100) >= 1 366f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch out << "\n " 367f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 368f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 369f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 370f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if rand(100) >= 25 371f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch out << generateCssStyling(tag) 372f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 373f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch out << ">\n" 374f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return out 375f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 376f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 377f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch def nextTestNum() 378f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if @subtest_data 379f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return @test_num 380f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch elsif @random_mode 381f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return rand(99999999999) 382f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch else 383f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return @test_num + 1 384f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 385f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 386f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 387f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch def generateCssPattern() 388f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch # Generate a CSS selector pattern. 389f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch choice = rand(100) 390f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch pattern = '' 391f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch case choice 392f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when 0..84 then pattern = @htmlTags[rand(@htmlTags.length)].dup 393f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when 85..89 then pattern = "*" 394f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when 90..94 then pattern = @cssAtRules[rand(@cssAtRules.length)].dup 395f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when 95..100 then pattern = '' 396f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 397f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 398f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if rand(100) < 25 399f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch pattern << " " + @htmlTags[rand(@htmlTags.length)] 400f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 401f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 402f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if rand(100) < 25 403f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch pattern << " > " + @htmlTags[rand(@htmlTags.length)] 404f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 405f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 406f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if rand(100) < 25 407f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch pattern << " + " + @htmlTags[rand(@htmlTags.length)] 408f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 409f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 410f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if rand(100) < 10 411f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch pattern << "*" 412f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 413f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 414f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 415f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if rand(100) < 25 416f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch pseudo = @cssPseudoTags[rand(@cssPseudoTags.length)].dup 417f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch # These tags typically have a parenthesis 418f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if (pseudo =~ /^lang|^nth|^not/ and rand(100) < 75 and pseudo !~ /\(/) or rand(100) < 20 419f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch pseudo << '(' 420f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 421f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 422f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if pseudo =~ /\(/ 423f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if rand(100) < 75 424f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch pseudo << generateGarbageValue() 425f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 426f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if rand(100) < 75 427f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch pseudo << ')' 428f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 429f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 430f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch pattern << ":" + pseudo 431f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 432f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 433f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if rand(100) < 20 434f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch html_attr = @htmlAttr[rand(@htmlAttr.length)] 435f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch match = '[' + html_attr 436f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch choice = rand(100) 437f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch garbage = generateGarbageValue() 438f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch case choice 439f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when 0..25 then match << ']' 440f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when 26..50 then match << "=\"#{garbage}\"]" 441f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when 51..75 then match << "=~\"#{garbage}\"]" 442f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch when 76..99 then match << "|=\"#{garbage}\"]" 443f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 444f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch pattern << match 445f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 446f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 447f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if rand(100) < 20 448f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if rand(100) < 50 449f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch pattern << '.' + generateGarbageValue() 450f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch else 451f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch pattern << '.*' 452f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 453f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 454f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 455f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if rand(100) < 20 456f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch pattern << '#' + generateGarbageValue() 457f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 458f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 459f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if rand(100) < 5 460f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch pattern << ' #' + generateGarbageValue() 461f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 462f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 463f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return pattern 464f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 465f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 466f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch def buildStyleTag() 467f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch out = "\n" 468f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 0.upto(rand(@config['properties_per_style_max'])) { 469f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch out << generateCssPattern() 470f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if rand(100) < 90 471f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch out << " {\n" 472f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 473f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 474f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 0.upto(rand(@config['properties_per_style_max'])) { 475f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch property = @cssTags[rand(@cssTags.length)].dup 476f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if isPropertyInBlacklist(['style', 'style', property]) 477f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch property = " EXCLUDED_#{property}" 478f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 479f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch out << " #{property}: " 480f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 481f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch values = [] 482f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 0.upto(rand(@config['attributes_per_style_property_max'])) { 483f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch values << generateCssValue(property) 484f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } 485f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch out << values.join(' ') 486f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if rand(100) < 95 487f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch out << ";\n" 488f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 489f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } 490f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if rand(100) < 90 491f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch out << "\n}\n" 492f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 493f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 494f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } 495f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return out 496f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 497f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 498f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 499f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch # Build any malicious javascript here. Fairly naive at the moment. 500f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch def buildJavaScript 501f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch target = @htmlTags[rand(@htmlTags.length)] 502f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch css_property = @cssTags[rand(@cssTags.length)] 503f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch css_property2 = @cssTags[rand(@cssTags.length)] 504f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch html_attr = @htmlAttr[rand(@htmlAttr.length)] 505f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch css_value = generateCssValue(css_property) 506f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch html_value = generateHtmlValue(html_attr) 507f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch html_value2 = generateGarbageNumber() 508f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch mangled = mangleTag(@htmlTags[rand(@htmlTags.length)]); 509f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch mangled2 = mangleTag(@htmlTags[rand(@htmlTags.length)]); 510f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 511f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch js = [] 512f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch js << "window.onload=function(){" 513f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch js << " var ietarget = document.createElement('#{target}');" 514f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch js << " ietarget.style.#{css_property} = '#{css_value}';" 515f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch js << " ietarget.#{html_attr} = '#{html_value}';" 516f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch js << " document.body.appendChild(ietarget);" 517f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch js << " ietarget.style.#{css_property2} = #{html_value2};" 518f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 519f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch js << " document.write('#{mangled}');" 520f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch js << " document.write('#{mangled2}');" 521f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch js << "}" 522f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return js.join("\n") 523f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 524f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 525f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch def buildMediaFile(mime_type) 526f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if @media.has_key?(mime_type) 527f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch data = @media[mime_type].dup 528f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch else 529f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch puts "No media found for #{mime_type}" 530f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch data = generateGarbageText() 531f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 532f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 533f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch # corrupt it in a subtle way 534f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch choice = rand(100) 535f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if choice > 50 536f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch garbage = generateGarbageValue() 537f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch else 538f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch garbage = rand(255).chr * rand(8) 539f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 540f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 541f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if "1.9".respond_to?(:encoding) 542f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch garbage.force_encoding('ASCII-8BIT') 543f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch data.force_encoding('ASCII-8BIT') 544f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 545f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 546f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch garbage_start = rand(data.length) 547f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch garbage_end = garbage_start + garbage.length 548f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch data[garbage_start..garbage_end] = garbage 549f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if rand(100) < 15 550f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch data << generateGarbageValue() 551f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 552f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return data 553f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 554f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 555f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch # Parse the subtest data passed in as part of the URL 556f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch def parseSubTestData(subtest_data) 557f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch # Initialize with one line at 0 558f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if not subtest_data or subtest_data.to_i == 0 559f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return [@config['initial_subtest_width'], [0]] 560f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 561f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch (lines_at_time, offsets_string) = subtest_data.split('_') 562f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch offsets = offsets_string.split(',').map! {|x| x.to_i } 563f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return [lines_at_time.to_i, offsets] 564f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 565f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 566f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch def generateTestUrl(test_num, subtest_width=nil, subtest_offsets=nil, mime_type=nil) 567f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch url = @cgi_url + '?' 568f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if subtest_width 569f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if subtest_offsets.length > @config['subtest_combinations_max'] 570f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch url << "t=" << test_num.to_s << "&l=test_redirect&z=THE_END" 571f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch else 572f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch url << "t=" << test_num.to_s << "&s=" << subtest_width.to_s << "_" << subtest_offsets.join(',') 573f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 574f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch else 575f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch url << "t=" << test_num.to_s 576f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 577f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 578f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if @random_mode 579f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch url << "&r=1" 580f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch elsif @stop_num 581f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch url << "&x=" << @stop_num.to_s 582f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 583f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 584f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if mime_type 585f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch url << '&m=' + CGI::escape(mime_type) 586f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 587f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 588f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch url << "&b=" << CGI::escape(@browser) 589f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return url 590f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 591f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 592f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch def buildBodyTags(tag_count) 593f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch tagList = ['body'] 594f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch # subtract the <body> tag from tag_count. 595f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 1.upto(tag_count-1) { tagList << @htmlTags[rand(@htmlTags.length)] } 596f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 597f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch # Lean ourselves toward lots of img and src tests 598f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch for tag, percent in @config['favor_html_tags'] 599f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if rand(100) < percent.to_f 600f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch # Don't overwrite the body tag. 601f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch tagList[rand(tagList.length-1)+1] = tag 602f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 603f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 604f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 605f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch # Now we have our hitlist of tags,lets mangle them. 606f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch mangled_tags = [] 607f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch tagList.each do |tag| 608f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch tag_data = mangleTag(tag) 609f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if tag == 'script' 610f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if rand(100) < 40 611f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch tag_data = "<script>" 612f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 613f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch tag_data << buildJavaScript() + "\n" + "</script>\n" 614f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch elsif tag == 'style' 615f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if rand(100) < 40 616f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch tag_data = "<style>" 617f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 618f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch tag_data << buildStyleTag() + "\n" + "</style>\n" 619f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch elsif rand(100) <= 90 620f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch tag_data << generateGarbageText() << "\n" 621f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch else 622f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch tag_data << "\n" 623f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 624f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 625f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if rand(100) <= 33 626f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch tag_data << "</#{tag}>\n" 627f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 628f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch mangled_tags << "\n<!-- START #{tag} -->\n" + tag_data + "\n<!-- END #{tag} -->\n" 629f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 630f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return mangled_tags 631f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 632f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 633f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch def buildHeaderTags(tag_count) 634f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch valid_head_tags = ['title', 'base', 'link', 'meta'] 635f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch header_tags = ['html', 'head'] 636f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 1.upto(tag_count-1) { header_tags << valid_head_tags[rand(valid_head_tags.length)] } 637f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch header_tags << @htmlTags[rand(@htmlTags.length)] 638f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch mangled_tags = [] 639f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch header_tags.each do |tag| 640f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch mangled_tags << mangleTag(tag, no_close_chance=true) 641f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 642f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return mangled_tags 643f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 644f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 645f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch def buildSurvivedPage(page_type) 646f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch page = "<html><head>" 647f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch page << "<body>Bummer. You survived both redirects. Let me go sulk in the corner.</body>" 648f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch page << "</html>" 649f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return page 650f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 651f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 652f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch def buildRedirect(test_num, subtest_data, lookup_mode, stop_num=nil) 653f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch # no more redirects. 654f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if lookup_mode == '1' or stop_num == test_num 655f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return '' 656f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 657f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 658f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if subtest_data 659f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch width, offsets = parseSubTestData(@subtest_data) 660f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch else 661f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch width, offsets = nil 662f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 663f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 664f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch # We still need a redirect, but don't bother generating new data. 665f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if lookup_mode 666f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch redirect_url = generateTestUrl(test_num, width, offsets) 667f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if lookup_mode == 'test_redirect' 668f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch redirect_url << "&l=test_another_redirect" 669f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch elsif lookup_mode == 'test_another_redirect' 670f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch redirect_url << "&l=survived_redirect" 671f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch else 672f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch redirect_url << "&l=#{lookup_mode}" 673f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 674f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch else 675f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch # This is a normal redirect going on to the next page. If we have subtest, get the next one. 676f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if subtest_data 677f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch width, offsets = combine_combo_creator(@config['html_tags_per_page'], width, offsets)[0..1] 678f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 679f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch redirect_url = generateTestUrl(nextTestNum(), width, offsets) 680f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 681f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 682f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch redirect_code = "\t<META HTTP-EQUIV=\"Refresh\" content=\"0;URL=#{redirect_url}\">\n" 683f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch # use both techniques, because you never know how you might be corrupting yourself. 684f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch redirect_code << "\t<script language=\"javascript\">setTimeout('window.location=\"#{redirect_url}\"', 1000);</script>\n" 685f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return redirect_code 686f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 687f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 688f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch def buildPage() 689f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if @lookup_mode == 'survived_redirect' 690f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return self.buildSurvivedPage(@lookup_mode) 691f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 692f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch tag_count = @config['html_tags_per_page'] 693f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 694f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if $TEST_CACHE.has_key?(@test_num) 695f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch (header_tags, body_tags) = $TEST_CACHE[@test_num] 696f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch else 697f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch header_tags = buildHeaderTags(3) 698f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch body_tags = buildBodyTags(tag_count - header_tags.length) 699f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 700f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch required_tags = { 701f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 0 => 'html', 702f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 1 => 'head', 703f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch header_tags.length => 'body' 704f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch } 705f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 706f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if @subtest_data and @subtest_data.length > 0 707f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if not $TEST_CACHE.has_key?(@test_num) 708f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch $TEST_CACHE[@test_num] = [header_tags, body_tags] 709f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 710f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch (width, offsets) = parseSubTestData(@subtest_data) 711f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch lines = combine_combo_creator(tag_count, width, offsets)[2] 712f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch all_tags = header_tags + body_tags 713f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch body_start = header_tags.length 714f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch header_tags = [] 715f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch body_tags = [] 716f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch # <html> and <body> are required, regardless of their existence in the subtest data. 717f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 0.upto(tag_count) do |line_number| 718f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch tag_data = nil 719f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if lines.include?(line_number) 720f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch tag_data = all_tags[line_number] 721f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch elsif required_tags.key?(line_number) 722f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch tag_data = "<" + required_tags[line_number] + ">" 723f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 724f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if tag_data 725f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if line_number < body_start 726f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch header_tags << tag_data 727f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch else 728f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch body_tags << tag_data 729f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 730f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 731f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 732f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch header_tags << "<!-- subtest mode: #{offsets.length} combinations, width: #{width} -->" 733f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 734f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 735f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch htmlText = header_tags[0..1].join("\n\t") 736f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch htmlText << buildRedirect(@test_num, @subtest_data, @lookup_mode, @stop_num) 737f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch htmlText << "<title>[#{@test_num}:#{@subtest_data}] iExploder #{$VERSION} - #{generateGarbageText()}</title>\n" 738f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if @claimed_browser and @claimed_browser.length > 1 739f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch show_browser = @claimed_browser 740f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch else 741f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch show_browser = @browser 742f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 743f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch htmlText << "\n<!-- iExploder #{$VERSION} | test #{@test_num}:#{@subtest_data} at #{Time.now} -->\n" 744f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch htmlText << "<!-- browser: #{show_browser} -->\n" 745f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch htmlText << header_tags[2..-1].join("\n\t") 746f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch htmlText << "\n</head>\n\n" 747f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch htmlText << body_tags.join("\n") 748f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch htmlText << "</body>\n</html>" 749f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return htmlText 750f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 751f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 752f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch def buildHeaders(mime_type) 753f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch use_headers = [] 754f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch banned_headers = [] 755f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch response = {'Content-Type' => mime_type} 756f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 0.upto(rand(@config['headers_per_page_max'])) do 757f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch try_header = @headerValues[rand(@headerValues.length)] 758f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if ! banned_headers.include?(try_header.downcase) 759f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch use_headers << try_header 760f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 761f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 762f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch for header in use_headers.uniq 763f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if rand(100) > 75 764f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch response[header] = generateGarbageNumber() 765f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch else 766f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch response[header] = generateGarbageUrl(header) 767f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 768f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 769f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch return response 770f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 771f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochend 772f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 773f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch 774f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch# for testing 775f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochif $0 == __FILE__ 776f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch ie = IExploder.new('config.yaml') 777f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch ie.test_num = ARGV[0].to_i || 1 778f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch ie.subtest_data = ARGV[1] || nil 779f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch mime_type = ARGV[2] || nil 780f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch ie.setRandomSeed() 781f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch if not mime_type 782f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch html_output = ie.buildPage() 783f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch puts html_output 784f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch else 785f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch headers = ie.buildHeaders(mime_type) 786f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch for (key, value) in headers 787f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch puts "#{key}: #{value}" 788f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 789f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch puts "Mime-Type: #{mime_type}" 790f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch puts ie.buildMediaFile(mime_type) 791f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch end 792f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochend 793