Const MAX_CONNECTIONS
= 8
Dim num_active_connections
If num_active_connections
< MAX_CONNECTIONS
Then num_active_connections = num_active_connections + 1
For i
= 1 To MAX_CONNECTIONS
If Connections
(i
).handle
= 0 Then Dim empty_connection
As connection_t
Connections(i) = empty_connection
Connections(i).handle = new_connection
num_active_connections = num_active_connections - 1
For i
= 1 To MAX_CONNECTIONS
Get #Connections
(i
).handle
, , buf$
Connections(i).read_buf = Connections(i).read_buf + buf$
process_request i
http_error_complete:
error_handler:
Print "HTTP error"; Http_error_info.code; Http_error_info.message;
" for connection"; Http_error_info.connection
file_error_handler:
File_error_info.failed = TRUE
File_error_info.code
= Err
s$
= "HTTP/1.1" + Str$(code
) + " " + message
+ CRLF
Put #Connections
(c
).handle
, , s$
s$ = header + ": " + value + CRLF
Put #Connections
(c
).handle
, , s$
Put #Connections
(c
).handle
, , CRLF
Put #Connections
(c
).handle
, , body
filepath = get_requested_filesystem_path(c)
File_error_info.failed = FALSE
If File_error_info.failed
Then http_error
403, "Permission Denied", c
'Doing this all in one go isn't healthy for a number of reasons (memory usage, starving other clients)
'It should be done in chunks in the main loop
http_send_status c, 200, "OK"
http_send_header c
, "Content-Length", LTrim$(Str$(Len(filedata
))) http_send_header c, "Connection", "close"
http_end_headers c
http_send_body c, filedata
close_connection c
s$ = "HTTP/1.1 200 OK" + CRLF + CRLF
Put #Connections
(c
).handle
, , s$
Close #Connections
(c
).handle
Connections(c).handle = 0
Function get_requested_filesystem_path$
(c
) '7230 5.3 also 3986 for URI
'Origin form only for now
raw_path = Connections(c).request_uri
If Left$(raw_path
, 1) <> "/" Then http_error
400, "Malformed URI", c
Dim hash
, questionmark
, path_len
hash
= InStr(raw_path
, "#") 'Clients shouldn't be sending fragments, but we will gracefully ignore them questionmark
= InStr(raw_path
, "?") If hash
> 0 Then path_len
= hash
- 1 If questionmark
> 0 And questionmark
< hash
Then path_len
= questionmark
- 1 ' Query strings are ignored for now
'Dim cwd As String
'cwd = _CWD$
'$If WIN Then
' 'raw_path = GXSTR_Replace(raw_path, "/", "\")
' cwd = GXSTR_Replace(cwd, "\", "/")
'$End If
get_requested_filesystem_path
= _CWD$ + cannonicalise_path
(percent_decode
(Left$(raw_path
, path_len
)))
hexchars
= Mid$(raw_string
, i
+ 1, 2) final_string
= final_string
+ Chr$(Val("&H" + hexchars
)) 'String ends in something like "%1", or is invalid hex characters
final_string = final_string + "%" + hexchars
final_string
= final_string
+ Chr$(c
) percent_decode = final_string
split raw_path, "/", segments()
If segments
(i
) = "." Or segments
(i
) = "" Then uplevels = uplevels + 1
path = "/" + segments(i) + path
uplevels = uplevels - 1
'Note: if uplevels > 0 at this point, the path attempted to go above the root
'This is usually a client trying to be naughty
cannonicalise_path = path
'https://www.qb64.org/forum/index.php?topic=1607.0
curpos
= 1: arrpos
= LBound(loadMeArray
): LD
= Len(delim
) dpos
= InStr(curpos
, SplitMeString
, delim
) loadMeArray
(arrpos
) = Mid$(SplitMeString
, curpos
, dpos
- curpos
) arrpos = arrpos + 1
curpos = dpos + LD
dpos
= InStr(curpos
, SplitMeString
, delim
) loadMeArray
(arrpos
) = Mid$(SplitMeString
, curpos
)
eol
= InStr(Connections
(c
).read_buf
, CRLF
) l
= Left$(Connections
(c
).read_buf
, eol
- 1) Connections
(c
).read_buf
= Mid$(Connections
(c
).read_buf
, eol
+ 2) If Connections
(c
).http_version
= 0 Then 'First line not yet read process_start_line c, l
'headers complete; act upon request now
http_do_get c
http_do_head c
process_header c, l
'7230 3.1.1
'METHOD uri HTTP/x.y
If sp1
= 0 Then http_error
400, "Bad Request", c
'7231 4.3
Connections(c).method = HTTP_GET
Connections(c).method = HTTP_HEAD
http_error 501, "Not Implemented", c
sp2
= InStr(sp1
+ 1, l
, " ") If sp2
= 0 Or sp2
- sp1
= 1 Then http_error
400, "Bad Request", c
Connections
(c
).request_uri
= Mid$(l
, sp1
+ 1, sp2
- sp1
- 1)
'7230 2.6
http_error 400, "Bad Request", c
Connections(c).http_version = HTTP_10
Connections(c).http_version = HTTP_11
http_error 505, "HTTP Version Not Supported", c
'All headers ignored for now
http_send_status connection, code, message
http_send_header connection, "Content-Length", "0"
http_send_header connection, "Connection", "close"
http_end_headers connection
close_connection connection
Http_error_info.code = code
Http_error_info.message = message
Http_error_info.connection = connection