redcarpet 2.0.0 → 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of redcarpet might be problematic. Click here for more details.
- data/ext/redcarpet/buffer.c +14 -20
- data/ext/redcarpet/html.c +32 -15
- data/ext/redcarpet/html.h +1 -0
- data/ext/redcarpet/markdown.c +6 -7
- data/ext/redcarpet/rc_markdown.c +13 -0
- data/ext/redcarpet/rc_render.c +4 -0
- data/lib/redcarpet.rb +1 -1
- data/lib/redcarpet/compat.rb +3 -0
- data/redcarpet.gemspec +2 -1
- data/test/redcarpet_test.rb +23 -0
- metadata +4 -3
data/ext/redcarpet/buffer.c
CHANGED
@@ -22,6 +22,7 @@
|
|
22
22
|
#include <stdio.h>
|
23
23
|
#include <stdlib.h>
|
24
24
|
#include <string.h>
|
25
|
+
#include <assert.h>
|
25
26
|
|
26
27
|
/* MSVC compat */
|
27
28
|
#if defined(_MSC_VER)
|
@@ -34,6 +35,7 @@ int
|
|
34
35
|
bufprefix(const struct buf *buf, const char *prefix)
|
35
36
|
{
|
36
37
|
size_t i;
|
38
|
+
assert(buf && buf->unit);
|
37
39
|
|
38
40
|
for (i = 0; i < buf->size; ++i) {
|
39
41
|
if (prefix[i] == 0)
|
@@ -52,7 +54,10 @@ bufgrow(struct buf *buf, size_t neosz)
|
|
52
54
|
{
|
53
55
|
size_t neoasz;
|
54
56
|
void *neodata;
|
55
|
-
|
57
|
+
|
58
|
+
assert(buf && buf->unit);
|
59
|
+
|
60
|
+
if (neosz > BUFFER_MAX_ALLOC_SIZE)
|
56
61
|
return BUF_ENOMEM;
|
57
62
|
|
58
63
|
if (buf->asize >= neosz)
|
@@ -91,8 +96,7 @@ bufnew(size_t unit)
|
|
91
96
|
const char *
|
92
97
|
bufcstr(struct buf *buf)
|
93
98
|
{
|
94
|
-
|
95
|
-
return NULL;
|
99
|
+
assert(buf && buf->unit);
|
96
100
|
|
97
101
|
if (buf->size < buf->asize && buf->data[buf->size] == 0)
|
98
102
|
return (char *)buf->data;
|
@@ -110,12 +114,11 @@ void
|
|
110
114
|
bufprintf(struct buf *buf, const char *fmt, ...)
|
111
115
|
{
|
112
116
|
va_list ap;
|
113
|
-
if (!buf || !buf->unit)
|
114
|
-
return;
|
115
|
-
|
116
117
|
int n;
|
117
118
|
|
118
|
-
|
119
|
+
assert(buf && buf->unit);
|
120
|
+
|
121
|
+
if (buf->size >= buf->asize && bufgrow(buf, buf->size + 1) < 0)
|
119
122
|
return;
|
120
123
|
|
121
124
|
va_start(ap, fmt);
|
@@ -133,6 +136,7 @@ bufprintf(struct buf *buf, const char *fmt, ...)
|
|
133
136
|
if ((size_t)n >= buf->asize - buf->size) {
|
134
137
|
if (bufgrow(buf, buf->size + n + 1) < 0)
|
135
138
|
return;
|
139
|
+
|
136
140
|
va_start(ap, fmt);
|
137
141
|
n = _buf_vsnprintf((char *)buf->data + buf->size, buf->asize - buf->size, fmt, ap);
|
138
142
|
va_end(ap);
|
@@ -148,8 +152,7 @@ bufprintf(struct buf *buf, const char *fmt, ...)
|
|
148
152
|
void
|
149
153
|
bufput(struct buf *buf, const void *data, size_t len)
|
150
154
|
{
|
151
|
-
|
152
|
-
return;
|
155
|
+
assert(buf && buf->unit);
|
153
156
|
|
154
157
|
if (buf->size + len > buf->asize && bufgrow(buf, buf->size + len) < 0)
|
155
158
|
return;
|
@@ -170,8 +173,7 @@ bufputs(struct buf *buf, const char *str)
|
|
170
173
|
void
|
171
174
|
bufputc(struct buf *buf, int c)
|
172
175
|
{
|
173
|
-
|
174
|
-
return;
|
176
|
+
assert(buf && buf->unit);
|
175
177
|
|
176
178
|
if (buf->size + 1 > buf->asize && bufgrow(buf, buf->size + 1) < 0)
|
177
179
|
return;
|
@@ -208,8 +210,7 @@ bufreset(struct buf *buf)
|
|
208
210
|
void
|
209
211
|
bufslurp(struct buf *buf, size_t len)
|
210
212
|
{
|
211
|
-
|
212
|
-
return;
|
213
|
+
assert(buf && buf->unit);
|
213
214
|
|
214
215
|
if (len >= buf->size) {
|
215
216
|
buf->size = 0;
|
@@ -220,10 +221,3 @@ bufslurp(struct buf *buf, size_t len)
|
|
220
221
|
memmove(buf->data, buf->data + len, buf->size);
|
221
222
|
}
|
222
223
|
|
223
|
-
/* vbufprintf: stdarg variant of formatted printing into a buffer */
|
224
|
-
void
|
225
|
-
vbufprintf(struct buf *buf, const char *fmt, va_list ap)
|
226
|
-
{
|
227
|
-
|
228
|
-
}
|
229
|
-
|
data/ext/redcarpet/html.c
CHANGED
@@ -60,6 +60,16 @@ sdhtml_is_tag(const uint8_t *tag_data, size_t tag_size, const char *tagname)
|
|
60
60
|
return HTML_TAG_NONE;
|
61
61
|
}
|
62
62
|
|
63
|
+
static inline void escape_html(struct buf *ob, const uint8_t *source, size_t length)
|
64
|
+
{
|
65
|
+
houdini_escape_html0(ob, source, length, 0);
|
66
|
+
}
|
67
|
+
|
68
|
+
static inline void escape_href(struct buf *ob, const uint8_t *source, size_t length)
|
69
|
+
{
|
70
|
+
houdini_escape_href(ob, source, length);
|
71
|
+
}
|
72
|
+
|
63
73
|
/********************
|
64
74
|
* GENERIC RENDERER *
|
65
75
|
********************/
|
@@ -79,7 +89,7 @@ rndr_autolink(struct buf *ob, const struct buf *link, enum mkd_autolink type, vo
|
|
79
89
|
BUFPUTSL(ob, "<a href=\"");
|
80
90
|
if (type == MKDA_EMAIL)
|
81
91
|
BUFPUTSL(ob, "mailto:");
|
82
|
-
|
92
|
+
escape_href(ob, link->data, link->size);
|
83
93
|
|
84
94
|
if (options->link_attributes) {
|
85
95
|
bufputc(ob, '\"');
|
@@ -95,9 +105,9 @@ rndr_autolink(struct buf *ob, const struct buf *link, enum mkd_autolink type, vo
|
|
95
105
|
* want to print the `mailto:` prefix
|
96
106
|
*/
|
97
107
|
if (bufprefix(link, "mailto:") == 0) {
|
98
|
-
|
108
|
+
escape_html(ob, link->data + 7, link->size - 7);
|
99
109
|
} else {
|
100
|
-
|
110
|
+
escape_html(ob, link->data, link->size);
|
101
111
|
}
|
102
112
|
|
103
113
|
BUFPUTSL(ob, "</a>");
|
@@ -127,7 +137,7 @@ rndr_blockcode(struct buf *ob, const struct buf *text, const struct buf *lang, v
|
|
127
137
|
org++;
|
128
138
|
|
129
139
|
if (cls) bufputc(ob, ' ');
|
130
|
-
|
140
|
+
escape_html(ob, lang->data + org, i - org);
|
131
141
|
}
|
132
142
|
}
|
133
143
|
|
@@ -136,7 +146,7 @@ rndr_blockcode(struct buf *ob, const struct buf *text, const struct buf *lang, v
|
|
136
146
|
BUFPUTSL(ob, "<pre><code>");
|
137
147
|
|
138
148
|
if (text)
|
139
|
-
|
149
|
+
escape_html(ob, text->data, text->size);
|
140
150
|
|
141
151
|
BUFPUTSL(ob, "</code></pre>\n");
|
142
152
|
}
|
@@ -154,7 +164,7 @@ static int
|
|
154
164
|
rndr_codespan(struct buf *ob, const struct buf *text, void *opaque)
|
155
165
|
{
|
156
166
|
BUFPUTSL(ob, "<code>");
|
157
|
-
if (text)
|
167
|
+
if (text) escape_html(ob, text->data, text->size);
|
158
168
|
BUFPUTSL(ob, "</code>");
|
159
169
|
return 1;
|
160
170
|
}
|
@@ -230,11 +240,11 @@ rndr_link(struct buf *ob, const struct buf *link, const struct buf *title, const
|
|
230
240
|
BUFPUTSL(ob, "<a href=\"");
|
231
241
|
|
232
242
|
if (link && link->size)
|
233
|
-
|
243
|
+
escape_href(ob, link->data, link->size);
|
234
244
|
|
235
245
|
if (title && title->size) {
|
236
246
|
BUFPUTSL(ob, "\" title=\"");
|
237
|
-
|
247
|
+
escape_html(ob, title->data, title->size);
|
238
248
|
}
|
239
249
|
|
240
250
|
if (options->link_attributes) {
|
@@ -322,9 +332,9 @@ rndr_raw_block(struct buf *ob, const struct buf *text, void *opaque)
|
|
322
332
|
size_t org, sz;
|
323
333
|
if (!text) return;
|
324
334
|
sz = text->size;
|
325
|
-
while (sz > 0 && text->data[sz - 1] == '\n') sz
|
335
|
+
while (sz > 0 && text->data[sz - 1] == '\n') sz--;
|
326
336
|
org = 0;
|
327
|
-
while (org < sz && text->data[org] == '\n') org
|
337
|
+
while (org < sz && text->data[org] == '\n') org++;
|
328
338
|
if (org >= sz) return;
|
329
339
|
if (ob->size) bufputc(ob, '\n');
|
330
340
|
bufput(ob, text->data + org, sz - org);
|
@@ -356,15 +366,15 @@ rndr_image(struct buf *ob, const struct buf *link, const struct buf *title, cons
|
|
356
366
|
if (!link || !link->size) return 0;
|
357
367
|
|
358
368
|
BUFPUTSL(ob, "<img src=\"");
|
359
|
-
|
369
|
+
escape_href(ob, link->data, link->size);
|
360
370
|
BUFPUTSL(ob, "\" alt=\"");
|
361
371
|
|
362
372
|
if (alt && alt->size)
|
363
|
-
|
373
|
+
escape_html(ob, alt->data, alt->size);
|
364
374
|
|
365
375
|
if (title && title->size) {
|
366
376
|
BUFPUTSL(ob, "\" title=\"");
|
367
|
-
|
377
|
+
escape_html(ob, title->data, title->size); }
|
368
378
|
|
369
379
|
bufputs(ob, USE_XHTML(options) ? "\"/>" : "\">");
|
370
380
|
return 1;
|
@@ -375,6 +385,13 @@ rndr_raw_html(struct buf *ob, const struct buf *text, void *opaque)
|
|
375
385
|
{
|
376
386
|
struct html_renderopt *options = opaque;
|
377
387
|
|
388
|
+
/* HTML_ESCAPE overrides SKIP_HTML, SKIP_STYLE, SKIP_LINKS and SKIP_IMAGES
|
389
|
+
* It doens't see if there are any valid tags, just escape all of them. */
|
390
|
+
if((options->flags & HTML_ESCAPE) != 0) {
|
391
|
+
escape_html(ob, text->data, text->size);
|
392
|
+
return 1;
|
393
|
+
}
|
394
|
+
|
378
395
|
if ((options->flags & HTML_SKIP_HTML) != 0)
|
379
396
|
return 1;
|
380
397
|
|
@@ -466,7 +483,7 @@ static void
|
|
466
483
|
rndr_normal_text(struct buf *ob, const struct buf *text, void *opaque)
|
467
484
|
{
|
468
485
|
if (text)
|
469
|
-
|
486
|
+
escape_html(ob, text->data, text->size);
|
470
487
|
}
|
471
488
|
|
472
489
|
static void
|
@@ -598,6 +615,6 @@ sdhtml_renderer(struct sd_callbacks *callbacks, struct html_renderopt *options,
|
|
598
615
|
callbacks->autolink = NULL;
|
599
616
|
}
|
600
617
|
|
601
|
-
if (render_flags & HTML_SKIP_HTML)
|
618
|
+
if (render_flags & HTML_SKIP_HTML || render_flags & HTML_ESCAPE)
|
602
619
|
callbacks->blockhtml = NULL;
|
603
620
|
}
|
data/ext/redcarpet/html.h
CHANGED
data/ext/redcarpet/markdown.c
CHANGED
@@ -1575,7 +1575,7 @@ parse_listitem(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t s
|
|
1575
1575
|
struct buf *work = 0, *inter = 0;
|
1576
1576
|
size_t beg = 0, end, pre, sublist = 0, orgpre = 0, i;
|
1577
1577
|
int in_empty = 0, has_inside_empty = 0;
|
1578
|
-
|
1578
|
+
size_t has_next_uli, has_next_oli;
|
1579
1579
|
|
1580
1580
|
/* keeping track of the first indentation prefix */
|
1581
1581
|
while (orgpre < 3 && orgpre < size && data[orgpre] == ' ')
|
@@ -1627,9 +1627,8 @@ parse_listitem(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t s
|
|
1627
1627
|
|
1628
1628
|
/* checking for ul/ol switch */
|
1629
1629
|
if (in_empty && (
|
1630
|
-
|
1631
|
-
|
1632
|
-
)){
|
1630
|
+
((*flags & MKD_LIST_ORDERED) && has_next_uli) ||
|
1631
|
+
(!(*flags & MKD_LIST_ORDERED) && has_next_oli))){
|
1633
1632
|
*flags |= MKD_LI_END;
|
1634
1633
|
break; /* the following item must have same list type */
|
1635
1634
|
}
|
@@ -1804,7 +1803,7 @@ parse_htmlblock(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t
|
|
1804
1803
|
i++;
|
1805
1804
|
|
1806
1805
|
if (i < size)
|
1807
|
-
curtag = find_block_tag((char *)data + 1, i - 1);
|
1806
|
+
curtag = find_block_tag((char *)data + 1, (int)i - 1);
|
1808
1807
|
|
1809
1808
|
/* handling of special cases */
|
1810
1809
|
if (!curtag) {
|
@@ -2361,7 +2360,7 @@ sd_markdown_new(
|
|
2361
2360
|
void
|
2362
2361
|
sd_markdown_render(struct buf *ob, const uint8_t *document, size_t doc_size, struct sd_markdown *md)
|
2363
2362
|
{
|
2364
|
-
|
2363
|
+
#define MARKDOWN_GROW(x) ((x) + ((x) >> 1))
|
2365
2364
|
|
2366
2365
|
struct buf *text;
|
2367
2366
|
size_t beg, end;
|
@@ -2401,7 +2400,7 @@ sd_markdown_render(struct buf *ob, const uint8_t *document, size_t doc_size, str
|
|
2401
2400
|
}
|
2402
2401
|
|
2403
2402
|
/* pre-grow the output buffer to minimize allocations */
|
2404
|
-
bufgrow(ob, text->size
|
2403
|
+
bufgrow(ob, MARKDOWN_GROW(text->size));
|
2405
2404
|
|
2406
2405
|
/* second pass: actual rendering */
|
2407
2406
|
if (md->cb.doc_header)
|
data/ext/redcarpet/rc_markdown.c
CHANGED
@@ -89,6 +89,18 @@ static VALUE rb_redcarpet_md__new(int argc, VALUE *argv, VALUE klass)
|
|
89
89
|
return rb_markdown;
|
90
90
|
}
|
91
91
|
|
92
|
+
static void check_utf8_encoding(VALUE str)
|
93
|
+
{
|
94
|
+
#ifdef HAVE_RUBY_ENCODING_H
|
95
|
+
rb_encoding *enc = rb_enc_get(str);
|
96
|
+
if (enc != rb_utf8_encoding() && enc != rb_usascii_encoding()) {
|
97
|
+
rb_raise(rb_eTypeError,
|
98
|
+
"Input must be UTF-8 or US-ASCII, %s given", rb_enc_name(enc));
|
99
|
+
}
|
100
|
+
#endif
|
101
|
+
}
|
102
|
+
|
103
|
+
|
92
104
|
static VALUE rb_redcarpet_md_render(VALUE self, VALUE text)
|
93
105
|
{
|
94
106
|
VALUE rb_rndr;
|
@@ -96,6 +108,7 @@ static VALUE rb_redcarpet_md_render(VALUE self, VALUE text)
|
|
96
108
|
struct sd_markdown *markdown;
|
97
109
|
|
98
110
|
Check_Type(text, T_STRING);
|
111
|
+
check_utf8_encoding(text);
|
99
112
|
|
100
113
|
rb_rndr = rb_iv_get(self, "@renderer");
|
101
114
|
Data_Get_Struct(self, struct sd_markdown, markdown);
|
data/ext/redcarpet/rc_render.c
CHANGED
@@ -352,6 +352,10 @@ static VALUE rb_redcarpet_html_init(int argc, VALUE *argv, VALUE self)
|
|
352
352
|
{
|
353
353
|
Check_Type(hash, T_HASH);
|
354
354
|
|
355
|
+
/* escape_html */
|
356
|
+
if (rb_hash_aref(hash, CSTR2SYM("escape_html")) == Qtrue)
|
357
|
+
render_flags |= HTML_ESCAPE;
|
358
|
+
|
355
359
|
/* filter_html */
|
356
360
|
if (rb_hash_aref(hash, CSTR2SYM("filter_html")) == Qtrue)
|
357
361
|
render_flags |= HTML_SKIP_HTML;
|
data/lib/redcarpet.rb
CHANGED
data/redcarpet.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
Gem::Specification.new do |s|
|
3
3
|
s.name = 'redcarpet'
|
4
|
-
s.version = '2.0.
|
4
|
+
s.version = '2.0.1'
|
5
5
|
s.summary = "Markdown that smells nice"
|
6
6
|
s.description = 'A fast, safe and extensible Markdown to (X)HTML parser'
|
7
7
|
s.date = '2011-09-14'
|
@@ -34,6 +34,7 @@ Gem::Specification.new do |s|
|
|
34
34
|
ext/redcarpet/stack.c
|
35
35
|
ext/redcarpet/stack.h
|
36
36
|
lib/redcarpet.rb
|
37
|
+
lib/redcarpet/compat.rb
|
37
38
|
lib/redcarpet/render_man.rb
|
38
39
|
redcarpet.gemspec
|
39
40
|
sundown
|
data/test/redcarpet_test.rb
CHANGED
@@ -60,6 +60,7 @@ class HTMLRenderTest < Test::Unit::TestCase
|
|
60
60
|
:no_images => Redcarpet::Render::HTML.new(:no_images => true),
|
61
61
|
:no_links => Redcarpet::Render::HTML.new(:no_links => true),
|
62
62
|
:safe_links => Redcarpet::Render::HTML.new(:safe_links_only => true),
|
63
|
+
:escape_html => Redcarpet::Render::HTML.new(:escape_html => true),
|
63
64
|
}
|
64
65
|
end
|
65
66
|
|
@@ -67,6 +68,28 @@ class HTMLRenderTest < Test::Unit::TestCase
|
|
67
68
|
Redcarpet::Markdown.new(rndr).render(text)
|
68
69
|
end
|
69
70
|
|
71
|
+
# Hint: overrides filter_html, no_images and no_links
|
72
|
+
def test_that_escape_html_works
|
73
|
+
source = <<EOS
|
74
|
+
Through <em>NO</em> <script>DOUBLE NO</script>
|
75
|
+
|
76
|
+
<script>BAD</script>
|
77
|
+
|
78
|
+
<img src="/favicon.ico" />
|
79
|
+
EOS
|
80
|
+
expected = <<EOE
|
81
|
+
<p>Through <em>NO</em> <script>DOUBLE NO</script></p>
|
82
|
+
|
83
|
+
<p><script>BAD</script></p>
|
84
|
+
|
85
|
+
<p><img src="/favicon.ico" />
|
86
|
+
|
87
|
+
EOE
|
88
|
+
|
89
|
+
markdown = render_with(@rndr[:escape_html], source)
|
90
|
+
html_equal expected, markdown
|
91
|
+
end
|
92
|
+
|
70
93
|
def test_that_filter_html_works
|
71
94
|
markdown = render_with(@rndr[:no_html], 'Through <em>NO</em> <script>DOUBLE NO</script>')
|
72
95
|
html_equal "<p>Through NO DOUBLE NO</p>", markdown
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redcarpet
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 13
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 2
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 2.0.
|
9
|
+
- 1
|
10
|
+
version: 2.0.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- "Natacha Port\xC3\xA9"
|
@@ -65,6 +65,7 @@ files:
|
|
65
65
|
- ext/redcarpet/stack.c
|
66
66
|
- ext/redcarpet/stack.h
|
67
67
|
- lib/redcarpet.rb
|
68
|
+
- lib/redcarpet/compat.rb
|
68
69
|
- lib/redcarpet/render_man.rb
|
69
70
|
- redcarpet.gemspec
|
70
71
|
- test/redcarpet_test.rb
|