Skip to content

Instantly share code, notes, and snippets.

@georgy7
Created September 24, 2015 22:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save georgy7/01ddac55ad09a5e46034 to your computer and use it in GitHub Desktop.
Save georgy7/01ddac55ad09a5e46034 to your computer and use it in GitHub Desktop.
7-Zipped & WebPied imageboard spaghetti server.
#!/usr/bin/env ruby
# encoding: utf-8
require 'rubygems'
gem 'seven_zip_ruby'
require 'seven_zip_ruby'
require 'webrick'
require 'fileutils'
gem 'nokogiri'
require 'nokogiri'
class Utils
def to_filename path
slash = path.rindex '/'
return path if nil == slash
slash += 1
path[slash..-1]
end
end
class ZipReader
def initialize(root, subfolder, name, p = nil)
path = root + subfolder
@folder_inside = name
@archive = path + name + '.7z' if nil == p
@archive = path + name + '.dat' unless nil == p
@cache_root = root + '../410_cache/'
@cache = @cache_root + subfolder
@ready = false
end
def get(filename)
extract if !@ready
data = nil
f = @cache + @folder_inside + '/' + filename
data = File.open(f, "rb").read
data
end
def clear
FileUtils.rm_rf(@cache) if Dir.exists?(@cache)
end
private
def extract
File.open(@archive, "rb") do |file|
SevenZipRuby::Reader.extract_all(file, @cache)
end
@ready = true
end
end
class CachelessZipReader < ZipReader
def initialize(a, b, c, p = nil)
super(a, b, c, p)
@pass = p
end
def get(filename)
while @indexing; sleep 2; end
make_index if !@ready
gete @entries[filename]
end
def clear
puts "Will close #{@archive} file..."
@reader.close
@file.close
end
private
def gete(entry, tries = 60)
begin
return @reader.extract_data(entry)
rescue
return nil if tries <= 0
return nil if nil == entry
sleep 1 + 1 * rand
return gete entry, tries - 1
end
end
def make_index
puts "Making index for #{@archive}..."
@indexing, @entries = true, {}
utils, params = Utils.new, {}
params[:password] = @pass if nil != @pass
@file = File.open(@archive, "rb")
@reader = SevenZipRuby::Reader.open(@file, params)
@reader.entries.select(&:file?).each do |e|
@entries[utils.to_filename(e.path)] = e
end
@ready, @indexing = true, false
end
end
class MyServlet < WEBrick::HTTPServlet::FileHandler
def initialize(server, folder,
archives)
super(server, folder)
@archives = archives
end
def do_GET (request, response)
case request.path
when '/b/arch/res/', /^\/b\/arch\/res\//
html_from_zip_reader @archives[0], request, response
when '/b/arch/thumb_m/', /^\/b\/arch\/thumb_m\//
img_from_zip_reader @archives[1], request, response
when '/dev/arch/res/', /^\/dev\/arch\/res\//
html_from_zip_reader @archives[2], request, response
when '/dev/arch/thumb_m/', /^\/dev\/arch\/thumb_m\//
img_from_zip_reader @archives[3], request, response
when '/dev/res/', /^\/dev\/res\//
html_from_zip_reader @archives[4], request, response
when '/dev/thumb_m/', /^\/dev\/thumb_m\//
img_from_zip_reader @archives[5], request, response
when '/b/res/', /^\/b\/res\//
html_from_zip_reader @archives[6], request, response
when '/b/thumb_m/', /^\/b\/thumb_m\//
img_from_zip_reader @archives[7], request, response
when '/cu/arch/res/', /^\/cu\/arch\/res\//
html_from_zip_reader @archives[8], request, response
when '/cu/arch/thumb_m/', /^\/cu\/arch\/thumb_m\//
img_from_zip_reader @archives[9], request, response
when '/cu/res/', /^\/cu\/res\//
html_from_zip_reader @archives[10], request, response
when '/cu/thumb_m/', /^\/cu\/thumb_m\//
img_from_zip_reader @archives[11], request, response
when '/', /^\/[^\/]*\.html/
html_from_zip_reader @archives[12], request, response
when '/b/', /^\/b\/[^\/]*\.html/
html_from_zip_reader @archives[13], request, response
when '/d/res/', /^\/d\/res\//
html_from_zip_reader @archives[14], request, response
when '/int/res/', /^\/int\/res\//
without_images @archives[15], request, response
when '/int/', /^\/int\/[^\/]*\.html/
without_images @archives[16], request, response
when '/int/thumb_m/', /^\/int\/thumb_m\//
img_from_zip_reader @archives[17], request, response
when '/cu/', /^\/cu\/[^\/]*\.html/
html_from_zip_reader @archives[18], request, response
when '/d/', /^\/d\/[^\/]*\.html/
html_from_zip_reader @archives[19], request, response
when '/dev/', /^\/dev\/[^\/]*\.html/
html_from_zip_reader @archives[20], request, response
else
super(request, response)
end
end
private
def change_js html
n = Nokogiri::HTML(html)
head = n.css('head').first
if nil != head
encoding_tag = Nokogiri::XML::Node.new('meta', n)
encoding_tag['http-equiv'] = 'Content-Type'
encoding_tag['content'] = 'text/html; charset=utf-8'
head.add_child encoding_tag
end
n.css('script').each do |node|
node.inner_html = 'function request_faptcha() { }' if
node.inner_html.include? 'faptcha_input'
b = 'if(document.styleSheets[stylesheetKey].href.indexOf'
e = 'var stylesheet = document.styleSheets[stylesheetKey];
if(typeof stylesheet.href === "string" && stylesheet.href.indexOf'
node.inner_html = node.inner_html.sub b, e
b = 'if(document.styleSheets[stylesheetKey].cssRules[ruleKey].selectorText.indexOf("postarea table")'
e = 'var rule = document.styleSheets[stylesheetKey].cssRules[ruleKey];
if((1 === rule.type) && rule.selectorText.indexOf("postarea table")'
node.inner_html = node.inner_html.sub b, e
end
n.to_html
end
def get_html(zipReader, request, response)
response.content_type = "text/html"
slash = (request.path.rindex '/') + 1
path = request.path[slash..-1]
path = 'index.html' if path.empty?
data = (zipReader.get path).to_s
response.status = 200 unless nil == data
response.status = 503 if nil == data
change_js data
end
def remove_thumbnails html
n = Nokogiri::HTML(html)
n.css('.reply img').remove
# if n.css('img.thumb').size > 0
# op = n.css('img.thumb')[0]
# op['src'] = op['src'].gsub /s.webp/, 'c.webp'
# end
n.to_html
end
def html_from_zip_reader(zipReader, request, response)
data = get_html(zipReader, request, response)
response.body = change_links data
end
def without_images(zipReader, request, response)
data = get_html(zipReader, request, response)
data = change_links data
response.body = remove_thumbnails data
end
def img_from_zip_reader(zipReader, request, response)
response.content_type = "image/webp"
slash = (request.path.rindex '/') + 1
path = request.path[slash..-1]
data = zipReader.get path
response.status = 200 unless nil == data
response.status = 503 if nil == data
response.body = data
end
def change_links html
n = Nokogiri::HTML(html)
n.css('img').each do |node|
node['src'] = node['src'].sub 'thumb', 'thumb_m'
node['src'] = node['src'].gsub 's.jpg', 's.webp'
node['src'] = node['src'].gsub 's.png', 's.webp'
node['src'] = node['src'].gsub 's.gif', 's.webp'
node['src'] = node['src'].gsub 'c.jpg', 'c.webp'
node['src'] = node['src'].gsub 'c.png', 'c.webp'
node['src'] = node['src'].gsub 'c.gif', 'c.webp'
end
r = n.to_html
r.gsub! /http:\/\/410chan.ru\//, '/'
r.gsub! /http:\/\/410chan.org\//, '/'
r.gsub! /"http:\/\/410chan.ru"/, '"/"'
r.gsub! /"http:\/\/410chan.org"/, '"/"'
r.gsub! /faptcha.php\?/, 'faptcha.php@'
r
end
end
class Main
def initialize
@webroot = './data/410/'
@readers = []
add_readers
end
def main
server = WEBrick::HTTPServer.new(:Port => 1410)
server.mount '/', MyServlet, @webroot,
@readers
trap("INT") {
server.shutdown
@readers.map(&:clear)
}
server.start
end
private
def add_readers
@readers.push CachelessZipReader.new @webroot, 'b/arch/', 'res', 'passsssss1'
@readers.push CachelessZipReader.new @webroot, 'b/arch/', 'thumb_m', 'passsssss2'
@readers.push CachelessZipReader.new @webroot, 'dev/arch/', 'res', 'passsssss3'
@readers.push CachelessZipReader.new @webroot, 'dev/arch/', 'thumb_m', 'passsssss4'
@readers.push CachelessZipReader.new @webroot, 'dev/', 'res', 'passsssss5'
@readers.push CachelessZipReader.new @webroot, 'dev/', 'thumb_m', 'passsssss6'
@readers.push CachelessZipReader.new @webroot, 'b/', 'res', 'passsssss7'
@readers.push CachelessZipReader.new @webroot, 'b/', 'thumb_m', 'passsssss8'
@readers.push CachelessZipReader.new @webroot, 'cu/arch/', 'res', 'passsssss9'
@readers.push CachelessZipReader.new @webroot, 'cu/arch/', 'thumb_m', 'passsssss10'
@readers.push CachelessZipReader.new @webroot, 'cu/', 'res', 'passsssss11'
@readers.push CachelessZipReader.new @webroot, 'cu/', 'thumb_m', 'passsssss12'
@readers.push CachelessZipReader.new @webroot, '', 'index', 'passsssss13'
@readers.push CachelessZipReader.new @webroot, 'b/', 'index', 'passsssss14'
@readers.push CachelessZipReader.new @webroot, 'd/', 'res', 'passsssss15'
@readers.push CachelessZipReader.new @webroot, 'int/', 'res', 'passsssss16'
@readers.push CachelessZipReader.new @webroot, 'int/', 'index', 'passsssss17'
@readers.push CachelessZipReader.new @webroot, 'int/', 'thumb_m', 'passsssss18'
@readers.push CachelessZipReader.new @webroot, 'cu/', 'index', 'passsssss19'
@readers.push CachelessZipReader.new @webroot, 'd/', 'index', 'passsssss20'
@readers.push CachelessZipReader.new @webroot, 'dev/', 'index', 'passsssss21'
end
end
if __FILE__ == $PROGRAM_NAME
Main.new.main
end
@georgy7
Copy link
Author

georgy7 commented Sep 24, 2015

Возможно упрощу, разобью на файлы и превращу в gem (MIT). Это трудно сделать из-за того, что скрипт даже затыкает проблемы конкретно этой имиджборды. Например, исправляет косяк в скрипте. Возможно позже всё это обдумаю и сделаю хорошо.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment