#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#define NEED_newSVpvn_flags
#define NEED_sv_2pv_flags
#include "ppport.h"
static
const
char
unsafe[256] = {
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
0,0,1,0, 0,0,1,1, 0,0,0,0, 0,0,0,0,
0,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,1,0,
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
0,0,0,0, 0,0,0,0, 0,0,0,1, 0,1,0,0,
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
};
static
size_t
safe_character_span(
const
char
*start,
const
char
*end) {
const
char
*cur = start;
while
(cur != end) {
unsigned
char
c = (unsigned
char
) *cur;
if
(unsafe[c]) {
break
;
}
cur++;
}
return
cur - start;
}
static
void
tx_sv_cat_with_escape_html_force(pTHX_ SV*
const
dest, SV*
const
src) {
STRLEN len;
const
char
* cur = SvPV_const(src, len);
const
char
*
const
end = cur + len;
STRLEN
const
dest_cur = SvCUR(dest);
char
* d;
(
void
)SvGROW(dest, dest_cur + ( len * (
sizeof
(
"""
) - 1) ) + 1);
if
(!SvUTF8(dest) && SvUTF8(src)) {
sv_utf8_upgrade(dest);
}
d = SvPVX(dest) + dest_cur;
#define CopyToken(token, to) STMT_START { \
Copy(token
""
, to,
sizeof
(token)-1,
char
); \
to +=
sizeof
(token)-1; \
} STMT_END
while
(cur != end) {
size_t
span = safe_character_span(cur, end);
Copy(cur, d, span,
char
);
cur += span;
d += span;
if
(cur != end) {
const
char
c = *(cur++);
if
(c ==
'&'
) {
CopyToken(
"&"
, d);
}
else
if
(c ==
'<'
) {
CopyToken(
"<"
, d);
}
else
if
(c ==
'>'
) {
CopyToken(
">"
, d);
}
else
if
(c ==
'"'
) {
CopyToken(
"""
, d);
}
else
if
(c ==
'`'
) {
CopyToken(
"`"
, d);
}
else
if
(c ==
'{'
) {
CopyToken(
"{"
, d);
}
else
if
(c ==
'}'
) {
CopyToken(
"}"
, d);
}
else
{
CopyToken(
"'"
, d);
}
}
}
#undef CopyToken
SvCUR_set(dest, d - SvPVX(dest));
*SvEND(dest) =
'\0'
;
}
static
SV*
tx_escape_html(pTHX_ SV*
const
str) {
SvGETMAGIC(str);
if
(!( !SvOK(str) )) {
SV*
const
dest = newSVpvs_flags(
""
, SVs_TEMP);
tx_sv_cat_with_escape_html_force(aTHX_ dest, str);
return
dest;
}
else
{
return
str;
}
}
MODULE = HTML::Escape PACKAGE = HTML::Escape
PROTOTYPES: DISABLE
void
escape_html(SV* str)
CODE:
{
ST(0) = tx_escape_html(aTHX_ str);
}