Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
M
mongoose
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
esp
mongoose
Commits
aa59dda9
Commit
aa59dda9
authored
Jan 09, 2014
by
Sergey Lyubka
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
wrapped read_from_cgi() into NO_CGI
parent
47b92e41
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
115 additions
and
114 deletions
+115
-114
mongoose.c
mongoose.c
+115
-114
No files found.
mongoose.c
View file @
aa59dda9
...
...
@@ -516,6 +516,63 @@ static int mg_snprintf(char *buf, size_t buflen, const char *fmt, ...) {
return
n
;
}
// Check whether full request is buffered. Return:
// -1 if request is malformed
// 0 if request is not yet fully buffered
// >0 actual request length, including last \r\n\r\n
static
int
get_request_len
(
const
char
*
s
,
int
buf_len
)
{
const
unsigned
char
*
buf
=
(
unsigned
char
*
)
s
;
int
i
;
for
(
i
=
0
;
i
<
buf_len
;
i
++
)
{
// Control characters are not allowed but >=128 are.
// Abort scan as soon as one malformed character is found.
if
(
!
isprint
(
buf
[
i
])
&&
buf
[
i
]
!=
'\r'
&&
buf
[
i
]
!=
'\n'
&&
buf
[
i
]
<
128
)
{
return
-
1
;
}
else
if
(
buf
[
i
]
==
'\n'
&&
i
+
1
<
buf_len
&&
buf
[
i
+
1
]
==
'\n'
)
{
return
i
+
2
;
}
else
if
(
buf
[
i
]
==
'\n'
&&
i
+
2
<
buf_len
&&
buf
[
i
+
1
]
==
'\r'
&&
buf
[
i
+
2
]
==
'\n'
)
{
return
i
+
3
;
}
}
return
0
;
}
// Skip the characters until one of the delimiters characters found.
// 0-terminate resulting word. Skip the rest of the delimiters if any.
// Advance pointer to buffer to the next word. Return found 0-terminated word.
static
char
*
skip
(
char
**
buf
,
const
char
*
delimiters
)
{
char
*
p
,
*
begin_word
,
*
end_word
,
*
end_delimiters
;
begin_word
=
*
buf
;
end_word
=
begin_word
+
strcspn
(
begin_word
,
delimiters
);
end_delimiters
=
end_word
+
strspn
(
end_word
,
delimiters
);
for
(
p
=
end_word
;
p
<
end_delimiters
;
p
++
)
{
*
p
=
'\0'
;
}
*
buf
=
end_delimiters
;
return
begin_word
;
}
// Parse HTTP headers from the given buffer, advance buffer to the point
// where parsing stopped.
static
void
parse_http_headers
(
char
**
buf
,
struct
mg_connection
*
ri
)
{
size_t
i
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
ri
->
http_headers
);
i
++
)
{
ri
->
http_headers
[
i
].
name
=
skip
(
buf
,
": "
);
ri
->
http_headers
[
i
].
value
=
skip
(
buf
,
"
\r\n
"
);
if
(
ri
->
http_headers
[
i
].
name
[
0
]
==
'\0'
)
break
;
ri
->
num_headers
=
i
+
1
;
}
}
static
const
char
*
status_code_to_str
(
int
status_code
)
{
switch
(
status_code
)
{
case
200
:
return
"OK"
;
...
...
@@ -677,6 +734,10 @@ static int mg_socketpair(sock_t sp[2]) {
return
ret
;
}
static
int
is_error
(
int
n
)
{
return
n
==
0
||
(
n
<
0
&&
errno
!=
EINTR
&&
errno
!=
EAGAIN
);
}
#ifndef NO_CGI
#ifdef _WIN32
static
pid_t
start_process
(
char
*
interp
,
const
char
*
cmd
,
const
char
*
env
,
...
...
@@ -941,6 +1002,58 @@ static void open_cgi_endpoint(struct connection *conn, const char *prog) {
closesocket
(
fds
[
1
]);
}
static
void
read_from_cgi
(
struct
connection
*
conn
)
{
char
buf
[
IOBUF_SIZE
];
int
len
,
n
=
recv
(
conn
->
endpoint
.
cgi_sock
,
buf
,
sizeof
(
buf
),
0
);
DBG
((
"%p %d"
,
conn
,
n
));
if
(
is_error
(
n
))
{
close_local_endpoint
(
conn
);
}
else
if
(
n
>
0
)
{
if
(
conn
->
num_bytes_sent
==
0
&&
conn
->
remote_iobuf
.
len
==
0
)
{
// Parse CGI headers, and modify the reply line if needed
if
((
len
=
get_request_len
(
buf
,
n
))
>
0
)
{
const
char
*
status
=
NULL
;
char
*
s
=
buf
,
buf2
[
sizeof
(
buf
)];
struct
mg_connection
c
;
int
i
,
k
;
memset
(
&
c
,
0
,
sizeof
(
c
));
buf
[
len
-
1
]
=
'\0'
;
parse_http_headers
(
&
s
,
&
c
);
if
(
mg_get_header
(
&
c
,
"Location"
)
!=
NULL
)
{
status
=
"302 Moved"
;
}
else
if
((
status
=
(
char
*
)
mg_get_header
(
&
c
,
"Status"
))
==
NULL
)
{
status
=
"200 OK"
;
}
k
=
mg_snprintf
(
buf2
,
sizeof
(
buf2
),
"HTTP/1.1 %s
\r\n
"
,
status
);
spool
(
&
conn
->
remote_iobuf
,
buf2
,
k
);
for
(
i
=
0
;
i
<
c
.
num_headers
;
i
++
)
{
k
=
mg_snprintf
(
buf2
,
sizeof
(
buf2
),
"%s: %s
\r\n
"
,
c
.
http_headers
[
i
].
name
,
c
.
http_headers
[
i
].
value
);
spool
(
&
conn
->
remote_iobuf
,
buf2
,
k
);
}
spool
(
&
conn
->
remote_iobuf
,
"
\r\n
"
,
2
);
memmove
(
buf
,
buf
+
len
,
n
-
len
);
n
-=
len
;
}
else
{
static
const
char
ok_200
[]
=
"HTTP/1.1 200 OK
\r\n
"
;
spool
(
&
conn
->
remote_iobuf
,
ok_200
,
sizeof
(
ok_200
)
-
1
);
}
}
spool
(
&
conn
->
remote_iobuf
,
buf
,
n
);
}
}
static
void
forward_post_data
(
struct
connection
*
conn
)
{
struct
iobuf
*
io
=
&
conn
->
local_iobuf
;
int
n
=
send
(
conn
->
endpoint
.
cgi_sock
,
io
->
buf
,
io
->
len
,
0
);
if
(
n
>
0
)
{
memmove
(
io
->
buf
,
io
->
buf
+
n
,
io
->
len
-
n
);
io
->
len
-=
n
;
}
}
#endif // !NO_CGI
// 'sa' must be an initialized address to bind to
...
...
@@ -1079,50 +1192,6 @@ static void close_conn(struct connection *conn) {
free
(
conn
);
}
// Check whether full request is buffered. Return:
// -1 if request is malformed
// 0 if request is not yet fully buffered
// >0 actual request length, including last \r\n\r\n
static
int
get_request_len
(
const
char
*
s
,
int
buf_len
)
{
const
unsigned
char
*
buf
=
(
unsigned
char
*
)
s
;
int
i
;
for
(
i
=
0
;
i
<
buf_len
;
i
++
)
{
// Control characters are not allowed but >=128 are.
// Abort scan as soon as one malformed character is found.
if
(
!
isprint
(
buf
[
i
])
&&
buf
[
i
]
!=
'\r'
&&
buf
[
i
]
!=
'\n'
&&
buf
[
i
]
<
128
)
{
return
-
1
;
}
else
if
(
buf
[
i
]
==
'\n'
&&
i
+
1
<
buf_len
&&
buf
[
i
+
1
]
==
'\n'
)
{
return
i
+
2
;
}
else
if
(
buf
[
i
]
==
'\n'
&&
i
+
2
<
buf_len
&&
buf
[
i
+
1
]
==
'\r'
&&
buf
[
i
+
2
]
==
'\n'
)
{
return
i
+
3
;
}
}
return
0
;
}
// Skip the characters until one of the delimiters characters found.
// 0-terminate resulting word. Skip the rest of the delimiters if any.
// Advance pointer to buffer to the next word. Return found 0-terminated word.
static
char
*
skip
(
char
**
buf
,
const
char
*
delimiters
)
{
char
*
p
,
*
begin_word
,
*
end_word
,
*
end_delimiters
;
begin_word
=
*
buf
;
end_word
=
begin_word
+
strcspn
(
begin_word
,
delimiters
);
end_delimiters
=
end_word
+
strspn
(
end_word
,
delimiters
);
for
(
p
=
end_word
;
p
<
end_delimiters
;
p
++
)
{
*
p
=
'\0'
;
}
*
buf
=
end_delimiters
;
return
begin_word
;
}
// Protect against directory disclosure attack by removing '..',
// excessive '/' and '\' characters
static
void
remove_double_dots_and_double_slashes
(
char
*
s
)
{
...
...
@@ -1167,20 +1236,6 @@ int mg_url_decode(const char *src, int src_len, char *dst,
return
i
>=
src_len
?
j
:
-
1
;
}
// Parse HTTP headers from the given buffer, advance buffer to the point
// where parsing stopped.
static
void
parse_http_headers
(
char
**
buf
,
struct
mg_connection
*
ri
)
{
size_t
i
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
ri
->
http_headers
);
i
++
)
{
ri
->
http_headers
[
i
].
name
=
skip
(
buf
,
": "
);
ri
->
http_headers
[
i
].
value
=
skip
(
buf
,
"
\r\n
"
);
if
(
ri
->
http_headers
[
i
].
name
[
0
]
==
'\0'
)
break
;
ri
->
num_headers
=
i
+
1
;
}
}
static
int
is_valid_http_method
(
const
char
*
method
)
{
return
!
strcmp
(
method
,
"GET"
)
||
!
strcmp
(
method
,
"POST"
)
||
!
strcmp
(
method
,
"HEAD"
)
||
!
strcmp
(
method
,
"CONNECT"
)
||
...
...
@@ -1688,10 +1743,6 @@ static void ping_idle_websocket_connection(struct connection *conn, time_t t) {
#define ping_idle_websocket_connection(conn, t)
#endif // !NO_WEBSOCKET
static
int
is_error
(
int
n
)
{
return
n
==
0
||
(
n
<
0
&&
errno
!=
EINTR
&&
errno
!=
EAGAIN
);
}
static
void
write_to_client
(
struct
connection
*
conn
)
{
struct
iobuf
*
io
=
&
conn
->
remote_iobuf
;
int
n
=
conn
->
ssl
==
NULL
?
send
(
conn
->
client_sock
,
io
->
buf
,
io
->
len
,
0
)
:
...
...
@@ -3183,15 +3234,6 @@ static void send_continue_if_expected(struct connection *conn) {
}
}
static
void
forward_post_data
(
struct
connection
*
conn
)
{
struct
iobuf
*
io
=
&
conn
->
local_iobuf
;
int
n
=
send
(
conn
->
endpoint
.
cgi_sock
,
io
->
buf
,
io
->
len
,
0
);
if
(
n
>
0
)
{
memmove
(
io
->
buf
,
io
->
buf
+
n
,
io
->
len
-
n
);
io
->
len
-=
n
;
}
}
static
int
is_valid_uri
(
const
char
*
uri
)
{
// Conform to http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.2
// URI can be an asterisk (*) or should start with slash.
...
...
@@ -3275,49 +3317,6 @@ static void read_from_client(struct connection *conn) {
}
}
static
void
read_from_cgi
(
struct
connection
*
conn
)
{
char
buf
[
IOBUF_SIZE
];
int
len
,
n
=
recv
(
conn
->
endpoint
.
cgi_sock
,
buf
,
sizeof
(
buf
),
0
);
DBG
((
"%p %d"
,
conn
,
n
));
if
(
is_error
(
n
))
{
close_local_endpoint
(
conn
);
}
else
if
(
n
>
0
)
{
if
(
conn
->
num_bytes_sent
==
0
&&
conn
->
remote_iobuf
.
len
==
0
)
{
// Parse CGI headers, and modify the reply line if needed
if
((
len
=
get_request_len
(
buf
,
n
))
>
0
)
{
const
char
*
status
=
NULL
;
char
*
s
=
buf
,
buf2
[
sizeof
(
buf
)];
struct
mg_connection
c
;
int
i
,
k
;
memset
(
&
c
,
0
,
sizeof
(
c
));
buf
[
len
-
1
]
=
'\0'
;
parse_http_headers
(
&
s
,
&
c
);
if
(
mg_get_header
(
&
c
,
"Location"
)
!=
NULL
)
{
status
=
"302 Moved"
;
}
else
if
((
status
=
(
char
*
)
mg_get_header
(
&
c
,
"Status"
))
==
NULL
)
{
status
=
"200 OK"
;
}
k
=
mg_snprintf
(
buf2
,
sizeof
(
buf2
),
"HTTP/1.1 %s
\r\n
"
,
status
);
spool
(
&
conn
->
remote_iobuf
,
buf2
,
k
);
for
(
i
=
0
;
i
<
c
.
num_headers
;
i
++
)
{
k
=
mg_snprintf
(
buf2
,
sizeof
(
buf2
),
"%s: %s
\r\n
"
,
c
.
http_headers
[
i
].
name
,
c
.
http_headers
[
i
].
value
);
spool
(
&
conn
->
remote_iobuf
,
buf2
,
k
);
}
spool
(
&
conn
->
remote_iobuf
,
"
\r\n
"
,
2
);
memmove
(
buf
,
buf
+
len
,
n
-
len
);
n
-=
len
;
}
else
{
static
const
char
ok_200
[]
=
"HTTP/1.1 200 OK
\r\n
"
;
spool
(
&
conn
->
remote_iobuf
,
ok_200
,
sizeof
(
ok_200
)
-
1
);
}
}
spool
(
&
conn
->
remote_iobuf
,
buf
,
n
);
}
}
#ifndef NO_LOGGING
static
void
log_header
(
const
struct
mg_connection
*
conn
,
const
char
*
header
,
FILE
*
fp
)
{
...
...
@@ -3475,10 +3474,12 @@ unsigned int mg_poll_server(struct mg_server *server, int milliseconds) {
conn
->
last_activity_time
=
current_time
;
read_from_client
(
conn
);
}
#ifndef NO_CGI
if
(
conn
->
endpoint_type
==
EP_CGI
&&
FD_ISSET
(
conn
->
endpoint
.
cgi_sock
,
&
read_set
))
{
read_from_cgi
(
conn
);
}
#endif
if
(
FD_ISSET
(
conn
->
client_sock
,
&
write_set
))
{
conn
->
last_activity_time
=
current_time
;
write_to_client
(
conn
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment