Advertisement
Guest User

Untitled

a guest
Jul 14th, 2014
373
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 7.47 KB | None | 0 0
  1. require 'rubygems'
  2.  
  3. require 'eventmachine'
  4.  
  5. def GetPOSTCommand(query)
  6.     if query[0..4] == 'POST '
  7.         if query.scan("\r\n\r\n").size > 0
  8.             return query[5..-1].slice(/^\S+(?= HTTP\/1.1\r\n)/i)  
  9.         end
  10.     end
  11.    
  12.     return nil    
  13. end
  14.  
  15. def GetGETCommand(query)
  16.     if query[0..3] == 'GET '
  17.         if query[query.bytesize-4..query.bytesize-1] == "\r\n\r\n"
  18.             return query[5..-1].slice(/^\S+(?= HTTP\/1.1\r\n)/i)  
  19.         end
  20.     end
  21.    
  22.     return nil    
  23. end
  24.  
  25.  
  26. def GetPOSTContentLength(query_header)
  27.     hdr_contentl =  query_header.slice(/\r\nContent-Length: \d+(?=\r\n)/i)
  28.     if hdr_contentl
  29.         return hdr_contentl.split(' ')[1].to_i
  30.     end
  31.    
  32.     return 0
  33. end
  34.  
  35. def GetHost(query_header)
  36.     hdr_contentl =  query_header.slice(/\r\nHost: \S+(?=\r\n)/i)
  37.     if hdr_contentl
  38.         return hdr_contentl.split(' ')[1]
  39.     end
  40.      
  41.     return nil
  42. end
  43.  
  44. def GetPOSTContent(query)  
  45.     header_size = query.split("\r\n\r\n")[0].bytesize+4
  46.     return query[header_size..-1]
  47. end
  48.  
  49. def GetPOSTHeader(query)    
  50.     return query.split("\r\n\r\n")[0] + "\r\n\r\n"  
  51. end
  52.  
  53. def GetPOSTBoundary(query_header)  
  54.     hdr_contentt = query_header.slice(/\r\nContent-Type:\s+multipart\/form-data;\s+boundary\=\S+(?=\r\n)/i)
  55.     if hdr_contentt
  56.         return hdr_contentt.split('boundary=')[1]
  57.     end
  58.    
  59.     return nil
  60. end
  61.  
  62. def ParsePart(part)    
  63.    
  64.     if part[0..3] == "--"
  65.         return nil
  66.     end
  67.    
  68.     size = part.bytesize
  69.     if part[size-2..size-1] != "\r\n"
  70.         return nil
  71.     end
  72.    
  73.     part = part[0..size-3]
  74.    
  75.     part_header = part.slice(/^\r\nContent-Disposition:\s+form-data;.+?name=\S+.*?(\r\n.*?)?\r\n\r\n/i)
  76.     if part_header == nil
  77.         return nil
  78.     end
  79.    
  80.     result = Hash.new
  81.    
  82.    
  83.     result["name"] = part_header.slice(/name=\"\S+\"/i).split("=")[1]
  84.    result["data"] = part[part_header.bytesize..-1]  
  85.    filename = part_header.slice(/filename=\"\S+\"/i)
  86.    if filename != nil
  87.        result["filename"] = filename.split("=")[1]
  88.    end
  89.  
  90.    return result
  91. end
  92.  
  93. def ParsePOSTMultipart(query_content, boundary)  
  94.  
  95.    parts = query_content.split("--"+boundary)
  96.  
  97.    result = Array.new
  98.    i = 0
  99.    parts.each do |cpart|
  100.        pp = ParsePart(cpart)
  101.        if pp != nil
  102.            result[i] = pp
  103.            i += 1        
  104.  
  105.        end
  106.    end
  107.    return result
  108. end
  109.  
  110. def ParsePOST(query, fullparse = true)
  111.  
  112.    cmd = GetPOSTCommand(query)
  113.    if cmd == nil
  114.        return nil
  115.    end
  116.    
  117.  
  118.    result = Hash.new
  119.    
  120.    result["type"] = "POST"
  121.    result["command"] = cmd  
  122.    qheader = GetPOSTHeader(query)
  123.    result["content-length"] = GetPOSTContentLength(qheader)
  124.     #puts "ParsePOST: cont-len #{result["content-length"]}  qheader.bytesize = #{qheader.bytesize} ( #{qheader.size})  query.bytesize = #{query.bytesize} (#{query.size})"
  125.     result["host"] = GetHost(qheader)
  126.     result["completed"] = (qheader.bytesize+result["content-length"] <= query.bytesize)
  127.    
  128.     if fullparse
  129.         result["content"] = GetPOSTContent(query)    
  130.        
  131.         result["boundary"]  =GetPOSTBoundary(qheader)
  132.         if result["boundary"] != nil
  133.             result["multipart"] = ParsePOSTMultipart(result["content"], result["boundary"])  
  134.  
  135.         end
  136.        
  137.     end  
  138.  
  139.     return result
  140. end
  141.  
  142. def PreParsePOST(query)
  143.  
  144.     return ParsePOST(query, false)
  145. end
  146.  
  147. def IsQueryCompleted(query)
  148.  
  149.     command = GetGETCommand(query)
  150.     if command != nil
  151.         result = Hash.new
  152.         result["type"] = "GET"
  153.         result["completed"] = true
  154.         result["host"] = GetHost(query)
  155.         result["command"] = command
  156.         return result
  157.     end
  158.        
  159.     result = PreParsePOST(query)   
  160.     if result != nil
  161.         if result["completed"]
  162.             result = ParsePOST(query)
  163.         end
  164.         return result
  165.     end
  166.    
  167.     return nil
  168. end
  169.  
  170. def SaveData(data)
  171.     b = rand
  172.     a = "#{b}"
  173.     time1 = Time.new
  174.     newfilename = time1.inspect + "_" + a + "_" + ".dat"
  175.     puts "Save to file #{newfilename}"
  176.     File.open(newfilename, 'w'){ |file| file.write data }
  177. end
  178.  
  179. #Здесь проверяем валидность URI и host
  180. def CheckURL(host, uri)
  181.     # URL = host+uri
  182.     puts "URL : #{host}#{uri}"
  183.     #можно host проверить, а можно не проверять
  184.     return uri == "handler.php"
  185. end
  186.  
  187. #Здесь обрабатываем GET-запросы
  188. def HandleGET(query_data)
  189.     puts "GET QUERY============="
  190.  
  191.     sz = query_data["command"].bytesize
  192.     return "HTTP\/1.1 200 OK\r\nServer: huy\r\nContent-Length: #{sz}\r\n\r\n"+query_data["command"]
  193. end
  194.  
  195. #Здесь обрабатываем POST-запросы
  196. def HandlePOST(query_data)
  197.     puts "POST QUERY============="
  198.     puts query_data["command"]
  199.     if query_data["boundary"] != nil
  200.        
  201.         # ПРИШЁЛ MULTIPART-FORM_DATA
  202.         puts "reveived multipart"      
  203.         # ВЫВОДИМ и сохраняем все файлы пришедшие в multipart
  204.         query_data["multipart"].each do |descr|
  205.             puts descr["name"]
  206.             puts descr["filename"]
  207.             SaveData(descr["data"])
  208.             innerPOST = ParsePOST(descr["data"])
  209.             # если пост в посте то уведомляем об этом
  210.             if innerPOST != nil
  211.                 # внутри мультипарта пришёл POST
  212.                 puts "reveived POST in multipart"
  213.                 puts "URL = #{innerPOST["host"]}#{innerPOST["command"]}"
  214.                
  215.             end
  216.         end
  217.     else
  218.         innerPOST = ParsePOST(query_data["content"])
  219.         if innerPOST != nil
  220.             # ПРИШЁЛ ПОСТ В ПОСТЕ
  221.             puts "reveived POST in POST"
  222.             puts "URL = #{innerPOST["host"]}#{innerPOST["command"]}"
  223.         end
  224.     end
  225.     puts "POST QUERY========= END"
  226.    
  227.     return "HTTP\/1.1 200 OK\r\nServer: huy\r\nContent-Length: 8\r\n\r\nSUCCESS!"
  228. end
  229.  
  230. class EchoServer < EventMachine::Connection
  231.    
  232.     def post_init      
  233.         puts "connection"  
  234.         @query_buffer = ""     
  235.     end
  236.  
  237.     def receive_data data
  238.        
  239.         @query_buffer << data
  240.        
  241.         q = IsQueryCompleted(@query_buffer)    
  242.         if q != nil
  243.             #puts "valid HTTP query"
  244.             if q["completed"]
  245.                 #puts "completed HTTP query"
  246.                 response =  ""
  247.                 if CheckURL(q["host"], q["command"])
  248.                     if q["type"] == "GET"                  
  249.                         response = HandleGET(q)
  250.                     elsif q["type"] == "POST"
  251.                         #puts "completed HTTP POST"
  252.                         response = HandlePOST(q)
  253.                     end
  254.                 else
  255.                     response = "HTTP/1.1 400 Bad request\r\nServer: huy\r\n\r\n"
  256.                 end
  257.                
  258.                 if response != ""
  259.                     #puts "response exist"
  260.                     #puts response
  261.  
  262.                     send_data(response)
  263.                 end
  264.                 close_connection_after_writing
  265.             else
  266.                 discard = true
  267.                 # обрабатываем только POST, ибо GET всегда приходит одним пакетом
  268.                
  269.                 #проверяем нормальный ли это POST запрос и узнаем разрешённый ли у него URI
  270.                 pq = PreParsePOST(@query_buffer)
  271.                 if pq != nil
  272.                    
  273.                     if CheckURL(pq["host"], pq["command"])
  274.                         #puts "not completed. wait full query..."
  275.                         discard = false
  276.                     end
  277.                 end
  278.                
  279.            
  280.                 if discard
  281.                     #puts "invalid POST request disconnect"
  282.                     send_data("HTTP/1.1 400 Bad request\r\nServer: huy\r\n\r\n")
  283.                     close_connection_after_writing
  284.                 end
  285.             end
  286.         else
  287.             #puts "invalid request header disconnect"
  288.              
  289.             send_data("HTTP/1.1 400 Bad request\r\nServer: huy\r\n\r\n")
  290.             close_connection_after_writing
  291.         end
  292.     end
  293.  
  294.     def unbind
  295.         puts "connection end"
  296.     end
  297. end
  298.  
  299. EventMachine::run {
  300.     EventMachine::start_server "192.168.0.1", 1420, EchoServer
  301. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement