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
e0b61092
Commit
e0b61092
authored
Jan 11, 2014
by
Sergey Lyubka
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added -DNO_FILESYSTEM
parent
d29f8496
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
208 additions
and
173 deletions
+208
-173
main.c
build/main.c
+10
-4
mongoose.c
mongoose.c
+198
-169
No files found.
build/main.c
View file @
e0b61092
...
@@ -120,7 +120,9 @@ static void show_usage_and_exit(void) {
...
@@ -120,7 +120,9 @@ static void show_usage_and_exit(void) {
fprintf
(
stderr
,
"Mongoose version %s (c) Sergey Lyubka, built on %s
\n
"
,
fprintf
(
stderr
,
"Mongoose version %s (c) Sergey Lyubka, built on %s
\n
"
,
MONGOOSE_VERSION
,
__DATE__
);
MONGOOSE_VERSION
,
__DATE__
);
fprintf
(
stderr
,
"Usage:
\n
"
);
fprintf
(
stderr
,
"Usage:
\n
"
);
#ifndef NO_AUTH
fprintf
(
stderr
,
" mongoose -A <htpasswd_file> <realm> <user> <passwd>
\n
"
);
fprintf
(
stderr
,
" mongoose -A <htpasswd_file> <realm> <user> <passwd>
\n
"
);
#endif
fprintf
(
stderr
,
" mongoose [config_file]
\n
"
);
fprintf
(
stderr
,
" mongoose [config_file]
\n
"
);
fprintf
(
stderr
,
" mongoose [-option value ...]
\n
"
);
fprintf
(
stderr
,
" mongoose [-option value ...]
\n
"
);
fprintf
(
stderr
,
"
\n
OPTIONS:
\n
"
);
fprintf
(
stderr
,
"
\n
OPTIONS:
\n
"
);
...
@@ -142,7 +144,7 @@ static const char *config_file_top_comment =
...
@@ -142,7 +144,7 @@ static const char *config_file_top_comment =
"# To make a change, remove leading '#', modify option's value,
\n
"
"# To make a change, remove leading '#', modify option's value,
\n
"
"# save this file and then restart Mongoose.
\n\n
"
;
"# save this file and then restart Mongoose.
\n\n
"
;
static
const
char
*
get_url_to_
first_open_port
(
const
struct
mg_server
*
server
)
{
static
const
char
*
get_url_to_
me
(
const
struct
mg_server
*
server
)
{
static
char
url
[
100
];
static
char
url
[
100
];
const
char
*
s
=
mg_get_option
(
server
,
"listening_port"
);
const
char
*
s
=
mg_get_option
(
server
,
"listening_port"
);
const
char
*
cert
=
mg_get_option
(
server
,
"ssl_certificate"
);
const
char
*
cert
=
mg_get_option
(
server
,
"ssl_certificate"
);
...
@@ -335,6 +337,7 @@ static void set_absolute_path(char *options[], const char *option_name,
...
@@ -335,6 +337,7 @@ static void set_absolute_path(char *options[], const char *option_name,
}
}
}
}
#ifndef NO_AUTH
int
modify_passwords_file
(
const
char
*
fname
,
const
char
*
domain
,
int
modify_passwords_file
(
const
char
*
fname
,
const
char
*
domain
,
const
char
*
user
,
const
char
*
pass
)
{
const
char
*
user
,
const
char
*
pass
)
{
int
found
;
int
found
;
...
@@ -397,6 +400,7 @@ int modify_passwords_file(const char *fname, const char *domain,
...
@@ -397,6 +400,7 @@ int modify_passwords_file(const char *fname, const char *domain,
return
1
;
return
1
;
}
}
#endif
static
void
start_mongoose
(
int
argc
,
char
*
argv
[])
{
static
void
start_mongoose
(
int
argc
,
char
*
argv
[])
{
char
*
options
[
MAX_OPTIONS
];
char
*
options
[
MAX_OPTIONS
];
...
@@ -406,6 +410,7 @@ static void start_mongoose(int argc, char *argv[]) {
...
@@ -406,6 +410,7 @@ static void start_mongoose(int argc, char *argv[]) {
die
(
"%s"
,
"Failed to start Mongoose."
);
die
(
"%s"
,
"Failed to start Mongoose."
);
}
}
#ifndef NO_AUTH
// Edit passwords file if -A option is specified
// Edit passwords file if -A option is specified
if
(
argc
>
1
&&
!
strcmp
(
argv
[
1
],
"-A"
))
{
if
(
argc
>
1
&&
!
strcmp
(
argv
[
1
],
"-A"
))
{
if
(
argc
!=
6
)
{
if
(
argc
!=
6
)
{
...
@@ -414,6 +419,7 @@ static void start_mongoose(int argc, char *argv[]) {
...
@@ -414,6 +419,7 @@ static void start_mongoose(int argc, char *argv[]) {
exit
(
modify_passwords_file
(
argv
[
2
],
argv
[
3
],
argv
[
4
],
argv
[
5
])
?
exit
(
modify_passwords_file
(
argv
[
2
],
argv
[
3
],
argv
[
4
],
argv
[
5
])
?
EXIT_SUCCESS
:
EXIT_FAILURE
);
EXIT_SUCCESS
:
EXIT_FAILURE
);
}
}
#endif
// Show usage if -h or --help options are specified
// Show usage if -h or --help options are specified
if
(
argc
==
2
&&
(
!
strcmp
(
argv
[
1
],
"-h"
)
||
!
strcmp
(
argv
[
1
],
"--help"
)))
{
if
(
argc
==
2
&&
(
!
strcmp
(
argv
[
1
],
"-h"
)
||
!
strcmp
(
argv
[
1
],
"--help"
)))
{
...
@@ -882,8 +888,8 @@ static LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam,
...
@@ -882,8 +888,8 @@ static LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam,
manage_service
(
LOWORD
(
wParam
));
manage_service
(
LOWORD
(
wParam
));
break
;
break
;
case
ID_CONNECT
:
case
ID_CONNECT
:
printf
(
"[%s]
\n
"
,
get_url_to_
first_open_port
(
server
));
printf
(
"[%s]
\n
"
,
get_url_to_
me
(
server
));
ShellExecute
(
NULL
,
"open"
,
get_url_to_
first_open_port
(
server
),
ShellExecute
(
NULL
,
"open"
,
get_url_to_
me
(
server
),
NULL
,
NULL
,
SW_SHOW
);
NULL
,
NULL
,
SW_SHOW
);
break
;
break
;
}
}
...
@@ -980,7 +986,7 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR cmdline, int show) {
...
@@ -980,7 +986,7 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR cmdline, int show) {
-
(
void
)
openBrowser
{
-
(
void
)
openBrowser
{
[[
NSWorkspace
sharedWorkspace
]
[[
NSWorkspace
sharedWorkspace
]
openURL
:
[
NSURL
URLWithString
:
openURL
:
[
NSURL
URLWithString
:
[
NSString
stringWithUTF8String
:
get_url_to_
first_open_port
(
server
)]]];
[
NSString
stringWithUTF8String
:
get_url_to_
me
(
server
)]]];
}
}
-
(
void
)
editConfig
{
-
(
void
)
editConfig
{
create_config_file
(
config_file
);
create_config_file
(
config_file
);
...
...
mongoose.c
View file @
e0b61092
...
@@ -189,6 +189,14 @@ struct ll { struct ll *prev, *next; };
...
@@ -189,6 +189,14 @@ struct ll { struct ll *prev, *next; };
#define DBG(x)
#define DBG(x)
#endif
#endif
#ifdef NO_FILESYSTEM
#define NO_AUTH
#define NO_CGI
#define NO_DAV
#define NO_DIRECTORY_LISTING
#define NO_LOGGING
#endif
union
socket_address
{
union
socket_address
{
struct
sockaddr
sa
;
struct
sockaddr
sa
;
struct
sockaddr_in
sin
;
struct
sockaddr_in
sin
;
...
@@ -217,10 +225,21 @@ struct dir_entry {
...
@@ -217,10 +225,21 @@ struct dir_entry {
// NOTE(lsm): this enum shoulds be in sync with the config_options.
// NOTE(lsm): this enum shoulds be in sync with the config_options.
enum
{
enum
{
ACCESS_CONTROL_LIST
,
ACCESS_LOG_FILE
,
AUTH_DOMAIN
,
CGI_INTERPRETER
,
ACCESS_CONTROL_LIST
,
#ifndef NO_FILESYSTEM
ACCESS_LOG_FILE
,
AUTH_DOMAIN
,
CGI_INTERPRETER
,
CGI_PATTERN
,
DAV_AUTH_FILE
,
DOCUMENT_ROOT
,
ENABLE_DIRECTORY_LISTING
,
CGI_PATTERN
,
DAV_AUTH_FILE
,
DOCUMENT_ROOT
,
ENABLE_DIRECTORY_LISTING
,
EXTRA_MIME_TYPES
,
GLOBAL_AUTH_FILE
,
HIDE_FILES_PATTERN
,
#endif
IDLE_TIMEOUT_MS
,
INDEX_FILES
,
LISTENING_PORT
,
EXTRA_MIME_TYPES
,
#ifndef NO_FILESYSTEM
GLOBAL_AUTH_FILE
,
#endif
HIDE_FILES_PATTERN
,
IDLE_TIMEOUT_MS
,
#ifndef NO_FILESYSTEM
INDEX_FILES
,
#endif
LISTENING_PORT
,
#ifndef _WIN32
#ifndef _WIN32
RUN_AS_USER
,
RUN_AS_USER
,
#endif
#endif
...
@@ -230,6 +249,37 @@ enum {
...
@@ -230,6 +249,37 @@ enum {
URL_REWRITES
,
NUM_OPTIONS
URL_REWRITES
,
NUM_OPTIONS
};
};
static
const
char
*
static_config_options
[]
=
{
"access_control_list"
,
NULL
,
#ifndef NO_FILESYSTEM
"access_log_file"
,
NULL
,
"auth_domain"
,
"mydomain.com"
,
"cgi_interpreter"
,
NULL
,
"cgi_pattern"
,
"**.cgi$|**.pl$|**.php$"
,
"dav_auth_file"
,
NULL
,
"document_root"
,
NULL
,
"enable_directory_listing"
,
"yes"
,
#endif
"extra_mime_types"
,
NULL
,
#ifndef NO_FILESYSTEM
"global_auth_file"
,
NULL
,
#endif
"hide_files_patterns"
,
NULL
,
"idle_timeout_ms"
,
"30000"
,
#ifndef NO_FILESYSTEM
"index_files"
,
"index.html,index.htm,index.cgi,index.php,index.lp"
,
#endif
"listening_port"
,
NULL
,
#ifndef _WIN32
"run_as_user"
,
NULL
,
#endif
#ifdef USE_SSL
"ssl_certificate"
,
NULL
,
#endif
"url_rewrites"
,
NULL
,
NULL
};
struct
mg_server
{
struct
mg_server
{
sock_t
listening_sock
;
sock_t
listening_sock
;
union
socket_address
lsa
;
// Listening socket address
union
socket_address
lsa
;
// Listening socket address
...
@@ -339,36 +389,6 @@ static const struct {
...
@@ -339,36 +389,6 @@ static const struct {
{
NULL
,
0
,
NULL
}
{
NULL
,
0
,
NULL
}
};
};
static
const
char
*
static_config_options
[]
=
{
"access_control_list"
,
NULL
,
"access_log_file"
,
NULL
,
"auth_domain"
,
"mydomain.com"
,
"cgi_interpreter"
,
NULL
,
"cgi_pattern"
,
"**.cgi$|**.pl$|**.php$"
,
"dav_auth_file"
,
NULL
,
"document_root"
,
NULL
,
"enable_directory_listing"
,
"yes"
,
"extra_mime_types"
,
NULL
,
"global_auth_file"
,
NULL
,
"hide_files_patterns"
,
NULL
,
"idle_timeout_ms"
,
"30000"
,
"index_files"
,
"index.html,index.htm,index.cgi,index.php,index.lp"
,
"listening_port"
,
NULL
,
#ifndef _WIN32
"run_as_user"
,
NULL
,
#endif
#ifdef USE_SSL
"ssl_certificate"
,
NULL
,
#endif
"url_rewrites"
,
NULL
,
NULL
};
static
const
char
*
static_month_names
[]
=
{
"Jan"
,
"Feb"
,
"Mar"
,
"Apr"
,
"May"
,
"Jun"
,
"Jul"
,
"Aug"
,
"Sep"
,
"Oct"
,
"Nov"
,
"Dec"
};
void
*
mg_start_thread
(
void
*
(
*
f
)(
void
*
),
void
*
p
)
{
void
*
mg_start_thread
(
void
*
(
*
f
)(
void
*
),
void
*
p
)
{
#ifdef _WIN32
#ifdef _WIN32
return
(
void
*
)
_beginthread
((
void
(
__cdecl
*
)(
void
*
))
f
,
0
,
p
);
return
(
void
*
)
_beginthread
((
void
(
__cdecl
*
)(
void
*
))
f
,
0
,
p
);
...
@@ -1413,6 +1433,18 @@ static int mg_strncasecmp(const char *s1, const char *s2, size_t len) {
...
@@ -1413,6 +1433,18 @@ static int mg_strncasecmp(const char *s1, const char *s2, size_t len) {
return
diff
;
return
diff
;
}
}
// Return HTTP header value, or NULL if not found.
const
char
*
mg_get_header
(
const
struct
mg_connection
*
ri
,
const
char
*
s
)
{
int
i
;
for
(
i
=
0
;
i
<
ri
->
num_headers
;
i
++
)
if
(
!
mg_strcasecmp
(
s
,
ri
->
http_headers
[
i
].
name
))
return
ri
->
http_headers
[
i
].
value
;
return
NULL
;
}
#ifndef NO_FILESYSTEM
// Perform case-insensitive match of string against pattern
// Perform case-insensitive match of string against pattern
static
int
match_prefix
(
const
char
*
pattern
,
int
pattern_len
,
const
char
*
str
)
{
static
int
match_prefix
(
const
char
*
pattern
,
int
pattern_len
,
const
char
*
str
)
{
const
char
*
or_str
;
const
char
*
or_str
;
...
@@ -1453,17 +1485,6 @@ static int match_prefix(const char *pattern, int pattern_len, const char *str) {
...
@@ -1453,17 +1485,6 @@ static int match_prefix(const char *pattern, int pattern_len, const char *str) {
return
j
;
return
j
;
}
}
// Return HTTP header value, or NULL if not found.
const
char
*
mg_get_header
(
const
struct
mg_connection
*
ri
,
const
char
*
s
)
{
int
i
;
for
(
i
=
0
;
i
<
ri
->
num_headers
;
i
++
)
if
(
!
mg_strcasecmp
(
s
,
ri
->
http_headers
[
i
].
name
))
return
ri
->
http_headers
[
i
].
value
;
return
NULL
;
}
// Return 1 if real file has been found, 0 otherwise
// Return 1 if real file has been found, 0 otherwise
static
int
convert_uri_to_file_name
(
struct
connection
*
conn
,
char
*
buf
,
static
int
convert_uri_to_file_name
(
struct
connection
*
conn
,
char
*
buf
,
size_t
buf_len
,
file_stat_t
*
st
)
{
size_t
buf_len
,
file_stat_t
*
st
)
{
...
@@ -1508,6 +1529,7 @@ static int convert_uri_to_file_name(struct connection *conn, char *buf,
...
@@ -1508,6 +1529,7 @@ static int convert_uri_to_file_name(struct connection *conn, char *buf,
return
0
;
return
0
;
}
}
#endif // NO_FILESYSTEM
static
int
should_keep_alive
(
const
struct
mg_connection
*
conn
)
{
static
int
should_keep_alive
(
const
struct
mg_connection
*
conn
)
{
const
char
*
method
=
conn
->
request_method
;
const
char
*
method
=
conn
->
request_method
;
...
@@ -1518,17 +1540,6 @@ static int should_keep_alive(const struct mg_connection *conn) {
...
@@ -1518,17 +1540,6 @@ static int should_keep_alive(const struct mg_connection *conn) {
(
header
==
NULL
&&
http_version
&&
!
strcmp
(
http_version
,
"1.1"
)));
(
header
==
NULL
&&
http_version
&&
!
strcmp
(
http_version
,
"1.1"
)));
}
}
static
const
char
*
suggest_connection_header
(
const
struct
mg_connection
*
conn
)
{
return
should_keep_alive
(
conn
)
?
"keep-alive"
:
"close"
;
}
static
void
mg_strlcpy
(
register
char
*
dst
,
register
const
char
*
src
,
size_t
n
)
{
for
(;
*
src
!=
'\0'
&&
n
>
1
;
n
--
)
{
*
dst
++
=
*
src
++
;
}
*
dst
=
'\0'
;
}
int
mg_write
(
struct
mg_connection
*
c
,
const
void
*
buf
,
int
len
)
{
int
mg_write
(
struct
mg_connection
*
c
,
const
void
*
buf
,
int
len
)
{
return
spool
(
&
((
struct
connection
*
)
c
)
->
remote_iobuf
,
buf
,
len
);
return
spool
(
&
((
struct
connection
*
)
c
)
->
remote_iobuf
,
buf
,
len
);
}
}
...
@@ -1903,111 +1914,30 @@ const char *mg_get_mime_type(const char *path) {
...
@@ -1903,111 +1914,30 @@ const char *mg_get_mime_type(const char *path) {
return
"text/plain"
;
return
"text/plain"
;
}
}
// Look at the "path" extension and figure what mime type it has.
static
struct
uri_handler
*
find_uri_handler
(
struct
mg_server
*
server
,
// Store mime type in the vector.
const
char
*
uri
)
{
static
void
get_mime_type
(
const
struct
mg_server
*
server
,
const
char
*
path
,
struct
ll
*
lp
,
*
tmp
;
struct
vec
*
vec
)
{
struct
uri_handler
*
uh
;
struct
vec
ext_vec
,
mime_vec
;
const
char
*
list
,
*
ext
;
size_t
path_len
;
path_len
=
strlen
(
path
);
// Scan user-defined mime types first, in case user wants to
// override default mime types.
list
=
server
->
config_options
[
EXTRA_MIME_TYPES
];
while
((
list
=
next_option
(
list
,
&
ext_vec
,
&
mime_vec
))
!=
NULL
)
{
// ext now points to the path suffix
ext
=
path
+
path_len
-
ext_vec
.
len
;
if
(
mg_strncasecmp
(
ext
,
ext_vec
.
ptr
,
ext_vec
.
len
)
==
0
)
{
*
vec
=
mime_vec
;
return
;
}
}
vec
->
ptr
=
mg_get_mime_type
(
path
);
vec
->
len
=
strlen
(
vec
->
ptr
);
}
static
int
parse_range_header
(
const
char
*
header
,
int64_t
*
a
,
int64_t
*
b
)
{
return
sscanf
(
header
,
"bytes=%"
INT64_FMT
"-%"
INT64_FMT
,
a
,
b
);
}
static
void
gmt_time_string
(
char
*
buf
,
size_t
buf_len
,
time_t
*
t
)
{
strftime
(
buf
,
buf_len
,
"%a, %d %b %Y %H:%M:%S GMT"
,
gmtime
(
t
));
}
static
void
construct_etag
(
char
*
buf
,
size_t
buf_len
,
const
file_stat_t
*
st
)
{
mg_snprintf
(
buf
,
buf_len
,
"
\"
%lx.%"
INT64_FMT
"
\"
"
,
(
unsigned
long
)
st
->
st_mtime
,
(
int64_t
)
st
->
st_size
);
}
static
void
open_file_endpoint
(
struct
connection
*
conn
,
const
char
*
path
,
file_stat_t
*
st
)
{
char
date
[
64
],
lm
[
64
],
etag
[
64
],
range
[
64
],
headers
[
500
];
const
char
*
msg
=
"OK"
,
*
hdr
;
time_t
curtime
=
time
(
NULL
);
int64_t
r1
,
r2
;
struct
vec
mime_vec
;
int
n
;
conn
->
endpoint_type
=
EP_FILE
;
set_close_on_exec
(
conn
->
endpoint
.
fd
);
conn
->
mg_conn
.
status_code
=
200
;
get_mime_type
(
conn
->
server
,
path
,
&
mime_vec
);
conn
->
cl
=
st
->
st_size
;
range
[
0
]
=
'\0'
;
// If Range: header specified, act accordingly
LINKED_LIST_FOREACH
(
&
server
->
uri_handlers
,
lp
,
tmp
)
{
r1
=
r2
=
0
;
uh
=
LINKED_LIST_ENTRY
(
lp
,
struct
uri_handler
,
link
);
hdr
=
mg_get_header
(
&
conn
->
mg_conn
,
"Range"
);
if
(
!
strncmp
(
uh
->
uri
,
uri
,
strlen
(
uh
->
uri
)))
return
uh
;
if
(
hdr
!=
NULL
&&
(
n
=
parse_range_header
(
hdr
,
&
r1
,
&
r2
))
>
0
&&
r1
>=
0
&&
r2
>=
0
)
{
conn
->
mg_conn
.
status_code
=
206
;
conn
->
cl
=
n
==
2
?
(
r2
>
conn
->
cl
?
conn
->
cl
:
r2
)
-
r1
+
1
:
conn
->
cl
-
r1
;
mg_snprintf
(
range
,
sizeof
(
range
),
"Content-Range: bytes "
"%"
INT64_FMT
"-%"
INT64_FMT
"/%"
INT64_FMT
"
\r\n
"
,
r1
,
r1
+
conn
->
cl
-
1
,
(
int64_t
)
st
->
st_size
);
msg
=
"Partial Content"
;
lseek
(
conn
->
endpoint
.
fd
,
r1
,
SEEK_SET
);
}
}
// Prepare Etag, Date, Last-Modified headers. Must be in UTC, according to
return
NULL
;
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3
gmt_time_string
(
date
,
sizeof
(
date
),
&
curtime
);
gmt_time_string
(
lm
,
sizeof
(
lm
),
&
st
->
st_mtime
);
construct_etag
(
etag
,
sizeof
(
etag
),
st
);
n
=
mg_snprintf
(
headers
,
sizeof
(
headers
),
"HTTP/1.1 %d %s
\r\n
"
"Date: %s
\r\n
"
"Last-Modified: %s
\r\n
"
"Etag: %s
\r\n
"
"Content-Type: %.*s
\r\n
"
"Content-Length: %"
INT64_FMT
"
\r\n
"
"Connection: %s
\r\n
"
"Accept-Ranges: bytes
\r\n
"
"%s%s
\r\n
"
,
conn
->
mg_conn
.
status_code
,
msg
,
date
,
lm
,
etag
,
(
int
)
mime_vec
.
len
,
mime_vec
.
ptr
,
conn
->
cl
,
suggest_connection_header
(
&
conn
->
mg_conn
),
range
,
USE_EXTRA_HTTP_HEADERS
);
spool
(
&
conn
->
remote_iobuf
,
headers
,
n
);
if
(
!
strcmp
(
conn
->
mg_conn
.
request_method
,
"HEAD"
))
{
conn
->
flags
|=
CONN_SPOOL_DONE
;
close
(
conn
->
endpoint
.
fd
);
conn
->
endpoint_type
=
EP_NONE
;
}
}
}
#ifndef NO_FILESYSTEM
// Convert month to the month number. Return -1 on error, or month number
// Convert month to the month number. Return -1 on error, or month number
static
int
get_month_index
(
const
char
*
s
)
{
static
int
get_month_index
(
const
char
*
s
)
{
static
const
char
*
month_names
[]
=
{
"Jan"
,
"Feb"
,
"Mar"
,
"Apr"
,
"May"
,
"Jun"
,
"Jul"
,
"Aug"
,
"Sep"
,
"Oct"
,
"Nov"
,
"Dec"
};
int
i
;
int
i
;
for
(
i
=
0
;
i
<
(
int
)
ARRAY_SIZE
(
static_
month_names
);
i
++
)
for
(
i
=
0
;
i
<
(
int
)
ARRAY_SIZE
(
month_names
);
i
++
)
if
(
!
strcmp
(
s
,
static_
month_names
[
i
]))
if
(
!
strcmp
(
s
,
month_names
[
i
]))
return
i
;
return
i
;
return
-
1
;
return
-
1
;
...
@@ -2045,6 +1975,41 @@ static time_t parse_date_string(const char *datetime) {
...
@@ -2045,6 +1975,41 @@ static time_t parse_date_string(const char *datetime) {
return
result
;
return
result
;
}
}
// Look at the "path" extension and figure what mime type it has.
// Store mime type in the vector.
static
void
get_mime_type
(
const
struct
mg_server
*
server
,
const
char
*
path
,
struct
vec
*
vec
)
{
struct
vec
ext_vec
,
mime_vec
;
const
char
*
list
,
*
ext
;
size_t
path_len
;
path_len
=
strlen
(
path
);
// Scan user-defined mime types first, in case user wants to
// override default mime types.
list
=
server
->
config_options
[
EXTRA_MIME_TYPES
];
while
((
list
=
next_option
(
list
,
&
ext_vec
,
&
mime_vec
))
!=
NULL
)
{
// ext now points to the path suffix
ext
=
path
+
path_len
-
ext_vec
.
len
;
if
(
mg_strncasecmp
(
ext
,
ext_vec
.
ptr
,
ext_vec
.
len
)
==
0
)
{
*
vec
=
mime_vec
;
return
;
}
}
vec
->
ptr
=
mg_get_mime_type
(
path
);
vec
->
len
=
strlen
(
vec
->
ptr
);
}
static
const
char
*
suggest_connection_header
(
const
struct
mg_connection
*
conn
)
{
return
should_keep_alive
(
conn
)
?
"keep-alive"
:
"close"
;
}
static
void
construct_etag
(
char
*
buf
,
size_t
buf_len
,
const
file_stat_t
*
st
)
{
mg_snprintf
(
buf
,
buf_len
,
"
\"
%lx.%"
INT64_FMT
"
\"
"
,
(
unsigned
long
)
st
->
st_mtime
,
(
int64_t
)
st
->
st_size
);
}
// Return True if we should reply 304 Not Modified.
// Return True if we should reply 304 Not Modified.
static
int
is_not_modified
(
const
struct
connection
*
conn
,
static
int
is_not_modified
(
const
struct
connection
*
conn
,
const
file_stat_t
*
stp
)
{
const
file_stat_t
*
stp
)
{
...
@@ -2056,19 +2021,6 @@ static int is_not_modified(const struct connection *conn,
...
@@ -2056,19 +2021,6 @@ static int is_not_modified(const struct connection *conn,
(
ims
!=
NULL
&&
stp
->
st_mtime
<=
parse_date_string
(
ims
));
(
ims
!=
NULL
&&
stp
->
st_mtime
<=
parse_date_string
(
ims
));
}
}
static
struct
uri_handler
*
find_uri_handler
(
struct
mg_server
*
server
,
const
char
*
uri
)
{
struct
ll
*
lp
,
*
tmp
;
struct
uri_handler
*
uh
;
LINKED_LIST_FOREACH
(
&
server
->
uri_handlers
,
lp
,
tmp
)
{
uh
=
LINKED_LIST_ENTRY
(
lp
,
struct
uri_handler
,
link
);
if
(
!
strncmp
(
uh
->
uri
,
uri
,
strlen
(
uh
->
uri
)))
return
uh
;
}
return
NULL
;
}
// For given directory path, substitute it to valid index file.
// For given directory path, substitute it to valid index file.
// Return 0 if index file has been found, -1 if not found.
// Return 0 if index file has been found, -1 if not found.
// If the file is found, it's stats is returned in stp.
// If the file is found, it's stats is returned in stp.
...
@@ -2096,7 +2048,8 @@ static int find_index_file(struct connection *conn, char *path,
...
@@ -2096,7 +2048,8 @@ static int find_index_file(struct connection *conn, char *path,
continue
;
continue
;
// Prepare full path to the index file
// Prepare full path to the index file
mg_strlcpy
(
path
+
n
+
1
,
filename_vec
.
ptr
,
filename_vec
.
len
+
1
);
strncpy
(
path
+
n
+
1
,
filename_vec
.
ptr
,
filename_vec
.
len
);
path
[
n
+
1
+
filename_vec
.
len
]
=
'\0'
;
//DBG(("[%s]", path));
//DBG(("[%s]", path));
...
@@ -2117,6 +2070,76 @@ static int find_index_file(struct connection *conn, char *path,
...
@@ -2117,6 +2070,76 @@ static int find_index_file(struct connection *conn, char *path,
return
found
;
return
found
;
}
}
static
int
parse_range_header
(
const
char
*
header
,
int64_t
*
a
,
int64_t
*
b
)
{
return
sscanf
(
header
,
"bytes=%"
INT64_FMT
"-%"
INT64_FMT
,
a
,
b
);
}
static
void
gmt_time_string
(
char
*
buf
,
size_t
buf_len
,
time_t
*
t
)
{
strftime
(
buf
,
buf_len
,
"%a, %d %b %Y %H:%M:%S GMT"
,
gmtime
(
t
));
}
static
void
open_file_endpoint
(
struct
connection
*
conn
,
const
char
*
path
,
file_stat_t
*
st
)
{
char
date
[
64
],
lm
[
64
],
etag
[
64
],
range
[
64
],
headers
[
500
];
const
char
*
msg
=
"OK"
,
*
hdr
;
time_t
curtime
=
time
(
NULL
);
int64_t
r1
,
r2
;
struct
vec
mime_vec
;
int
n
;
conn
->
endpoint_type
=
EP_FILE
;
set_close_on_exec
(
conn
->
endpoint
.
fd
);
conn
->
mg_conn
.
status_code
=
200
;
get_mime_type
(
conn
->
server
,
path
,
&
mime_vec
);
conn
->
cl
=
st
->
st_size
;
range
[
0
]
=
'\0'
;
// If Range: header specified, act accordingly
r1
=
r2
=
0
;
hdr
=
mg_get_header
(
&
conn
->
mg_conn
,
"Range"
);
if
(
hdr
!=
NULL
&&
(
n
=
parse_range_header
(
hdr
,
&
r1
,
&
r2
))
>
0
&&
r1
>=
0
&&
r2
>=
0
)
{
conn
->
mg_conn
.
status_code
=
206
;
conn
->
cl
=
n
==
2
?
(
r2
>
conn
->
cl
?
conn
->
cl
:
r2
)
-
r1
+
1
:
conn
->
cl
-
r1
;
mg_snprintf
(
range
,
sizeof
(
range
),
"Content-Range: bytes "
"%"
INT64_FMT
"-%"
INT64_FMT
"/%"
INT64_FMT
"
\r\n
"
,
r1
,
r1
+
conn
->
cl
-
1
,
(
int64_t
)
st
->
st_size
);
msg
=
"Partial Content"
;
lseek
(
conn
->
endpoint
.
fd
,
r1
,
SEEK_SET
);
}
// Prepare Etag, Date, Last-Modified headers. Must be in UTC, according to
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3
gmt_time_string
(
date
,
sizeof
(
date
),
&
curtime
);
gmt_time_string
(
lm
,
sizeof
(
lm
),
&
st
->
st_mtime
);
construct_etag
(
etag
,
sizeof
(
etag
),
st
);
n
=
mg_snprintf
(
headers
,
sizeof
(
headers
),
"HTTP/1.1 %d %s
\r\n
"
"Date: %s
\r\n
"
"Last-Modified: %s
\r\n
"
"Etag: %s
\r\n
"
"Content-Type: %.*s
\r\n
"
"Content-Length: %"
INT64_FMT
"
\r\n
"
"Connection: %s
\r\n
"
"Accept-Ranges: bytes
\r\n
"
"%s%s
\r\n
"
,
conn
->
mg_conn
.
status_code
,
msg
,
date
,
lm
,
etag
,
(
int
)
mime_vec
.
len
,
mime_vec
.
ptr
,
conn
->
cl
,
suggest_connection_header
(
&
conn
->
mg_conn
),
range
,
USE_EXTRA_HTTP_HEADERS
);
spool
(
&
conn
->
remote_iobuf
,
headers
,
n
);
if
(
!
strcmp
(
conn
->
mg_conn
.
request_method
,
"HEAD"
))
{
conn
->
flags
|=
CONN_SPOOL_DONE
;
close
(
conn
->
endpoint
.
fd
);
conn
->
endpoint_type
=
EP_NONE
;
}
}
#endif // NO_FILESYSTEM
static
void
write_terminating_chunk
(
struct
connection
*
conn
)
{
static
void
write_terminating_chunk
(
struct
connection
*
conn
)
{
mg_write
(
&
conn
->
mg_conn
,
"0
\r\n\r\n
"
,
5
);
mg_write
(
&
conn
->
mg_conn
,
"0
\r\n\r\n
"
,
5
);
}
}
...
@@ -2584,7 +2607,6 @@ static void forward_put_data(struct connection *conn) {
...
@@ -2584,7 +2607,6 @@ static void forward_put_data(struct connection *conn) {
}
}
}
}
}
}
#endif // NO_DAV
static
void
send_options
(
struct
connection
*
conn
)
{
static
void
send_options
(
struct
connection
*
conn
)
{
static
const
char
reply
[]
=
"HTTP/1.1 200 OK
\r\n
Allow: GET, POST, HEAD, "
static
const
char
reply
[]
=
"HTTP/1.1 200 OK
\r\n
Allow: GET, POST, HEAD, "
...
@@ -2592,6 +2614,7 @@ static void send_options(struct connection *conn) {
...
@@ -2592,6 +2614,7 @@ static void send_options(struct connection *conn) {
spool
(
&
conn
->
remote_iobuf
,
reply
,
sizeof
(
reply
)
-
1
);
spool
(
&
conn
->
remote_iobuf
,
reply
,
sizeof
(
reply
)
-
1
);
conn
->
flags
|=
CONN_SPOOL_DONE
;
conn
->
flags
|=
CONN_SPOOL_DONE
;
}
}
#endif // NO_DAV
#ifndef NO_AUTH
#ifndef NO_AUTH
static
void
send_authorization_request
(
struct
connection
*
conn
)
{
static
void
send_authorization_request
(
struct
connection
*
conn
)
{
...
@@ -2630,7 +2653,7 @@ static FILE *open_auth_file(struct connection *conn, const char *path) {
...
@@ -2630,7 +2653,7 @@ static FILE *open_auth_file(struct connection *conn, const char *path) {
return
fp
;
return
fp
;
}
}
#if
ndef HAVE_MD5
#if
!defined(HAVE_MD5) && !defined(NO_AUTH)
typedef
struct
MD5Context
{
typedef
struct
MD5Context
{
uint32_t
buf
[
4
];
uint32_t
buf
[
4
];
uint32_t
bits
[
2
];
uint32_t
bits
[
2
];
...
@@ -3234,13 +3257,15 @@ static void handle_lsp_request(struct connection *conn, const char *path,
...
@@ -3234,13 +3257,15 @@ static void handle_lsp_request(struct connection *conn, const char *path,
#endif // USE_LUA
#endif // USE_LUA
static
void
open_local_endpoint
(
struct
connection
*
conn
)
{
static
void
open_local_endpoint
(
struct
connection
*
conn
)
{
const
char
*
cl_hdr
=
mg_get_header
(
&
conn
->
mg_conn
,
"Content-Length"
);
#ifndef NO_FILESYSTEM
static
const
char
lua_pat
[]
=
LUA_SCRIPT_PATTERN
;
static
const
char
lua_pat
[]
=
LUA_SCRIPT_PATTERN
;
char
path
[
MAX_PATH_SIZE
];
file_stat_t
st
;
file_stat_t
st
;
char
path
[
MAX_PATH_SIZE
];
int
exists
=
0
,
is_directory
=
0
;
int
exists
=
0
,
is_directory
=
0
;
const
char
*
cl_hdr
=
mg_get_header
(
&
conn
->
mg_conn
,
"Content-Length"
);
const
char
*
cgi_pat
=
conn
->
server
->
config_options
[
CGI_PATTERN
];
const
char
*
cgi_pat
=
conn
->
server
->
config_options
[
CGI_PATTERN
];
const
char
*
dir_lst
=
conn
->
server
->
config_options
[
ENABLE_DIRECTORY_LISTING
];
const
char
*
dir_lst
=
conn
->
server
->
config_options
[
ENABLE_DIRECTORY_LISTING
];
#endif
conn
->
mg_conn
.
content_len
=
cl_hdr
==
NULL
?
0
:
(
int
)
to64
(
cl_hdr
);
conn
->
mg_conn
.
content_len
=
cl_hdr
==
NULL
?
0
:
(
int
)
to64
(
cl_hdr
);
...
@@ -3262,6 +3287,9 @@ static void open_local_endpoint(struct connection *conn) {
...
@@ -3262,6 +3287,9 @@ static void open_local_endpoint(struct connection *conn) {
return
;
return
;
}
}
#ifdef NO_FILESYSTEM
send_http_error
(
conn
,
404
,
NULL
);
#else
exists
=
convert_uri_to_file_name
(
conn
,
path
,
sizeof
(
path
),
&
st
);
exists
=
convert_uri_to_file_name
(
conn
,
path
,
sizeof
(
path
),
&
st
);
is_directory
=
S_ISDIR
(
st
.
st_mode
);
is_directory
=
S_ISDIR
(
st
.
st_mode
);
...
@@ -3329,6 +3357,7 @@ static void open_local_endpoint(struct connection *conn) {
...
@@ -3329,6 +3357,7 @@ static void open_local_endpoint(struct connection *conn) {
}
else
{
}
else
{
send_http_error
(
conn
,
404
,
NULL
);
send_http_error
(
conn
,
404
,
NULL
);
}
}
#endif // NO_FILESYSTEM
}
}
static
void
send_continue_if_expected
(
struct
connection
*
conn
)
{
static
void
send_continue_if_expected
(
struct
connection
*
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