Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- require 'rubygems'
- require 'eventmachine'
- def GetPOSTCommand(query)
- if query[0..4] == 'POST '
- if query.scan("\r\n\r\n").size > 0
- return query[5..-1].slice(/^\S+(?= HTTP\/1.1\r\n)/i)
- end
- end
- return nil
- end
- def GetGETCommand(query)
- if query[0..3] == 'GET '
- if query[query.bytesize-4..query.bytesize-1] == "\r\n\r\n"
- return query[5..-1].slice(/^\S+(?= HTTP\/1.1\r\n)/i)
- end
- end
- return nil
- end
- def GetPOSTContentLength(query_header)
- hdr_contentl = query_header.slice(/\r\nContent-Length: \d+(?=\r\n)/i)
- if hdr_contentl
- return hdr_contentl.split(' ')[1].to_i
- end
- return 0
- end
- def GetHost(query_header)
- hdr_contentl = query_header.slice(/\r\nHost: \S+(?=\r\n)/i)
- if hdr_contentl
- return hdr_contentl.split(' ')[1]
- end
- return nil
- end
- def GetPOSTContent(query)
- header_size = query.split("\r\n\r\n")[0].bytesize+4
- return query[header_size..-1]
- end
- def GetPOSTHeader(query)
- return query.split("\r\n\r\n")[0] + "\r\n\r\n"
- end
- def GetPOSTBoundary(query_header)
- hdr_contentt = query_header.slice(/\r\nContent-Type:\s+multipart\/form-data;\s+boundary\=\S+(?=\r\n)/i)
- if hdr_contentt
- return hdr_contentt.split('boundary=')[1]
- end
- return nil
- end
- def ParsePart(part)
- if part[0..3] == "--"
- return nil
- end
- size = part.bytesize
- if part[size-2..size-1] != "\r\n"
- return nil
- end
- part = part[0..size-3]
- part_header = part.slice(/^\r\nContent-Disposition:\s+form-data;.+?name=\S+.*?(\r\n.*?)?\r\n\r\n/i)
- if part_header == nil
- return nil
- end
- result = Hash.new
- result["name"] = part_header.slice(/name=\"\S+\"/i).split("=")[1]
- result["data"] = part[part_header.bytesize..-1]
- filename = part_header.slice(/filename=\"\S+\"/i)
- if filename != nil
- result["filename"] = filename.split("=")[1]
- end
- return result
- end
- def ParsePOSTMultipart(query_content, boundary)
- parts = query_content.split("--"+boundary)
- result = Array.new
- i = 0
- parts.each do |cpart|
- pp = ParsePart(cpart)
- if pp != nil
- result[i] = pp
- i += 1
- end
- end
- return result
- end
- def ParsePOST(query, fullparse = true)
- cmd = GetPOSTCommand(query)
- if cmd == nil
- return nil
- end
- result = Hash.new
- result["type"] = "POST"
- result["command"] = cmd
- qheader = GetPOSTHeader(query)
- result["content-length"] = GetPOSTContentLength(qheader)
- #puts "ParsePOST: cont-len #{result["content-length"]} qheader.bytesize = #{qheader.bytesize} ( #{qheader.size}) query.bytesize = #{query.bytesize} (#{query.size})"
- result["host"] = GetHost(qheader)
- result["completed"] = (qheader.bytesize+result["content-length"] <= query.bytesize)
- if fullparse
- result["content"] = GetPOSTContent(query)
- result["boundary"] =GetPOSTBoundary(qheader)
- if result["boundary"] != nil
- result["multipart"] = ParsePOSTMultipart(result["content"], result["boundary"])
- end
- end
- return result
- end
- def PreParsePOST(query)
- return ParsePOST(query, false)
- end
- def IsQueryCompleted(query)
- command = GetGETCommand(query)
- if command != nil
- result = Hash.new
- result["type"] = "GET"
- result["completed"] = true
- result["host"] = GetHost(query)
- result["command"] = command
- return result
- end
- result = PreParsePOST(query)
- if result != nil
- if result["completed"]
- result = ParsePOST(query)
- end
- return result
- end
- return nil
- end
- def SaveData(data)
- b = rand
- a = "#{b}"
- time1 = Time.new
- newfilename = time1.inspect + "_" + a + "_" + ".dat"
- puts "Save to file #{newfilename}"
- File.open(newfilename, 'w'){ |file| file.write data }
- end
- #Здесь проверяем валидность URI и host
- def CheckURL(host, uri)
- # URL = host+uri
- puts "URL : #{host}#{uri}"
- #можно host проверить, а можно не проверять
- return uri == "handler.php"
- end
- #Здесь обрабатываем GET-запросы
- def HandleGET(query_data)
- puts "GET QUERY============="
- sz = query_data["command"].bytesize
- return "HTTP\/1.1 200 OK\r\nServer: huy\r\nContent-Length: #{sz}\r\n\r\n"+query_data["command"]
- end
- #Здесь обрабатываем POST-запросы
- def HandlePOST(query_data)
- puts "POST QUERY============="
- puts query_data["command"]
- if query_data["boundary"] != nil
- # ПРИШЁЛ MULTIPART-FORM_DATA
- puts "reveived multipart"
- # ВЫВОДИМ и сохраняем все файлы пришедшие в multipart
- query_data["multipart"].each do |descr|
- puts descr["name"]
- puts descr["filename"]
- SaveData(descr["data"])
- innerPOST = ParsePOST(descr["data"])
- # если пост в посте то уведомляем об этом
- if innerPOST != nil
- # внутри мультипарта пришёл POST
- puts "reveived POST in multipart"
- puts "URL = #{innerPOST["host"]}#{innerPOST["command"]}"
- end
- end
- else
- innerPOST = ParsePOST(query_data["content"])
- if innerPOST != nil
- # ПРИШЁЛ ПОСТ В ПОСТЕ
- puts "reveived POST in POST"
- puts "URL = #{innerPOST["host"]}#{innerPOST["command"]}"
- end
- end
- puts "POST QUERY========= END"
- return "HTTP\/1.1 200 OK\r\nServer: huy\r\nContent-Length: 8\r\n\r\nSUCCESS!"
- end
- class EchoServer < EventMachine::Connection
- def post_init
- puts "connection"
- @query_buffer = ""
- end
- def receive_data data
- @query_buffer << data
- q = IsQueryCompleted(@query_buffer)
- if q != nil
- #puts "valid HTTP query"
- if q["completed"]
- #puts "completed HTTP query"
- response = ""
- if CheckURL(q["host"], q["command"])
- if q["type"] == "GET"
- response = HandleGET(q)
- elsif q["type"] == "POST"
- #puts "completed HTTP POST"
- response = HandlePOST(q)
- end
- else
- response = "HTTP/1.1 400 Bad request\r\nServer: huy\r\n\r\n"
- end
- if response != ""
- #puts "response exist"
- #puts response
- send_data(response)
- end
- close_connection_after_writing
- else
- discard = true
- # обрабатываем только POST, ибо GET всегда приходит одним пакетом
- #проверяем нормальный ли это POST запрос и узнаем разрешённый ли у него URI
- pq = PreParsePOST(@query_buffer)
- if pq != nil
- if CheckURL(pq["host"], pq["command"])
- #puts "not completed. wait full query..."
- discard = false
- end
- end
- if discard
- #puts "invalid POST request disconnect"
- send_data("HTTP/1.1 400 Bad request\r\nServer: huy\r\n\r\n")
- close_connection_after_writing
- end
- end
- else
- #puts "invalid request header disconnect"
- send_data("HTTP/1.1 400 Bad request\r\nServer: huy\r\n\r\n")
- close_connection_after_writing
- end
- end
- def unbind
- puts "connection end"
- end
- end
- EventMachine::run {
- EventMachine::start_server "192.168.0.1", 1420, EchoServer
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement