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
37751a28
Commit
37751a28
authored
Nov 23, 2013
by
Sergey Lyubka
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
directory ops moved to directory.c
parent
45347bd4
Changes
7
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
520 additions
and
673 deletions
+520
-673
Makefile
build/Makefile
+1
-1
directory.c
build/src/directory.c
+238
-0
internal.h
build/src/internal.h
+1
-4
mongoose.c
build/src/mongoose.c
+2
-325
string.c
build/src/string.c
+19
-0
mongoose.c
mongoose.c
+259
-329
unit_test.c
test/unit_test.c
+0
-14
No files found.
build/Makefile
View file @
37751a28
...
...
@@ -29,7 +29,7 @@ VERSION = $(shell perl -lne \
SOURCES
=
src/internal.h src/util.c src/string.c src/parse_date.c
\
src/options.c src/crypto.c src/auth.c src/win32.c src/unix.c
\
src/mg_printf.c src/ssl.c src/http_client.c src/mime.c
\
src/mongoose.c src/lua.c
src/
directory.c src/
mongoose.c src/lua.c
TINY_SOURCES
=
../mongoose.c main.c
LUA_SOURCES
=
$(TINY_SOURCES)
sqlite3.c lsqlite3.c lua_5.2.1.c
...
...
build/src/directory.c
0 → 100644
View file @
37751a28
#include "internal.h"
static
void
print_dir_entry
(
const
struct
de
*
de
)
{
char
size
[
64
],
mod
[
64
],
href
[
PATH_MAX
*
3
];
const
char
*
slash
=
de
->
file
.
is_directory
?
"/"
:
""
;
if
(
de
->
file
.
is_directory
)
{
mg_snprintf
(
size
,
sizeof
(
size
),
"%s"
,
"[DIRECTORY]"
);
}
else
{
// We use (signed) cast below because MSVC 6 compiler cannot
// convert unsigned __int64 to double. Sigh.
if
(
de
->
file
.
size
<
1024
)
{
mg_snprintf
(
size
,
sizeof
(
size
),
"%d"
,
(
int
)
de
->
file
.
size
);
}
else
if
(
de
->
file
.
size
<
0x100000
)
{
mg_snprintf
(
size
,
sizeof
(
size
),
"%.1fk"
,
(
double
)
de
->
file
.
size
/
1024
.
0
);
}
else
if
(
de
->
file
.
size
<
0x40000000
)
{
mg_snprintf
(
size
,
sizeof
(
size
),
"%.1fM"
,
(
double
)
de
->
file
.
size
/
1048576
);
}
else
{
mg_snprintf
(
size
,
sizeof
(
size
),
"%.1fG"
,
(
double
)
de
->
file
.
size
/
1073741824
);
}
}
strftime
(
mod
,
sizeof
(
mod
),
"%d-%b-%Y %H:%M"
,
localtime
(
&
de
->
file
.
modification_time
));
mg_url_encode
(
de
->
file_name
,
href
,
sizeof
(
href
));
de
->
conn
->
num_bytes_sent
+=
mg_chunked_printf
(
de
->
conn
,
"<tr><td><a href=
\"
%s%s%s
\"
>%s%s</a></td>"
"<td> %s</td><td> %s</td></tr>
\n
"
,
de
->
conn
->
request_info
.
uri
,
href
,
slash
,
de
->
file_name
,
slash
,
mod
,
size
);
}
// This function is called from send_directory() and used for
// sorting directory entries by size, or name, or modification time.
// On windows, __cdecl specification is needed in case if project is built
// with __stdcall convention. qsort always requires __cdels callback.
static
int
WINCDECL
compare_dir_entries
(
const
void
*
p1
,
const
void
*
p2
)
{
const
struct
de
*
a
=
(
const
struct
de
*
)
p1
,
*
b
=
(
const
struct
de
*
)
p2
;
const
char
*
query_string
=
a
->
conn
->
request_info
.
query_string
;
int
cmp_result
=
0
;
if
(
query_string
==
NULL
)
{
query_string
=
"na"
;
}
if
(
a
->
file
.
is_directory
&&
!
b
->
file
.
is_directory
)
{
return
-
1
;
// Always put directories on top
}
else
if
(
!
a
->
file
.
is_directory
&&
b
->
file
.
is_directory
)
{
return
1
;
// Always put directories on top
}
else
if
(
*
query_string
==
'n'
)
{
cmp_result
=
strcmp
(
a
->
file_name
,
b
->
file_name
);
}
else
if
(
*
query_string
==
's'
)
{
cmp_result
=
a
->
file
.
size
==
b
->
file
.
size
?
0
:
a
->
file
.
size
>
b
->
file
.
size
?
1
:
-
1
;
}
else
if
(
*
query_string
==
'd'
)
{
cmp_result
=
a
->
file
.
modification_time
==
b
->
file
.
modification_time
?
0
:
a
->
file
.
modification_time
>
b
->
file
.
modification_time
?
1
:
-
1
;
}
return
query_string
[
1
]
==
'd'
?
-
cmp_result
:
cmp_result
;
}
static
int
must_hide_file
(
struct
mg_connection
*
conn
,
const
char
*
path
)
{
const
char
*
pw_pattern
=
"**"
PASSWORDS_FILE_NAME
"$"
;
const
char
*
pattern
=
conn
->
ctx
->
config
[
HIDE_FILES
];
return
match_prefix
(
pw_pattern
,
strlen
(
pw_pattern
),
path
)
>
0
||
(
pattern
!=
NULL
&&
match_prefix
(
pattern
,
strlen
(
pattern
),
path
)
>
0
);
}
static
int
scan_directory
(
struct
mg_connection
*
conn
,
const
char
*
dir
,
void
*
data
,
void
(
*
cb
)(
struct
de
*
,
void
*
))
{
char
path
[
PATH_MAX
];
struct
dirent
*
dp
;
DIR
*
dirp
;
struct
de
de
;
if
((
dirp
=
opendir
(
dir
))
==
NULL
)
{
return
0
;
}
else
{
de
.
conn
=
conn
;
while
((
dp
=
readdir
(
dirp
))
!=
NULL
)
{
// Do not show current dir and hidden files
if
(
!
strcmp
(
dp
->
d_name
,
"."
)
||
!
strcmp
(
dp
->
d_name
,
".."
)
||
must_hide_file
(
conn
,
dp
->
d_name
))
{
continue
;
}
mg_snprintf
(
path
,
sizeof
(
path
),
"%s%c%s"
,
dir
,
'/'
,
dp
->
d_name
);
// If we don't memset stat structure to zero, mtime will have
// garbage and strftime() will segfault later on in
// print_dir_entry(). memset is required only if mg_stat()
// fails. For more details, see
// http://code.google.com/p/mongoose/issues/detail?id=79
memset
(
&
de
.
file
,
0
,
sizeof
(
de
.
file
));
mg_stat
(
path
,
&
de
.
file
);
de
.
file_name
=
dp
->
d_name
;
cb
(
&
de
,
data
);
}
(
void
)
closedir
(
dirp
);
}
return
1
;
}
static
int
remove_directory
(
struct
mg_connection
*
conn
,
const
char
*
dir
)
{
char
path
[
PATH_MAX
];
struct
dirent
*
dp
;
DIR
*
dirp
;
struct
de
de
;
if
((
dirp
=
opendir
(
dir
))
==
NULL
)
{
return
0
;
}
else
{
de
.
conn
=
conn
;
while
((
dp
=
readdir
(
dirp
))
!=
NULL
)
{
// Do not show current dir, but show hidden files
if
(
!
strcmp
(
dp
->
d_name
,
"."
)
||
!
strcmp
(
dp
->
d_name
,
".."
))
{
continue
;
}
mg_snprintf
(
path
,
sizeof
(
path
),
"%s%c%s"
,
dir
,
'/'
,
dp
->
d_name
);
// If we don't memset stat structure to zero, mtime will have
// garbage and strftime() will segfault later on in
// print_dir_entry(). memset is required only if mg_stat()
// fails. For more details, see
// http://code.google.com/p/mongoose/issues/detail?id=79
memset
(
&
de
.
file
,
0
,
sizeof
(
de
.
file
));
mg_stat
(
path
,
&
de
.
file
);
if
(
de
.
file
.
modification_time
)
{
if
(
de
.
file
.
is_directory
)
{
remove_directory
(
conn
,
path
);
}
else
{
mg_remove
(
path
);
}
}
}
(
void
)
closedir
(
dirp
);
rmdir
(
dir
);
}
return
1
;
}
struct
dir_scan_data
{
struct
de
*
entries
;
int
num_entries
;
int
arr_size
;
};
// Behaves like realloc(), but frees original pointer on failure
static
void
*
realloc2
(
void
*
ptr
,
size_t
size
)
{
void
*
new_ptr
=
realloc
(
ptr
,
size
);
if
(
new_ptr
==
NULL
)
{
free
(
ptr
);
}
return
new_ptr
;
}
static
void
dir_scan_callback
(
struct
de
*
de
,
void
*
data
)
{
struct
dir_scan_data
*
dsd
=
(
struct
dir_scan_data
*
)
data
;
if
(
dsd
->
entries
==
NULL
||
dsd
->
num_entries
>=
dsd
->
arr_size
)
{
dsd
->
arr_size
*=
2
;
dsd
->
entries
=
(
struct
de
*
)
realloc2
(
dsd
->
entries
,
dsd
->
arr_size
*
sizeof
(
dsd
->
entries
[
0
]));
}
if
(
dsd
->
entries
==
NULL
)
{
// TODO(lsm): propagate an error to the caller
dsd
->
num_entries
=
0
;
}
else
{
dsd
->
entries
[
dsd
->
num_entries
].
file_name
=
mg_strdup
(
de
->
file_name
);
dsd
->
entries
[
dsd
->
num_entries
].
file
=
de
->
file
;
dsd
->
entries
[
dsd
->
num_entries
].
conn
=
de
->
conn
;
dsd
->
num_entries
++
;
}
}
static
void
handle_directory_request
(
struct
mg_connection
*
conn
,
const
char
*
dir
)
{
int
i
,
sort_direction
;
struct
dir_scan_data
data
=
{
NULL
,
0
,
128
};
if
(
!
scan_directory
(
conn
,
dir
,
&
data
,
dir_scan_callback
))
{
send_http_error
(
conn
,
500
,
"Cannot open directory"
,
"Error: opendir(%s): %s"
,
dir
,
strerror
(
ERRNO
));
return
;
}
sort_direction
=
conn
->
request_info
.
query_string
!=
NULL
&&
conn
->
request_info
.
query_string
[
1
]
==
'd'
?
'a'
:
'd'
;
conn
->
must_close
=
1
;
mg_printf
(
conn
,
"%s"
,
"HTTP/1.1 200 OK
\r\n
"
"Transfer-Encoding: Chunked
\r\n
"
"Content-Type: text/html; charset=utf-8
\r\n\r\n
"
);
conn
->
num_bytes_sent
+=
mg_chunked_printf
(
conn
,
"<html><head><title>Index of %s</title>"
"<style>th {text-align: left;}</style></head>"
"<body><h1>Index of %s</h1><pre><table cellpadding=
\"
0
\"
>"
"<tr><th><a href=
\"
?n%c
\"
>Name</a></th>"
"<th><a href=
\"
?d%c
\"
>Modified</a></th>"
"<th><a href=
\"
?s%c
\"
>Size</a></th></tr>"
"<tr><td colspan=
\"
3
\"
><hr></td></tr>"
,
conn
->
request_info
.
uri
,
conn
->
request_info
.
uri
,
sort_direction
,
sort_direction
,
sort_direction
);
// Print first entry - link to a parent directory
conn
->
num_bytes_sent
+=
mg_chunked_printf
(
conn
,
"<tr><td><a href=
\"
%s%s
\"
>%s</a></td>"
"<td> %s</td><td> %s</td></tr>
\n
"
,
conn
->
request_info
.
uri
,
".."
,
"Parent directory"
,
"-"
,
"-"
);
// Sort and print directory entries
qsort
(
data
.
entries
,
(
size_t
)
data
.
num_entries
,
sizeof
(
data
.
entries
[
0
]),
compare_dir_entries
);
for
(
i
=
0
;
i
<
data
.
num_entries
;
i
++
)
{
print_dir_entry
(
&
data
.
entries
[
i
]);
free
(
data
.
entries
[
i
].
file_name
);
}
free
(
data
.
entries
);
conn
->
num_bytes_sent
+=
mg_chunked_printf
(
conn
,
"%s"
,
"</table></body></html>"
);
conn
->
num_bytes_sent
+=
mg_write
(
conn
,
"0
\r\n\r\n
"
,
5
);
conn
->
status_code
=
200
;
}
build/src/internal.h
View file @
37751a28
...
...
@@ -399,7 +399,7 @@ struct socket {
// NOTE(lsm): this enum shoulds be in sync with the config_options.
enum
{
CGI_EXTENSIONS
,
CGI_ENVIRONMENT
,
PUT_DELETE_PASSWORDS_FILE
,
CGI_INTERPRETER
,
PROTECT_URI
,
AUTHENTICATION_DOMAIN
,
SSI_EXTENSIONS
,
THROTTLE
,
PROTECT_URI
,
AUTHENTICATION_DOMAIN
,
SSI_EXTENSIONS
,
ACCESS_LOG_FILE
,
ENABLE_DIRECTORY_LISTING
,
ERROR_LOG_FILE
,
GLOBAL_PASSWORDS_FILE
,
INDEX_FILES
,
ENABLE_KEEP_ALIVE
,
ACCESS_CONTROL_LIST
,
EXTRA_MIME_TYPES
,
LISTENING_PORTS
,
DOCUMENT_ROOT
,
SSL_CERTIFICATE
,
...
...
@@ -446,9 +446,6 @@ struct mg_connection {
int
request_len
;
// Size of the request + headers in a buffer
int
data_len
;
// Total size of data in a buffer
int
status_code
;
// HTTP reply status code, e.g. 200
int
throttle
;
// Throttling, bytes/sec. <= 0 means no throttle
time_t
last_throttle_time
;
// Last time throttled data was sent
int64_t
last_throttle_bytes
;
// Bytes sent this second
};
// Directory entry
...
...
build/src/mongoose.c
View file @
37751a28
This diff is collapsed.
Click to expand it.
build/src/string.c
View file @
37751a28
...
...
@@ -266,3 +266,22 @@ static void remove_double_dots_and_double_slashes(char *s) {
*
p
=
'\0'
;
}
void
mg_url_encode
(
const
char
*
src
,
char
*
dst
,
size_t
dst_len
)
{
static
const
char
*
dont_escape
=
"._-$,;~()"
;
static
const
char
*
hex
=
"0123456789abcdef"
;
const
char
*
end
=
dst
+
dst_len
-
1
;
for
(;
*
src
!=
'\0'
&&
dst
<
end
;
src
++
,
dst
++
)
{
if
(
isalnum
(
*
(
const
unsigned
char
*
)
src
)
||
strchr
(
dont_escape
,
*
(
const
unsigned
char
*
)
src
)
!=
NULL
)
{
*
dst
=
*
src
;
}
else
if
(
dst
+
2
<
end
)
{
dst
[
0
]
=
'%'
;
dst
[
1
]
=
hex
[(
*
(
const
unsigned
char
*
)
src
)
>>
4
];
dst
[
2
]
=
hex
[(
*
(
const
unsigned
char
*
)
src
)
&
0xf
];
dst
+=
2
;
}
}
*
dst
=
'\0'
;
}
mongoose.c
View file @
37751a28
This diff is collapsed.
Click to expand it.
test/unit_test.c
View file @
37751a28
...
...
@@ -416,19 +416,6 @@ static void test_mg_get_var(void) {
ASSERT
(
mg_get_var
(
post
[
1
],
strlen
(
post
[
1
]),
"st"
,
buf
,
17
)
==
16
);
}
static
void
test_set_throttle
(
void
)
{
ASSERT
(
set_throttle
(
NULL
,
0x0a000001
,
"/"
)
==
0
);
ASSERT
(
set_throttle
(
"10.0.0.0/8=20"
,
0x0a000001
,
"/"
)
==
20
);
ASSERT
(
set_throttle
(
"10.0.0.0/8=0.5k"
,
0x0a000001
,
"/"
)
==
512
);
ASSERT
(
set_throttle
(
"10.0.0.0/8=17m"
,
0x0a000001
,
"/"
)
==
1048576
*
17
);
ASSERT
(
set_throttle
(
"10.0.0.0/8=1x"
,
0x0a000001
,
"/"
)
==
0
);
ASSERT
(
set_throttle
(
"10.0.0.0/8=5,0.0.0.0/0=10"
,
0x0a000001
,
"/"
)
==
10
);
ASSERT
(
set_throttle
(
"10.0.0.0/8=5,/foo/**=7"
,
0x0a000001
,
"/index"
)
==
5
);
ASSERT
(
set_throttle
(
"10.0.0.0/8=5,/foo/**=7"
,
0x0a000001
,
"/foo/x"
)
==
7
);
ASSERT
(
set_throttle
(
"10.0.0.0/8=5,/foo/**=7"
,
0x0b000001
,
"/foxo/x"
)
==
0
);
ASSERT
(
set_throttle
(
"10.0.0.0/8=5,*=1"
,
0x0b000001
,
"/foxo/x"
)
==
1
);
}
static
void
test_next_option
(
void
)
{
const
char
*
p
,
*
list
=
"x/8,/y**=1;2k,z"
;
struct
vec
a
,
b
;
...
...
@@ -684,7 +671,6 @@ int __cdecl main(void) {
test_should_keep_alive
();
test_mg_download
();
test_mg_get_var
();
test_set_throttle
();
test_next_option
();
test_mg_stat
();
test_skip_quoted
();
...
...
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