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
6168573e
Commit
6168573e
authored
Jun 27, 2018
by
Philipp Schafft
🦁
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Feature: Render error messages via Report XML and XSLT
parent
7fadb6ce
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
94 additions
and
58 deletions
+94
-58
admin/error-html.xsl
admin/error-html.xsl
+17
-0
admin/error-plaintext.xsl
admin/error-plaintext.xsl
+10
-0
src/client.c
src/client.c
+45
-51
src/client.h
src/client.h
+2
-0
src/errors.c
src/errors.c
+4
-1
src/errors.h
src/errors.h
+2
-1
src/xslt.c
src/xslt.c
+14
-5
No files found.
admin/error-html.xsl
0 → 100644
View file @
6168573e
<xsl:stylesheet
xmlns:xsl =
"http://www.w3.org/1999/XSL/Transform"
version =
"1.0"
xmlns=
"http://www.w3.org/1999/xhtml"
>
<xsl:output
omit-xml-declaration=
"no"
method=
"xml"
doctype-public=
"-//W3C//DTD XHTML 1.0 Strict//EN"
doctype-system=
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
indent=
"yes"
encoding=
"UTF-8"
/>
<xsl:include
href=
"includes/web-page.xsl"
/>
<xsl:variable
name=
"title"
>
Error
</xsl:variable>
<xsl:template
name=
"content"
>
<div
class=
"roundbox"
>
<xsl:for-each
select=
"/report/incident"
>
<div
class=
"article"
>
<h3>
Response
</h3>
<h4>
Message
</h4>
<p><xsl:value-of
select=
"state/text"
/></p>
</div>
</xsl:for-each>
</div>
</xsl:template>
</xsl:stylesheet>
admin/error-plaintext.xsl
0 → 100644
View file @
6168573e
<xsl:stylesheet
xmlns:xsl =
"http://www.w3.org/1999/XSL/Transform"
version =
"1.0"
>
<xsl:output
omit-xml-declaration=
"yes"
media-type=
"text/plain"
method=
"text"
indent=
"no"
encoding=
"UTF-8"
/>
<xsl:template
name=
"content"
match=
"/report"
>
<xsl:for-each
select=
"/report/incident"
>
<xsl:text>
Report:


</xsl:text>
<xsl:value-of
select=
"state/text"
/>
<xsl:text>


</xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
src/client.c
View file @
6168573e
...
...
@@ -239,79 +239,73 @@ int client_read_bytes(client_t *client, void *buf, unsigned len)
return
bytes
;
}
static
inline
void
_client_send_error
(
client_t
*
client
,
int
plain
,
const
icecast_error_t
*
error
)
static
inline
void
_client_send_error
(
client_t
*
client
,
const
icecast_error_t
*
error
)
{
ssize_t
ret
;
refbuf_t
*
data
;
ice_config_t
*
config
;
reportxml_t
*
report
;
admin_format_t
admin_format
;
const
char
*
xslt
=
NULL
;
if
(
error
->
http_status
==
500
)
{
client_send_500
(
client
,
error
->
message
);
return
;
}
admin_format
=
client_get_admin_format_by_content_negotiation
(
client
);
data
=
refbuf_new
(
PER_CLIENT_REFBUF_SIZE
);
if
(
!
data
)
{
client_send_500
(
client
,
error
->
message
);
return
;
switch
(
admin_format
)
{
case
ADMIN_FORMAT_RAW
:
xslt
=
NULL
;
break
;
case
ADMIN_FORMAT_TRANSFORMED
:
xslt
=
CLIENT_DEFAULT_ERROR_XSL_TRANSFORMED
;
break
;
case
ADMIN_FORMAT_PLAINTEXT
:
xslt
=
CLIENT_DEFAULT_ERROR_XSL_PLAINTEXT
;
break
;
default:
client_send_500
(
client
,
"Invalid Admin Type"
);
break
;
}
client
->
reuse
=
ICECAST_REUSE_KEEPALIVE
;
ret
=
util_http_build_header
(
client
->
refbuf
->
data
,
PER_CLIENT_REFBUF_SIZE
,
0
,
0
,
error
->
http_status
,
NULL
,
plain
?
"text/plain"
:
"text/html"
,
"utf-8"
,
NULL
,
NULL
,
client
);
if
(
ret
==
-
1
||
ret
>=
PER_CLIENT_REFBUF_SIZE
)
{
ICECAST_LOG_ERROR
(
"Dropping client as we can not build response headers."
);
client_send_500
(
client
,
"Header generation failed."
);
return
;
}
config
=
config_get_config
();
report
=
reportxml_database_build_report
(
config
->
reportxml_db
,
error
->
uuid
,
-
1
);
config_release_config
();
if
(
plain
)
{
snprintf
(
data
->
data
,
data
->
len
,
"Error %i
\r\n
---------
\r\n\r\n
Message: %s
\r\n\r\n
Error code: %s
\r\n
"
,
error
->
http_status
,
error
->
message
,
error
->
uuid
);
}
else
{
snprintf
(
data
->
data
,
data
->
len
,
"<html><head><title>Error %i</title></head><body><h1>Error %i</h1><hr><p><b>%s</b></p><p>Error code: %s</p></body></html>
\r\n
"
,
error
->
http_status
,
error
->
http_status
,
error
->
message
,
error
->
uuid
);
if
(
!
report
)
{
reportxml_node_t
*
root
,
*
incident
,
*
state
,
*
text
;
report
=
reportxml_new
();
root
=
reportxml_get_root_node
(
report
);
incident
=
reportxml_node_new
(
REPORTXML_NODE_TYPE_INCIDENT
,
NULL
,
NULL
,
NULL
);
state
=
reportxml_node_new
(
REPORTXML_NODE_TYPE_STATE
,
NULL
,
error
->
uuid
,
NULL
);
text
=
reportxml_node_new
(
REPORTXML_NODE_TYPE_TEXT
,
NULL
,
NULL
,
NULL
);
reportxml_node_set_content
(
text
,
error
->
message
);
reportxml_node_add_child
(
state
,
text
);
reportxml_node_add_child
(
incident
,
state
);
reportxml_node_add_child
(
root
,
incident
);
refobject_unref
(
text
);
refobject_unref
(
state
);
refobject_unref
(
incident
);
refobject_unref
(
root
);
}
data
->
len
=
strlen
(
data
->
data
);
snprintf
(
client
->
refbuf
->
data
+
ret
,
PER_CLIENT_REFBUF_SIZE
-
ret
,
"Content-Length: %llu
\r\n\r\n
"
,
(
long
long
unsigned
int
)
data
->
len
);
client
->
respcode
=
error
->
http_status
;
client
->
refbuf
->
len
=
strlen
(
client
->
refbuf
->
data
);
client
->
refbuf
->
next
=
data
;
client_send_reportxml
(
client
,
report
,
DOCUMENT_DOMAIN_ADMIN
,
xslt
,
admin_format
,
error
->
http_status
);
fserve_add_client
(
client
,
NULL
);
refobject_unref
(
report
);
}
void
client_send_error_by_id
(
client_t
*
client
,
icecast_error_id_t
id
)
{
const
icecast_error_t
*
error
=
error_get_by_id
(
id
);
const
char
*
pref
;
int
plain
;
if
(
!
error
)
{
client_send_500
(
client
,
"Unknown error ID"
);
return
;
}
pref
=
util_http_select_best
(
httpp_getvar
(
client
->
parser
,
"accept"
),
"text/plain"
,
"text/html"
,
(
const
char
*
)
NULL
);
if
(
strcmp
(
pref
,
"text/plain"
)
==
0
)
{
plain
=
1
;
}
else
if
(
strcmp
(
pref
,
"text/html"
)
==
0
)
{
plain
=
0
;
}
else
{
plain
=
1
;
if
(
error
->
http_status
==
500
)
{
client_send_500
(
client
,
error
->
message
);
return
;
}
_client_send_error
(
client
,
plain
,
error
);
_client_send_error
(
client
,
error
);
}
void
client_send_101
(
client_t
*
client
,
reuse_t
reuse
)
...
...
src/client.h
View file @
6168573e
...
...
@@ -29,6 +29,8 @@
#define CLIENT_DEFAULT_REPORT_XSL_TRANSFORMED "report-html.xsl"
#define CLIENT_DEFAULT_REPORT_XSL_PLAINTEXT "report-plaintext.xsl"
#define CLIENT_DEFAULT_ERROR_XSL_TRANSFORMED "error-html.xsl"
#define CLIENT_DEFAULT_ERROR_XSL_PLAINTEXT "error-plaintext.xsl"
#define CLIENT_DEFAULT_ADMIN_FORMAT ADMIN_FORMAT_TRANSFORMED
typedef
enum
_document_domain_tag
{
...
...
src/errors.c
View file @
6168573e
...
...
@@ -132,7 +132,10 @@ static const icecast_error_t __errors[] = {
.
message
=
"Could not parse XSLT file"
},
{.
id
=
ICECAST_ERROR_XSLT_problem
,
.
http_status
=
500
,
.
uuid
=
"d3c6e4b3-7d6e-4191-a81b-970273067ae3"
,
.
message
=
"XSLT problem"
}
.
message
=
"XSLT problem"
},
{.
id
=
ICECAST_ERROR_RECURSIVE_ERROR
,
.
http_status
=
500
,
.
uuid
=
"13489d5c-eae6-4bf3-889e-ec1fa9a9b9ac"
,
.
message
=
"Recursive error"
}
};
const
icecast_error_t
*
error_get_by_id
(
icecast_error_id_t
id
)
{
...
...
src/errors.h
View file @
6168573e
...
...
@@ -48,7 +48,8 @@ typedef enum {
ICECAST_ERROR_SOURCE_MOUNT_UNAVAILABLE
,
ICECAST_ERROR_SOURCE_STREAM_PREPARATION_ERROR
,
ICECAST_ERROR_XSLT_PARSE
,
ICECAST_ERROR_XSLT_problem
ICECAST_ERROR_XSLT_problem
,
ICECAST_ERROR_RECURSIVE_ERROR
}
icecast_error_id_t
;
struct
icecast_error_tag
{
...
...
src/xslt.c
View file @
6168573e
...
...
@@ -285,6 +285,15 @@ static xmlDocPtr custom_loader(const xmlChar *URI,
return
ret
;
}
static
inline
void
_send_error
(
client_t
*
client
,
icecast_error_id_t
id
,
int
old_status
)
{
if
(
old_status
>=
400
)
{
client_send_error_by_id
(
client
,
ICECAST_ERROR_RECURSIVE_ERROR
);
return
;
}
client_send_error_by_id
(
client
,
id
);
}
void
xslt_transform
(
xmlDocPtr
doc
,
const
char
*
xslfilename
,
client_t
*
client
,
int
status
)
{
xmlDocPtr
res
;
...
...
@@ -305,7 +314,7 @@ void xslt_transform(xmlDocPtr doc, const char *xslfilename, client_t *client, in
{
thread_mutex_unlock
(
&
xsltlock
);
ICECAST_LOG_ERROR
(
"problem reading stylesheet
\"
%s
\"
"
,
xslfilename
);
client
_send_error
_by_id
(
client
,
ICECAST_ERROR_XSLT_PARSE
);
_send_error
(
client
,
ICECAST_ERROR_XSLT_PARSE
,
status
);
return
;
}
...
...
@@ -349,7 +358,7 @@ void xslt_transform(xmlDocPtr doc, const char *xslfilename, client_t *client, in
ret
=
util_http_build_header
(
refbuf
->
data
,
full_len
,
0
,
0
,
status
,
NULL
,
mediatype
,
charset
,
NULL
,
NULL
,
client
);
if
(
ret
==
-
1
)
{
ICECAST_LOG_ERROR
(
"Dropping client as we can not build response headers."
);
client
_send_error
_by_id
(
client
,
ICECAST_ERROR_GEN_HEADER_GEN_FAILED
);
_send_error
(
client
,
ICECAST_ERROR_GEN_HEADER_GEN_FAILED
,
status
);
}
else
{
if
(
full_len
<
(
ret
+
(
ssize_t
)
len
+
(
ssize_t
)
64
)
)
{
void
*
new_data
;
...
...
@@ -362,12 +371,12 @@ void xslt_transform(xmlDocPtr doc, const char *xslfilename, client_t *client, in
ret
=
util_http_build_header
(
refbuf
->
data
,
full_len
,
0
,
0
,
status
,
NULL
,
mediatype
,
charset
,
NULL
,
NULL
,
client
);
if
(
ret
==
-
1
)
{
ICECAST_LOG_ERROR
(
"Dropping client as we can not build response headers."
);
client
_send_error
_by_id
(
client
,
ICECAST_ERROR_GEN_HEADER_GEN_FAILED
);
_send_error
(
client
,
ICECAST_ERROR_GEN_HEADER_GEN_FAILED
,
status
);
failed
=
1
;
}
}
else
{
ICECAST_LOG_ERROR
(
"Client buffer reallocation failed. Dropping client."
);
client
_send_error
_by_id
(
client
,
ICECAST_ERROR_GEN_BUFFER_REALLOC
);
_send_error
(
client
,
ICECAST_ERROR_GEN_BUFFER_REALLOC
,
status
);
failed
=
1
;
}
}
...
...
@@ -387,7 +396,7 @@ void xslt_transform(xmlDocPtr doc, const char *xslfilename, client_t *client, in
else
{
ICECAST_LOG_WARN
(
"problem applying stylesheet
\"
%s
\"
"
,
xslfilename
);
client
_send_error
_by_id
(
client
,
ICECAST_ERROR_XSLT_problem
);
_send_error
(
client
,
ICECAST_ERROR_XSLT_problem
,
status
);
}
thread_mutex_unlock
(
&
xsltlock
);
xmlFreeDoc
(
res
);
...
...
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