Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
Xiph.Org
Icecast-Server
Commits
ab8c8c68
Commit
ab8c8c68
authored
Dec 31, 2002
by
Michael Smith
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
mp3 metadata complete. Still untested.
svn path=/trunk/httpp/; revision=4191
parent
5275ab34
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
264 additions
and
28 deletions
+264
-28
src/client.c
src/client.c
+10
-0
src/client.h
src/client.h
+1
-0
src/connection.c
src/connection.c
+67
-1
src/httpp/httpp.c
src/httpp/httpp.c
+142
-2
src/httpp/httpp.h
src/httpp/httpp.h
+3
-0
src/util.c
src/util.c
+39
-25
src/util.h
src/util.h
+2
-0
No files found.
src/client.c
View file @
ab8c8c68
...
...
@@ -45,6 +45,16 @@ void client_destroy(client_t *client)
free
(
client
);
}
void
client_send_400
(
client_t
*
client
,
char
*
message
)
{
int
bytes
;
bytes
=
sock_write
(
client
->
con
->
sock
,
"HTTP/1.0 404 File Not Found
\r\n
"
"Content-Type: text/html
\r\n\r\n
"
"<b>%s</b>
\r\n
"
,
message
);
if
(
bytes
>
0
)
client
->
con
->
sent_bytes
=
bytes
;
client
->
respcode
=
404
;
client_destroy
(
client
);
}
void
client_send_404
(
client_t
*
client
,
char
*
message
)
{
int
bytes
;
...
...
src/client.h
View file @
ab8c8c68
...
...
@@ -31,5 +31,6 @@ client_t *client_create(connection_t *con, http_parser_t *parser);
void
client_destroy
(
client_t
*
client
);
void
client_send_404
(
client_t
*
client
,
char
*
message
);
void
client_send_401
(
client_t
*
client
);
void
client_send_400
(
client_t
*
client
,
char
*
message
);
#endif
/* __CLIENT_H__ */
src/connection.c
View file @
ab8c8c68
...
...
@@ -36,6 +36,7 @@
#include "fserve.h"
#include "source.h"
#include "format.h"
#include "format_mp3.h"
#define CATMODULE "connection"
...
...
@@ -418,6 +419,65 @@ static int _check_source_pass(http_parser_t *parser)
return
ret
;
}
static
void
handle_metadata_request
(
client_t
*
client
)
{
source_t
*
source
;
char
*
action
;
char
*
mount
;
char
*
value
;
mp3_state
*
state
;
int
bytes
;
if
(
!
_check_source_pass
(
client
->
parser
))
{
INFO0
(
"Metadata request with wrong or missing password"
);
client_send_401
(
client
);
return
;
}
action
=
httpp_get_query_param
(
client
->
parser
,
"mode"
);
mount
=
httpp_get_query_param
(
client
->
parser
,
"mount"
);
value
=
httpp_get_query_param
(
client
->
parser
,
"song"
);
if
(
value
==
NULL
||
action
==
NULL
||
mount
==
NULL
)
{
client_send_400
(
client
,
"Missing parameter"
);
return
;
}
avl_tree_rlock
(
global
.
source_tree
);
source
=
source_find_mount
(
mount
);
avl_tree_unlock
(
global
.
source_tree
);
if
(
source
==
NULL
)
{
client_send_400
(
client
,
"No such mountpoint"
);
return
;
}
if
(
source
->
format
->
type
!=
FORMAT_TYPE_MP3
)
{
client_send_400
(
client
,
"Not mp3, cannot update metadata"
);
return
;
}
if
(
strcmp
(
action
,
"updinfo"
)
!=
0
)
{
client_send_400
(
client
,
"No such action"
);
return
;
}
state
=
source
->
format
->
_state
;
thread_mutex_lock
(
&
(
state
->
lock
));
free
(
state
->
metadata
);
state
->
metadata
=
strdup
(
value
);
state
->
metadata_age
++
;
thread_mutex_unlock
(
&
(
state
->
lock
));
DEBUG2
(
"Metadata on mountpoint %s changed to
\"
%s
\"
"
,
mount
,
value
);
client
->
respcode
=
200
;
bytes
=
sock_write
(
client
->
con
->
sock
,
"HTTP/1.0 200 OK
\r\n
Content-Type: text/html
\r\n\r\n
"
"Update successful"
);
if
(
bytes
>
0
)
client
->
con
->
sent_bytes
=
bytes
;
client_destroy
(
client
);
}
static
void
_handle_source_request
(
connection_t
*
con
,
http_parser_t
*
parser
,
char
*
uri
)
{
...
...
@@ -500,7 +560,7 @@ static void _handle_get_request(connection_t *con,
** aren't subject to the limits.
*/
/* TODO: add GUID-xxxxxx */
if
(
strcmp
(
uri
,
"/stats.xml"
)
==
0
)
{
if
(
strcmp
(
uri
,
"/
admin/
stats.xml"
)
==
0
)
{
if
(
!
_check_source_pass
(
parser
))
{
INFO0
(
"Request for stats.xml with incorrect or no password"
);
client_send_401
(
client
);
...
...
@@ -512,6 +572,12 @@ static void _handle_get_request(connection_t *con,
return
;
}
if
(
strcmp
(
uri
,
"/admin/metadata"
)
==
0
)
{
DEBUG0
(
"Got metadata update request"
);
handle_metadata_request
(
client
);
return
;
}
/* Here we are parsing the URI request to see
** if the extension is .xsl, if so, then process
** this request as an XSLT request
...
...
src/httpp/httpp.c
View file @
ab8c8c68
...
...
@@ -40,6 +40,7 @@ void httpp_initialize(http_parser_t *parser, http_varlist_t *defaults)
parser
->
req_type
=
httpp_req_none
;
parser
->
uri
=
NULL
;
parser
->
vars
=
avl_tree_new
(
_compare_vars
,
NULL
);
parser
->
queryvars
=
avl_tree_new
(
_compare_vars
,
NULL
);
/* now insert the default variables */
list
=
defaults
;
...
...
@@ -178,6 +179,100 @@ int httpp_parse_response(http_parser_t *parser, char *http_data, unsigned long l
return
1
;
}
static
int
hex
(
char
c
)
{
if
(
c
>=
'0'
&&
c
<=
'9'
)
return
c
-
'0'
;
else
if
(
c
>=
'A'
&&
c
<=
'F'
)
return
c
-
'A'
+
10
;
else
if
(
c
>=
'a'
&&
c
<=
'f'
)
return
c
-
'a'
+
10
;
else
return
-
1
;
}
static
char
*
url_escape
(
char
*
src
)
{
int
len
=
strlen
(
src
);
unsigned
char
*
decoded
;
int
i
;
char
*
dst
;
int
done
=
0
;
decoded
=
calloc
(
1
,
len
+
1
);
dst
=
decoded
;
for
(
i
=
0
;
i
<
len
;
i
++
)
{
switch
(
src
[
i
])
{
case
'%'
:
if
(
i
+
2
>=
len
)
{
free
(
decoded
);
return
NULL
;
}
if
(
hex
(
src
[
i
+
1
])
==
-
1
||
hex
(
src
[
i
+
2
])
==
-
1
)
{
free
(
decoded
);
return
NULL
;
}
*
dst
++
=
hex
(
src
[
i
+
1
])
*
16
+
hex
(
src
[
i
+
2
]);
i
+=
2
;
break
;
case
'#'
:
done
=
1
;
break
;
case
0
:
free
(
decoded
);
return
NULL
;
break
;
default:
*
dst
++
=
src
[
i
];
break
;
}
if
(
done
)
break
;
}
*
dst
=
0
;
/* null terminator */
return
decoded
;
}
/** TODO: This is almost certainly buggy in some cases */
static
void
parse_query
(
http_parser_t
*
parser
,
char
*
query
)
{
int
len
;
int
i
=
0
;
char
*
key
=
query
;
char
*
val
=
NULL
;
if
(
!
query
||
!*
query
)
return
;
len
=
strlen
(
query
);
while
(
i
<
len
)
{
switch
(
query
[
i
])
{
case
'&'
:
query
[
i
]
=
0
;
if
(
val
&&
key
)
{
httpp_set_query_param
(
parser
,
key
,
val
);
}
key
=
query
+
i
+
1
;
break
;
case
'='
:
query
[
i
]
=
0
;
val
=
query
+
i
+
1
;
break
;
}
i
++
;
}
if
(
val
&&
key
)
{
httpp_set_query_param
(
parser
,
key
,
val
);
}
}
int
httpp_parse
(
http_parser_t
*
parser
,
char
*
http_data
,
unsigned
long
len
)
{
char
*
data
,
*
tmp
;
...
...
@@ -247,8 +342,17 @@ int httpp_parse(http_parser_t *parser, char *http_data, unsigned long len)
parser
->
req_type
=
httpp_req_unknown
;
}
if
(
uri
!=
NULL
&&
strlen
(
uri
)
>
0
)
if
(
uri
!=
NULL
&&
strlen
(
uri
)
>
0
)
{
char
*
query
;
if
((
query
=
strchr
(
uri
,
'?'
))
!=
NULL
)
{
*
query
=
0
;
query
++
;
parse_query
(
parser
,
query
);
}
parser
->
uri
=
strdup
(
uri
);
}
else
parser
->
uri
=
NULL
;
...
...
@@ -335,7 +439,7 @@ char *httpp_getvar(http_parser_t *parser, char *name)
http_var_t
*
found
;
var
.
name
=
name
;
var
.
value
=
NULL
;
var
.
value
=
NULL
;
if
(
avl_get_by_key
(
parser
->
vars
,
(
void
*
)
&
var
,
(
void
**
)
&
found
)
==
0
)
return
found
->
value
;
...
...
@@ -343,6 +447,41 @@ char *httpp_getvar(http_parser_t *parser, char *name)
return
NULL
;
}
void
httpp_set_query_param
(
http_parser_t
*
parser
,
char
*
name
,
char
*
value
)
{
http_var_t
*
var
;
if
(
name
==
NULL
||
value
==
NULL
)
return
;
var
=
(
http_var_t
*
)
malloc
(
sizeof
(
http_var_t
));
if
(
var
==
NULL
)
return
;
var
->
name
=
strdup
(
name
);
var
->
value
=
url_escape
(
value
);
if
(
httpp_get_query_param
(
parser
,
name
)
==
NULL
)
{
avl_insert
(
parser
->
queryvars
,
(
void
*
)
var
);
}
else
{
avl_delete
(
parser
->
queryvars
,
(
void
*
)
var
,
_free_vars
);
avl_insert
(
parser
->
queryvars
,
(
void
*
)
var
);
}
}
char
*
httpp_get_query_param
(
http_parser_t
*
parser
,
char
*
name
)
{
http_var_t
var
;
http_var_t
*
found
;
var
.
name
=
name
;
var
.
value
=
NULL
;
if
(
avl_get_by_key
(
parser
->
queryvars
,
(
void
*
)
&
var
,
(
void
**
)
&
found
)
==
0
)
return
found
->
value
;
else
return
NULL
;
}
void
httpp_clear
(
http_parser_t
*
parser
)
{
parser
->
req_type
=
httpp_req_none
;
...
...
@@ -350,6 +489,7 @@ void httpp_clear(http_parser_t *parser)
free
(
parser
->
uri
);
parser
->
uri
=
NULL
;
avl_tree_free
(
parser
->
vars
,
_free_vars
);
avl_tree_free
(
parser
->
queryvars
,
_free_vars
);
parser
->
vars
=
NULL
;
}
...
...
src/httpp/httpp.h
View file @
ab8c8c68
...
...
@@ -33,6 +33,7 @@ typedef struct http_parser_tag {
httpp_request_type_e
req_type
;
char
*
uri
;
avl_tree
*
vars
;
avl_tree
*
queryvars
;
}
http_parser_t
;
http_parser_t
*
httpp_create_parser
(
void
);
...
...
@@ -41,6 +42,8 @@ int httpp_parse(http_parser_t *parser, char *http_data, unsigned long len);
int
httpp_parse_response
(
http_parser_t
*
parser
,
char
*
http_data
,
unsigned
long
len
,
char
*
uri
);
void
httpp_setvar
(
http_parser_t
*
parser
,
char
*
name
,
char
*
value
);
char
*
httpp_getvar
(
http_parser_t
*
parser
,
char
*
name
);
void
httpp_set_query_param
(
http_parser_t
*
parser
,
char
*
name
,
char
*
value
);
char
*
httpp_get_query_param
(
http_parser_t
*
parser
,
char
*
name
);
void
httpp_destroy
(
http_parser_t
*
parser
);
void
httpp_clear
(
http_parser_t
*
parser
);
...
...
src/util.c
View file @
ab8c8c68
...
...
@@ -208,50 +208,43 @@ char *util_get_path_from_normalised_uri(char *uri) {
return
fullpath
;
}
/* Get an absolute path (from the webroot dir) from a URI. Return NULL if the
* path contains 'disallowed' sequences like foo/../ (which could be used to
* escape from the webroot) or if it cannot be URI-decoded.
* Caller should free the path.
*/
char
*
util_normalise_uri
(
char
*
uri
)
{
int
urilen
=
strlen
(
uri
);
unsigned
char
*
path
;
char
*
dst
;
char
*
util_url_escape
(
char
*
src
)
{
int
len
=
strlen
(
src
);
unsigned
char
*
decoded
;
int
i
;
char
*
dst
;
int
done
=
0
;
if
(
uri
[
0
]
!=
'/'
)
return
NULL
;
decoded
=
calloc
(
1
,
len
+
1
);
path
=
calloc
(
1
,
urilen
+
1
)
;
dst
=
decoded
;
dst
=
path
;
for
(
i
=
0
;
i
<
urilen
;
i
++
)
{
switch
(
uri
[
i
])
{
for
(
i
=
0
;
i
<
len
;
i
++
)
{
switch
(
src
[
i
])
{
case
'%'
:
if
(
i
+
2
>=
uri
len
)
{
free
(
path
);
if
(
i
+
2
>=
len
)
{
free
(
decoded
);
return
NULL
;
}
if
(
hex
(
uri
[
i
+
1
])
==
-
1
||
hex
(
uri
[
i
+
2
])
==
-
1
)
{
free
(
path
);
if
(
hex
(
src
[
i
+
1
])
==
-
1
||
hex
(
src
[
i
+
2
])
==
-
1
)
{
free
(
decoded
);
return
NULL
;
}
*
dst
++
=
hex
(
uri
[
i
+
1
])
*
16
+
hex
(
uri
[
i
+
2
]);
*
dst
++
=
hex
(
src
[
i
+
1
])
*
16
+
hex
(
src
[
i
+
2
]);
i
+=
2
;
break
;
case
'#'
:
done
=
1
;
break
;
case
0
:
ERROR0
(
"Fatal internal logic error in util_
get_path_from_uri
()"
);
free
(
path
);
ERROR0
(
"Fatal internal logic error in util_
url_escape
()"
);
free
(
decoded
);
return
NULL
;
break
;
default:
*
dst
++
=
uri
[
i
];
*
dst
++
=
src
[
i
];
break
;
}
if
(
done
)
...
...
@@ -260,9 +253,30 @@ char *util_normalise_uri(char *uri) {
*
dst
=
0
;
/* null terminator */
return
decoded
;
}
/* Get an absolute path (from the webroot dir) from a URI. Return NULL if the
* path contains 'disallowed' sequences like foo/../ (which could be used to
* escape from the webroot) or if it cannot be URI-decoded.
* Caller should free the path.
*/
char
*
util_normalise_uri
(
char
*
uri
)
{
char
*
path
;
if
(
uri
[
0
]
!=
'/'
)
return
NULL
;
path
=
util_url_escape
(
uri
);
if
(
path
==
NULL
)
{
WARN1
(
"Error decoding URI: %s
\n
"
,
uri
);
return
NULL
;
}
/* We now have a full URI-decoded path. Check it for allowability */
if
(
verify_path
(
path
))
return
(
char
*
)
path
;
return
path
;
else
{
WARN1
(
"Rejecting invalid path
\"
%s
\"
"
,
path
);
free
(
path
);
...
...
src/util.h
View file @
ab8c8c68
...
...
@@ -14,4 +14,6 @@ char *util_normalise_uri(char *uri);
char
*
util_base64_encode
(
char
*
data
);
char
*
util_base64_decode
(
unsigned
char
*
input
);
char
*
util_url_escape
(
char
*
src
);
#endif
/* __UTIL_H__ */
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