diff --git a/Node.js/index.js b/Node.js/index.js new file mode 100644 index 0000000..80c31c9 --- /dev/null +++ b/Node.js/index.js @@ -0,0 +1,76 @@ +const https = require('https') +const http = require('http') +const fs = require('fs') + +async function main_loop() { + for (let i = 0; i < times; i++) { + const url = await url_generator(domains, mode, log) + try { + const response = await fetch(url) + console.log(`${url} exists!`) + fs.appendFile("JS_report.txt", "\n" + url + " | STATUS_CODE: " + String(response.statusCode), function(err) {if (err) throw err}) + } + catch(e) { + if (e.errno != 'ENOTFOUND') { + console.log(`${url} exists!`) + fs.appendFile("JS_report.txt", "\n" + url + " | ERROR_CODE: " + e.errno, function(err) {if (err) throw err}) + } + } + } + fs.appendFile("JS_report.txt", "\n---\n", function(err) {if (err) throw err}) + console.log('\nFinished at ' + String(new Date().getHours()) + 'h' + String(new Date().getMinutes()) + 'm') +} + +function url_generator(domains, mode, log) { + let result = mode[Math.round(Math.random() * (mode.length - 1))] + "://" + const characters = "abcdefghijklmnopqrstuvwxyz0123456789" + const url_length = Math.floor(Math.random() * (30 - 2) + 2) + for (let i = 0; i < url_length; i++) { + result += characters.charAt(Math.floor(Math.random() * characters.length)) + } + result += domains[Math.floor(Math.random() * domains.length)] + if (log) console.log(result) + return result +} + +function fetch(url, options = {}) { + return new Promise((resolve, reject) => { + if (!url) return reject(new Error('URL was not provided')) + + const { body, method = 'GET', ...restOptions } = options + const client = url.startsWith('https') ? https : http + const request = client.request(url, { method, ...restOptions }, (res) => { + let chunks = '' + res.setEncoding('utf8') + res.on('data', (chunk) => { + chunks += chunk + }) + res.on('end', () => { + resolve({ statusCode: res.statusCode, body: chunks }) + }) + }) + request.on('error', (err) => { + reject(err) + }) + if (body) { + request.setHeader('Content-Length', body.length) + request.write(body) + } + request.end() + }) +} + +const times = process.argv.indexOf('-t') > -1 ? Math.round(Number(process.argv[process.argv.indexOf('-t') + 1])) : 3000 +if (isNaN(times)) return console.error("-t argument expected a number!") +const domains = process.argv.indexOf('-d') > -1 ? process.argv[process.argv.indexOf('-d') + 1].split(',') : ['.com', '.net', '.edu', '.gov', '.cn', '.org'] +const mode = process.argv.indexOf('-m') > -1 ? process.argv[process.argv.indexOf('-m') + 1].split(',') : ['http'] +const log = process.argv.indexOf('-l') > -1 + +process.stdout.write(`\nI am going to look for images through ${times} random URLs with the following domains: `) +console.log(domains) +process.stdout.write("These URLs will use the following protocols: ") +console.log(mode) +console.log('Started at ' + String(new Date().getHours()) + 'h' + String(new Date().getMinutes()) + 'm\n') + +fs.appendFile("JS_report.txt", "---", function(err) {if (err) throw err}) +main_loop() diff --git a/Python/index.py b/Python/index.py new file mode 100644 index 0000000..627db38 --- /dev/null +++ b/Python/index.py @@ -0,0 +1,48 @@ +import sys +import random +import datetime +import urllib.request + +def main_loop(): + for i in range(times): + url = url_generator(domains, log) + try: + response = urllib.request.urlopen(url) + print(url + " exists!") + f.write("\n" + url + " | STATUS_CODE: " + str(response.getcode())) + except Exception as e: + if "[Errno 11001]" in str(e): continue + if "[" in str(e) and "]" in str(e): e = str(e)[str(e).index("[") + 1:str(e).index("]")] + ": " + str(e)[str(e).index("]") + 2:][:-1] + print(url + " exists!") + f.write("\n" + url + " | ERROR_CODE: " + str(e)) + + f.write("\n---\n") + f.close() + print("Finished at " + str(datetime.datetime.now().time())[0:5].replace(":", "h") + "m") + +def url_generator(domains, log): + result = mode[random.randint(0, len(mode) - 1)] + "://" + characters = "abcdefghijklmnopqrstuvwxyz0123456789" + url_length = random.randint(2, 30) + result += ''.join(random.choice(characters) for i in range(url_length)) + result += domains[random.randint(0, len(domains) - 1)] + if log: print(result) + return result + +times = sys.argv[sys.argv.index('-t') + 1] if '-t' in sys.argv else 3000 +try: + times = int(times) +except: + print("-t argument expected a number!") + sys.exit() +domains = sys.argv[sys.argv.index('-d') + 1] if '-d' in sys.argv else ['.com', '.net', '.edu', '.gov', '.cn', '.org'] +mode = sys.argv[sys.argv.index('-m') + 1].split(",") if '-m' in sys.argv else ['http'] +log = '-l' in sys.argv + +print("\nI am going to look for images through " + str(times) + " random URLs with the following domains: " + str(domains)) +print("These URLs use the following protocols: " + str(mode)) +print("Started at " + str(datetime.datetime.now().time())[0:5].replace(":", "h") + "m") + +f = open("PY_report.txt", "a+") +f.write("---") +main_loop() diff --git a/README.md b/README.md index cf5cf10..38f2de7 100644 --- a/README.md +++ b/README.md @@ -8,10 +8,11 @@ Each script has its own requirements. * index.py, the Python script, requires [Python 3](https://www.python.org/downloads/) * index.js, the Node.js script, requires [Node.js](https://nodejs.org/en/download/) +* index.rb, the Ruby script, requires [Ruby](https://rubyinstaller.org/downloads/) ## HOW TO RUN -You can run the Python script by simply double clicking on it or going into the command-line, moving into the right directory and entering the file name, which is index.py. +You can run the Python or Ruby script by simply double clicking on it or going into the command-line, moving into the right directory and entering the file name. To run the Node.js script, you will have to use the command-line. @@ -26,20 +27,20 @@ No matter which script, if you wish to use arguments, you are required to use th - "-t" defines the number of URLs the script will go through. - "-d" defines all the top-level domains the URLs will use, separated only by a ",". -- "-m" defines the application protocol used. +- "-m" defines the application protocol used. Multiple protocols can be defined by separating them with a ",". - "-l" defines by whether or not it is present whether or not all URLs will be logged in the command-line. * "-t" defaults to 3000. * "-d" defaults to a lot of popular top-level domains. * "-m" defaults to "http". -* "-l" defaults to False. +* "-l" makes it so URLs will be logged. ```sh # To make the Python script go through 3000 URLs in HTTP with various top-level domains without logging: $ index.py -# To make the Python script go through 500 URLs in HTTP with only the .com and .fr top-level domains with logging: -$ index.py -t 500 -l -d .com,.fr +# To make the Ruby script go through 500 URLs in HTTP and HTTPS with only the .com and .fr top-level domains with logging: +$ index.rb -t 500 -m http,https -l -d .com,.fr # To make the Node.js script go through 3000 URLs in HTTPS with various top-level domains with logging: $ node index.js -m https -l @@ -48,12 +49,11 @@ $ node index.js -m https -l ## FAQ Q: Is there a script that is better than the other? -A: As far as I am aware, nope! However, some scripts may receive different status or error codes for the same website, and the Python script error codes have more length than those by the other scripts. +A: As far as I am aware, nope! However, the reports are generated differently depending of the script and some websites send different codes depending of the script. Q: Why does the "-m" argument defaults to "http" rather than "https"? A: Requests in "http" receive more status codes than error codes compared to "https". I suspect it's because some websites don't support "https" very well, even in the current year. ## TO DO -- Allow "-m" to support multiple application protocols like "-d". - Add more languages. diff --git a/Ruby/index.rb b/Ruby/index.rb new file mode 100644 index 0000000..96f839b --- /dev/null +++ b/Ruby/index.rb @@ -0,0 +1,39 @@ +require 'net/http' + +def main_loop + TIMES.times do + url = url_generator(DOMAINS, MODE) + puts(url) if LOG + begin + response = Net::HTTP.get_response(URI(url)) + puts("#{url} exists!") + File.open("RB_report.txt", 'a+') {|f| f.write("\n#{url} | STATUS_CODE: #{response.code} | DETAILS: #{response.message}")} + rescue Exception => e # Unlike JS/PY, the number of existing websites that raise exceptions is small + if e.class != SocketError + puts("#{url} exists!") + File.open("RB_report.txt", 'a+') {|f| f.write("\n#{url} | ERROR_CODE: #{e.class.to_s} | DETAILS: #{e.to_s}")} + end + end + end + File.open("RB_report.txt", 'a+') {|f| f.write("\n---\n")} + puts("Finished at #{Time.new.hour}h#{Time.new.min}m\n") +end + +def url_generator(domains, mode) + result = mode[rand(0..mode.length - 1)] + '://' + url_length = rand(2..30) + result += rand(36 ** url_length).to_s(36) + result += domains[rand(0..domains.length - 1)] +end + +TIMES = ARGV.include?('-t') ? ARGV[ARGV.index("-t") + 1].to_i : 3000 +DOMAINS = ARGV.include?('-d') ? ARGV[ARGV.index("-d") + 1].split(",") : ['.com', '.net', '.edu', '.gov', '.cn', '.org'] +MODE = ARGV.include?('-m') ? ARGV[ARGV.index("-m") + 1].split(",") : ['http'] +LOG = ARGV.index("-l").class == Integer + +puts("\nI am going to look for images through #{TIMES} random URLs with the following domains: #{DOMAINS}") +puts("These URLs will use the following protocols: #{MODE}") +puts("Started at #{Time.new.hour}h#{Time.new.min}m\n") + +File.open("RB_report.txt", 'a+') {|f| f.write("---")} +main_loop