-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathhttp-handler.cbl
More file actions
238 lines (203 loc) · 9.4 KB
/
http-handler.cbl
File metadata and controls
238 lines (203 loc) · 9.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
*> HTTP request parser and response generator module
IDENTIFICATION DIVISION.
PROGRAM-ID. HTTP-HANDLER.
DATA DIVISION.
WORKING-STORAGE SECTION.
*> Include HTTP request/response data structures
COPY "http-structs.cpy".
*> Include file handling data structures
COPY "file-structs.cpy".
*> General purpose index for string operations (binary for efficiency)
01 WS-INDEX PIC 9(4) COMP.
*> Position of space character in HTTP request parsing
01 WS-SPACE-POS PIC 9(4) COMP.
*> Length of extracted path from HTTP request
01 WS-PATH-LEN PIC 9(4) COMP.
*> Return code from called modules (0=success, 1=error)
01 WS-RETURN-CODE PIC 9.
*> String representation of file size for Content-Length header
01 WS-SIZE-STR PIC X(10).
*> HTTP line terminator sequence (carriage return + line feed)
01 WS-CRLF PIC XX VALUE X"0D0A".
*> Decoded path after URL decoding (converts %20 to space, etc.)
01 WS-DECODED-PATH PIC X(512).
*> Parameters passed from calling program
LINKAGE SECTION.
*> HTTP request data received from client (8KB max)
01 LS-REQUEST-BUF PIC X(8192).
*> Buffer for building HTTP response (64KB max)
01 LS-RESPONSE-BUF PIC X(65536).
*> Actual length of generated response
01 LS-RESPONSE-LEN PIC 9(8) COMP-5.
*> Program entry point with parameters
PROCEDURE DIVISION USING LS-REQUEST-BUF LS-RESPONSE-BUF
LS-RESPONSE-LEN.
*> Main HTTP request processing logic
MAIN-LOGIC.
*> Initialize HTTP request fields
MOVE SPACES TO REQUEST-METHOD
MOVE SPACES TO REQUEST-PATH
MOVE 0 TO LS-RESPONSE-LEN
*> DISPLAY "Raw request: '" LS-REQUEST-BUF(1:80) "'"
*> Find first space in request to separate HTTP method
*> HTTP format: "GET /path HTTP/1.1"
MOVE 0 TO WS-SPACE-POS
INSPECT LS-REQUEST-BUF TALLYING WS-SPACE-POS
FOR CHARACTERS BEFORE INITIAL SPACE
*> DISPLAY "First space at position: " WS-SPACE-POS
*> DISPLAY "Character at pos 4: '" LS-REQUEST-BUF(4:1) "' = "
*> FUNCTION ORD(LS-REQUEST-BUF(4:1))
*> DISPLAY "Character at pos 5: '" LS-REQUEST-BUF(5:1) "' = "
*> FUNCTION ORD(LS-REQUEST-BUF(5:1))
*> Extract HTTP method (GET, POST, etc.) from first part of request
IF WS-SPACE-POS > 0 AND WS-SPACE-POS <= 10
MOVE LS-REQUEST-BUF(1:WS-SPACE-POS) TO REQUEST-METHOD
*> DISPLAY "Method: '" REQUEST-METHOD "'"
END-IF
*> Skip space after method to find start of path
COMPUTE WS-INDEX = WS-SPACE-POS + 2
*> DISPLAY "Starting path search at position: " WS-INDEX
*> Find end of path (next space or line ending)
MOVE 0 TO WS-PATH-LEN
PERFORM VARYING WS-SPACE-POS FROM WS-INDEX BY 1
UNTIL WS-SPACE-POS > 8192
IF LS-REQUEST-BUF(WS-SPACE-POS:1) = SPACE OR
LS-REQUEST-BUF(WS-SPACE-POS:1) = X"0D" OR
LS-REQUEST-BUF(WS-SPACE-POS:1) = X"0A"
COMPUTE WS-PATH-LEN = WS-SPACE-POS - WS-INDEX
*> DISPLAY "Found delimiter at position: " WS-SPACE-POS
*> DISPLAY "Delimiter is: "
*> FUNCTION ORD(LS-REQUEST-BUF(WS-SPACE-POS:1))
EXIT PERFORM
END-IF
END-PERFORM
*> DISPLAY "Path starts at: " WS-INDEX
*> DISPLAY "Path length: " WS-PATH-LEN
*> Extract the URL path from the HTTP request
IF WS-PATH-LEN > 0 AND WS-PATH-LEN <= 512
MOVE LS-REQUEST-BUF(WS-INDEX:WS-PATH-LEN)
TO REQUEST-PATH
*> DISPLAY "Extracted path: '" REQUEST-PATH(1:50) "'"
END-IF
*> Decode URL-encoded characters (e.g., %20 -> space)
CALL "URL-DECODE" USING REQUEST-PATH WS-DECODED-PATH
*> Validate and sanitize the requested path for security
CALL "PATH-UTILS" USING WS-DECODED-PATH SANITIZED-PATH
WS-RETURN-CODE
*> DISPLAY "Requested path: '" REQUEST-PATH "'"
*> DISPLAY "Decoded path: '" WS-DECODED-PATH "'"
*> DISPLAY "Sanitized path: '" SANITIZED-PATH "'"
*> DISPLAY "Path validation result: " WS-RETURN-CODE
*> If path validation failed, return 403 Forbidden
IF WS-RETURN-CODE NOT = 0
PERFORM BUILD-403-RESPONSE
GOBACK
END-IF
*> Attempt to read the requested file
CALL "FILE-OPS" USING SANITIZED-PATH FILE-BUFFER
FILE-SIZE WS-RETURN-CODE
*> DISPLAY "File read result: " WS-RETURN-CODE
*> DISPLAY "File size: " FILE-SIZE
*> If file is too large, return 413 Payload Too Large
IF WS-RETURN-CODE = 2
PERFORM BUILD-413-RESPONSE
GOBACK
END-IF
*> If file read failed, return 404 Not Found
IF WS-RETURN-CODE NOT = 0
*> DISPLAY "File not found: '" SANITIZED-PATH "'"
PERFORM BUILD-404-RESPONSE
GOBACK
END-IF
*> Determine MIME type based on file extension
CALL "MIME-TYPES" USING SANITIZED-PATH MIME-TYPE
*> Build successful HTTP response with file content
PERFORM BUILD-200-RESPONSE
GOBACK.
*> Build HTTP 200 OK response with file content
BUILD-200-RESPONSE.
*> Convert file size to string for Content-Length header
MOVE FILE-SIZE TO WS-SIZE-STR
*> Initialize response buffer with LOW-VALUE for string termination
MOVE LOW-VALUE TO LS-RESPONSE-BUF
*> Build HTTP response headers using STRING statement
*> STRING concatenates multiple values into one field
STRING "HTTP/1.1 200 OK" DELIMITED BY SIZE
WS-CRLF DELIMITED BY SIZE
"Content-Type: " DELIMITED BY SIZE
MIME-TYPE DELIMITED BY SPACE
WS-CRLF DELIMITED BY SIZE
"Content-Length: " DELIMITED BY SIZE
WS-SIZE-STR DELIMITED BY SPACE
WS-CRLF DELIMITED BY SIZE
WS-CRLF DELIMITED BY SIZE
INTO LS-RESPONSE-BUF
END-STRING
*> Calculate length of HTTP headers
MOVE 0 TO LS-RESPONSE-LEN
INSPECT LS-RESPONSE-BUF TALLYING LS-RESPONSE-LEN
FOR CHARACTERS BEFORE INITIAL LOW-VALUE
*> DISPLAY "Header length: " LS-RESPONSE-LEN
*> Append file content after headers if file was read successfully
IF LS-RESPONSE-LEN > 0 AND FILE-SIZE > 0
MOVE FILE-BUFFER(1:FILE-SIZE) TO
LS-RESPONSE-BUF(LS-RESPONSE-LEN + 1:FILE-SIZE)
ADD FILE-SIZE TO LS-RESPONSE-LEN
END-IF
*> DISPLAY "Total response length: " LS-RESPONSE-LEN
*> DISPLAY "File size: " FILE-SIZE
.
*> Build HTTP 404 Not Found response
BUILD-404-RESPONSE.
*> Create complete HTTP response with headers and HTML body
STRING "HTTP/1.1 404 Not Found" DELIMITED BY SIZE
WS-CRLF DELIMITED BY SIZE
"Content-Type: text/html" DELIMITED BY SIZE
WS-CRLF DELIMITED BY SIZE
"Content-Length: 47" DELIMITED BY SIZE
WS-CRLF DELIMITED BY SIZE
WS-CRLF DELIMITED BY SIZE
"<html><body><h1>404 Not Found</h1></body></html>"
DELIMITED BY SIZE
INTO LS-RESPONSE-BUF
END-STRING
*> Calculate total response length for sending
INSPECT LS-RESPONSE-BUF TALLYING LS-RESPONSE-LEN
FOR CHARACTERS BEFORE INITIAL LOW-VALUE
.
*> Build HTTP 403 Forbidden response (for security violations)
BUILD-403-RESPONSE.
*> Create complete HTTP response for path traversal attempts
STRING "HTTP/1.1 403 Forbidden" DELIMITED BY SIZE
WS-CRLF DELIMITED BY SIZE
"Content-Type: text/html" DELIMITED BY SIZE
WS-CRLF DELIMITED BY SIZE
"Content-Length: 47" DELIMITED BY SIZE
WS-CRLF DELIMITED BY SIZE
WS-CRLF DELIMITED BY SIZE
"<html><body><h1>403 Forbidden</h1></body></html>"
DELIMITED BY SIZE
INTO LS-RESPONSE-BUF
END-STRING
*> Calculate total response length for sending
INSPECT LS-RESPONSE-BUF TALLYING LS-RESPONSE-LEN
FOR CHARACTERS BEFORE INITIAL LOW-VALUE
.
*> Build HTTP 413 Payload Too Large response (for oversized files)
BUILD-413-RESPONSE.
*> Create complete HTTP response for files exceeding buffer size
STRING "HTTP/1.1 413 Payload Too Large" DELIMITED BY SIZE
WS-CRLF DELIMITED BY SIZE
"Content-Type: text/html" DELIMITED BY SIZE
WS-CRLF DELIMITED BY SIZE
"Content-Length: 59" DELIMITED BY SIZE
WS-CRLF DELIMITED BY SIZE
WS-CRLF DELIMITED BY SIZE
"<html><body><h1>413 Payload Too Large</h1></body></html>"
DELIMITED BY SIZE
INTO LS-RESPONSE-BUF
END-STRING
*> Calculate total response length for sending
INSPECT LS-RESPONSE-BUF TALLYING LS-RESPONSE-LEN
FOR CHARACTERS BEFORE INITIAL LOW-VALUE
.