CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/lib/rex/proto/nuuo/response.rb
Views: 11704
1
# -*- coding:binary -*-
2
3
module Rex
4
module Proto
5
module Nuuo
6
class Response
7
8
module ParseCode
9
Completed = 1
10
Partial = 2
11
Error = 3
12
end
13
14
module ParseState
15
ProcessingHeader = 1
16
ProcessingBody = 2
17
Completed = 3
18
end
19
20
attr_accessor :headers
21
attr_accessor :body
22
attr_accessor :protocol
23
attr_accessor :status_code
24
attr_accessor :message
25
attr_accessor :bufq
26
attr_accessor :state
27
28
def initialize(buf=nil)
29
self.state = ParseState::ProcessingHeader
30
self.headers = {}
31
self.body = ''
32
self.protocol = nil
33
self.status_code = nil
34
self.message = nil
35
self.bufq = ''
36
parse(buf) if buf
37
end
38
39
def to_s
40
s = ''
41
return unless self.protocol
42
s << self.protocol
43
s << " #{self.status_code}" if self.status_code
44
s << " #{self.message}" if self.message
45
s << "\r\n"
46
47
self.headers.each do |k,v|
48
s << "#{k}: #{v}\r\n"
49
end
50
51
s << "\r\n#{self.body}"
52
end
53
54
# returns state of parsing
55
def parse(buf)
56
self.bufq << buf
57
58
if self.state == ParseState::ProcessingHeader
59
parse_header
60
end
61
62
if self.state == ParseState::ProcessingBody
63
if self.body_bytes_left == 0
64
self.state = ParseState::Completed
65
else
66
parse_body
67
end
68
end
69
70
(self.state == ParseState::Completed) ? ParseCode::Completed : ParseCode::Partial
71
end
72
73
protected
74
attr_accessor :body_bytes_left
75
76
def parse_header
77
head,body = self.bufq.split("\r\n\r\n", 2)
78
return nil unless body
79
80
get_headers(head)
81
self.bufq = body || ''
82
self.body_bytes_left = 0
83
84
if self.headers['Content-Length']
85
self.body_bytes_left = self.headers['Content-Length'].to_i
86
end
87
88
self.state = ParseState::ProcessingBody
89
end
90
91
def parse_body
92
return if self.bufq.length == 0
93
if self.body_bytes_left >= 0
94
part = self.bufq.slice!(0, self.body_bytes_left)
95
self.body << part
96
self.body_bytes_left -= part.length
97
else
98
self.body_bytes_left = 0
99
end
100
101
if self.body_bytes_left == 0
102
self.state = ParseState::Completed
103
end
104
end
105
106
def get_headers(head)
107
head.each_line.with_index do |l, i|
108
if i == 0
109
self.protocol,self.status_code,self.message = l.split(' ', 3)
110
self.status_code = self.status_code.to_i if self.status_code
111
next
112
end
113
k,v = l.split(':', 2)
114
self.headers[k] = v.strip
115
end
116
end
117
118
end
119
end
120
end
121
end
122
123