Created
September 24, 2015 22:28
-
-
Save georgy7/01ddac55ad09a5e46034 to your computer and use it in GitHub Desktop.
7-Zipped & WebPied imageboard spaghetti server.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Возможно упрощу, разобью на файлы и превращу в gem (MIT). Это трудно сделать из-за того, что скрипт даже затыкает проблемы конкретно этой имиджборды. Например, исправляет косяк в скрипте. Возможно позже всё это обдумаю и сделаю хорошо.