rinku 1.3.1 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +2 -1
- data/ext/rinku/rinku.c +11 -5
- data/lib/rails_rinku.rb +2 -1
- data/rinku.gemspec +1 -4
- data/test/autolink_test.rb +12 -9
- metadata +2 -5
- data/ext/rinku/houdini.h +0 -28
- data/ext/rinku/houdini_href_e.c +0 -108
- data/ext/rinku/houdini_html_e.c +0 -84
data/README.markdown
CHANGED
@@ -89,7 +89,8 @@ Rinku is written by me
|
|
89
89
|
----------------------
|
90
90
|
|
91
91
|
I am Vicent Marti, and I wrote Rinku.
|
92
|
-
While Rinku is busy doing autolinks, you should be busy following me on twitter.
|
92
|
+
While Rinku is busy doing autolinks, you should be busy following me on twitter.
|
93
|
+
[`@tanoku`](http://twitter.com/tanoku). Do it.
|
93
94
|
|
94
95
|
Rinku has an awesome license
|
95
96
|
----------------------------
|
data/ext/rinku/rinku.c
CHANGED
@@ -26,7 +26,6 @@
|
|
26
26
|
|
27
27
|
#include "autolink.h"
|
28
28
|
#include "buffer.h"
|
29
|
-
#include "houdini.h"
|
30
29
|
|
31
30
|
#include <string.h>
|
32
31
|
#include <stdlib.h>
|
@@ -73,9 +72,9 @@ static const char *g_hrefs[] = {
|
|
73
72
|
};
|
74
73
|
|
75
74
|
static void
|
76
|
-
|
75
|
+
autolink__print(struct buf *ob, const struct buf *link, void *payload)
|
77
76
|
{
|
78
|
-
|
77
|
+
bufput(ob, link->data, link->size);
|
79
78
|
}
|
80
79
|
|
81
80
|
/* From sundown/html/html.c */
|
@@ -187,7 +186,7 @@ rinku_autolink(
|
|
187
186
|
}
|
188
187
|
|
189
188
|
if (link_text_cb == NULL)
|
190
|
-
link_text_cb = &
|
189
|
+
link_text_cb = &autolink__print;
|
191
190
|
|
192
191
|
if (link_attr != NULL) {
|
193
192
|
while (isspace(*link_attr))
|
@@ -228,7 +227,7 @@ rinku_autolink(
|
|
228
227
|
bufput(ob, text + i, end - i - rewind);
|
229
228
|
|
230
229
|
bufputs(ob, g_hrefs[(int)action]);
|
231
|
-
|
230
|
+
bufput(ob, link->data, link->size);
|
232
231
|
|
233
232
|
if (link_attr) {
|
234
233
|
BUFPUTSL(ob, "\" ");
|
@@ -277,6 +276,13 @@ autolink_callback(struct buf *link_text, const struct buf *link, void *block)
|
|
277
276
|
* Parses a block of text looking for "safe" urls or email addresses,
|
278
277
|
* and turns them into HTML links with the given attributes.
|
279
278
|
*
|
279
|
+
* NOTE: The block of text may or may not be HTML; if the text is HTML,
|
280
|
+
* Rinku will skip the relevant tags to prevent double-linking and linking
|
281
|
+
* inside `pre` blocks by default.
|
282
|
+
*
|
283
|
+
* NOTE: If the input text is HTML, it's expected to be already escaped.
|
284
|
+
* Rinku will perform no escaping.
|
285
|
+
*
|
280
286
|
* NOTE: Currently the follow protocols are considered safe and are the
|
281
287
|
* only ones that will be autolinked.
|
282
288
|
*
|
data/lib/rails_rinku.rb
CHANGED
@@ -10,8 +10,9 @@ module RailsRinku
|
|
10
10
|
options[:html] = args[1] || {}
|
11
11
|
end
|
12
12
|
options.reverse_merge!(:link => :all, :html => {})
|
13
|
+
text = text.html_safe unless text.html_safe?
|
13
14
|
|
14
|
-
Rinku.auto_link(text, options[:link], tag_options(options[:html]), &block)
|
15
|
+
Rinku.auto_link(text.html_safe, options[:link], tag_options(options[:html]), &block)
|
15
16
|
end
|
16
17
|
end
|
17
18
|
|
data/rinku.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'rinku'
|
3
|
-
s.version = '1.
|
3
|
+
s.version = '1.4.0'
|
4
4
|
s.summary = "Mostly autolinking"
|
5
5
|
s.description = <<-EOF
|
6
6
|
A fast and very smart autolinking library that
|
@@ -20,9 +20,6 @@ Gem::Specification.new do |s|
|
|
20
20
|
ext/rinku/buffer.c
|
21
21
|
ext/rinku/buffer.h
|
22
22
|
ext/rinku/extconf.rb
|
23
|
-
ext/rinku/houdini.h
|
24
|
-
ext/rinku/houdini_href_e.c
|
25
|
-
ext/rinku/houdini_html_e.c
|
26
23
|
lib/rinku.rb
|
27
24
|
lib/rails_rinku.rb
|
28
25
|
rinku.gemspec
|
data/test/autolink_test.rb
CHANGED
@@ -79,11 +79,14 @@ This is just a test. <a href="http://www.pokemon.com">http://www.pokemon.com</a>
|
|
79
79
|
pic = "http://example.com/pic.png"
|
80
80
|
url = "http://example.com/album?a&b=c"
|
81
81
|
|
82
|
-
|
82
|
+
expect = %(My pic: <a href="#{pic}"><img src="#{pic}" width="160px"></a> -- full album here #{generate_result(url)})
|
83
|
+
text = "My pic: #{pic} -- full album here #{CGI.escapeHTML url}"
|
84
|
+
|
85
|
+
assert_equal expect, Rinku.auto_link(text) { |link|
|
83
86
|
if link =~ /\.(jpg|gif|png|bmp|tif)$/i
|
84
|
-
%(<img src="#{
|
87
|
+
%(<img src="#{link}" width="160px">)
|
85
88
|
else
|
86
|
-
|
89
|
+
link
|
87
90
|
end
|
88
91
|
}
|
89
92
|
end
|
@@ -166,7 +169,7 @@ This is just a test. <a href="http://www.pokemon.com">http://www.pokemon.com</a>
|
|
166
169
|
)
|
167
170
|
|
168
171
|
urls.each do |url|
|
169
|
-
assert_linked %(<a href="#{CGI.escapeHTML
|
172
|
+
assert_linked %(<a href="#{CGI.escapeHTML url}">#{CGI.escapeHTML url}</a>), CGI.escapeHTML(url)
|
170
173
|
end
|
171
174
|
end
|
172
175
|
|
@@ -182,14 +185,14 @@ This is just a test. <a href="http://www.pokemon.com">http://www.pokemon.com</a>
|
|
182
185
|
link2_result = %{<a href="http://#{link2_raw}">#{link2_raw}</a>}
|
183
186
|
link3_raw = 'http://manuals.ruby-on-rails.com/read/chapter.need_a-period/103#page281'
|
184
187
|
link3_result = %{<a href="#{link3_raw}">#{link3_raw}</a>}
|
185
|
-
link4_raw = 'http://foo.example.com/controller/action?parm=value&p2=v2#anchor123'
|
186
|
-
link4_result = %{<a href="#{
|
188
|
+
link4_raw = CGI.escapeHTML 'http://foo.example.com/controller/action?parm=value&p2=v2#anchor123'
|
189
|
+
link4_result = %{<a href="#{link4_raw}">#{link4_raw}</a>}
|
187
190
|
link5_raw = 'http://foo.example.com:3000/controller/action'
|
188
191
|
link5_result = %{<a href="#{link5_raw}">#{link5_raw}</a>}
|
189
192
|
link6_raw = 'http://foo.example.com:3000/controller/action+pack'
|
190
193
|
link6_result = %{<a href="#{link6_raw}">#{link6_raw}</a>}
|
191
|
-
link7_raw = 'http://foo.example.com/controller/action?parm=value&p2=v2#anchor-123'
|
192
|
-
link7_result = %{<a href="#{
|
194
|
+
link7_raw = CGI.escapeHTML 'http://foo.example.com/controller/action?parm=value&p2=v2#anchor-123'
|
195
|
+
link7_result = %{<a href="#{link7_raw}">#{link7_raw}</a>}
|
193
196
|
link8_raw = 'http://foo.example.com:3000/controller/action.html'
|
194
197
|
link8_result = %{<a href="#{link8_raw}">#{link8_raw}</a>}
|
195
198
|
link9_raw = 'http://business.timesonline.co.uk/article/0,,9065-2473189,00.html'
|
@@ -245,7 +248,7 @@ This is just a test. <a href="http://www.pokemon.com">http://www.pokemon.com</a>
|
|
245
248
|
|
246
249
|
def generate_result(link_text, href = nil)
|
247
250
|
href ||= link_text
|
248
|
-
%{<a href="#{CGI
|
251
|
+
%{<a href="#{CGI.escapeHTML href}">#{CGI.escapeHTML link_text}</a>}
|
249
252
|
end
|
250
253
|
|
251
254
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rinku
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.4.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-11-
|
12
|
+
date: 2011-11-10 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: ! " A fast and very smart autolinking library that\n acts as a
|
15
15
|
drop-in replacement for Rails `auto_link`\n"
|
@@ -29,9 +29,6 @@ files:
|
|
29
29
|
- ext/rinku/buffer.c
|
30
30
|
- ext/rinku/buffer.h
|
31
31
|
- ext/rinku/extconf.rb
|
32
|
-
- ext/rinku/houdini.h
|
33
|
-
- ext/rinku/houdini_href_e.c
|
34
|
-
- ext/rinku/houdini_html_e.c
|
35
32
|
- lib/rinku.rb
|
36
33
|
- lib/rails_rinku.rb
|
37
34
|
- rinku.gemspec
|
data/ext/rinku/houdini.h
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
#ifndef __HOUDINI_H__
|
2
|
-
#define __HOUDINI_H__
|
3
|
-
|
4
|
-
#include "buffer.h"
|
5
|
-
|
6
|
-
#ifdef HOUDINI_USE_LOCALE
|
7
|
-
# define _isxdigit(c) isxdigit(c)
|
8
|
-
# define _isdigit(c) isdigit(c)
|
9
|
-
#else
|
10
|
-
/*
|
11
|
-
* Helper _isdigit methods -- do not trust the current locale
|
12
|
-
* */
|
13
|
-
# define _isxdigit(c) (strchr("0123456789ABCDEFabcdef", (c)) != NULL)
|
14
|
-
# define _isdigit(c) ((c) >= '0' && (c) <= '9')
|
15
|
-
#endif
|
16
|
-
|
17
|
-
extern void houdini_escape_html(struct buf *ob, const uint8_t *src, size_t size);
|
18
|
-
extern void houdini_escape_html0(struct buf *ob, const uint8_t *src, size_t size, int secure);
|
19
|
-
extern void houdini_unescape_html(struct buf *ob, const uint8_t *src, size_t size);
|
20
|
-
extern void houdini_escape_uri(struct buf *ob, const uint8_t *src, size_t size);
|
21
|
-
extern void houdini_escape_url(struct buf *ob, const uint8_t *src, size_t size);
|
22
|
-
extern void houdini_escape_href(struct buf *ob, const uint8_t *src, size_t size);
|
23
|
-
extern void houdini_unescape_uri(struct buf *ob, const uint8_t *src, size_t size);
|
24
|
-
extern void houdini_unescape_url(struct buf *ob, const uint8_t *src, size_t size);
|
25
|
-
extern void houdini_escape_js(struct buf *ob, const uint8_t *src, size_t size);
|
26
|
-
extern void houdini_unescape_js(struct buf *ob, const uint8_t *src, size_t size);
|
27
|
-
|
28
|
-
#endif
|
data/ext/rinku/houdini_href_e.c
DELETED
@@ -1,108 +0,0 @@
|
|
1
|
-
#include <assert.h>
|
2
|
-
#include <stdio.h>
|
3
|
-
#include <string.h>
|
4
|
-
|
5
|
-
#include "houdini.h"
|
6
|
-
|
7
|
-
#define ESCAPE_GROW_FACTOR(x) (((x) * 12) / 10)
|
8
|
-
|
9
|
-
/*
|
10
|
-
* The following characters will not be escaped:
|
11
|
-
*
|
12
|
-
* -_.+!*'(),%#@?=;:/,+&$ alphanum
|
13
|
-
*
|
14
|
-
* Note that this character set is the addition of:
|
15
|
-
*
|
16
|
-
* - The characters which are safe to be in an URL
|
17
|
-
* - The characters which are *not* safe to be in
|
18
|
-
* an URL because they are RESERVED characters.
|
19
|
-
*
|
20
|
-
* We asume (lazily) that any RESERVED char that
|
21
|
-
* appears inside an URL is actually meant to
|
22
|
-
* have its native function (i.e. as an URL
|
23
|
-
* component/separator) and hence needs no escaping.
|
24
|
-
*
|
25
|
-
* There are two exceptions: the chacters & (amp)
|
26
|
-
* and ' (single quote) do not appear in the table.
|
27
|
-
* They are meant to appear in the URL as components,
|
28
|
-
* yet they require special HTML-entity escaping
|
29
|
-
* to generate valid HTML markup.
|
30
|
-
*
|
31
|
-
* All other characters will be escaped to %XX.
|
32
|
-
*
|
33
|
-
*/
|
34
|
-
static const char HREF_SAFE[] = {
|
35
|
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
36
|
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
37
|
-
0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
|
38
|
-
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1,
|
39
|
-
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
40
|
-
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
|
41
|
-
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
42
|
-
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
|
43
|
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
44
|
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
45
|
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
46
|
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
47
|
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
48
|
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
49
|
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
50
|
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
51
|
-
};
|
52
|
-
|
53
|
-
void
|
54
|
-
houdini_escape_href(struct buf *ob, const uint8_t *src, size_t size)
|
55
|
-
{
|
56
|
-
static const char hex_chars[] = "0123456789ABCDEF";
|
57
|
-
size_t i = 0, org;
|
58
|
-
char hex_str[3];
|
59
|
-
|
60
|
-
bufgrow(ob, ESCAPE_GROW_FACTOR(size));
|
61
|
-
hex_str[0] = '%';
|
62
|
-
|
63
|
-
while (i < size) {
|
64
|
-
org = i;
|
65
|
-
while (i < size && HREF_SAFE[src[i]] != 0)
|
66
|
-
i++;
|
67
|
-
|
68
|
-
if (i > org)
|
69
|
-
bufput(ob, src + org, i - org);
|
70
|
-
|
71
|
-
/* escaping */
|
72
|
-
if (i >= size)
|
73
|
-
break;
|
74
|
-
|
75
|
-
switch (src[i]) {
|
76
|
-
/* amp appears all the time in URLs, but needs
|
77
|
-
* HTML-entity escaping to be inside an href */
|
78
|
-
case '&':
|
79
|
-
BUFPUTSL(ob, "&");
|
80
|
-
break;
|
81
|
-
|
82
|
-
/* the single quote is a valid URL character
|
83
|
-
* according to the standard; it needs HTML
|
84
|
-
* entity escaping too */
|
85
|
-
case '\'':
|
86
|
-
BUFPUTSL(ob, "'");
|
87
|
-
break;
|
88
|
-
|
89
|
-
/* the space can be escaped to %20 or a plus
|
90
|
-
* sign. we're going with the generic escape
|
91
|
-
* for now. the plus thing is more commonly seen
|
92
|
-
* when building GET strings */
|
93
|
-
#if 0
|
94
|
-
case ' ':
|
95
|
-
bufputc(ob, '+');
|
96
|
-
break;
|
97
|
-
#endif
|
98
|
-
|
99
|
-
/* every other character goes with a %XX escaping */
|
100
|
-
default:
|
101
|
-
hex_str[1] = hex_chars[(src[i] >> 4) & 0xF];
|
102
|
-
hex_str[2] = hex_chars[src[i] & 0xF];
|
103
|
-
bufput(ob, hex_str, 3);
|
104
|
-
}
|
105
|
-
|
106
|
-
i++;
|
107
|
-
}
|
108
|
-
}
|
data/ext/rinku/houdini_html_e.c
DELETED
@@ -1,84 +0,0 @@
|
|
1
|
-
#include <assert.h>
|
2
|
-
#include <stdio.h>
|
3
|
-
#include <string.h>
|
4
|
-
|
5
|
-
#include "houdini.h"
|
6
|
-
|
7
|
-
#define ESCAPE_GROW_FACTOR(x) (((x) * 12) / 10) /* this is very scientific, yes */
|
8
|
-
|
9
|
-
/**
|
10
|
-
* According to the OWASP rules:
|
11
|
-
*
|
12
|
-
* & --> &
|
13
|
-
* < --> <
|
14
|
-
* > --> >
|
15
|
-
* " --> "
|
16
|
-
* ' --> ' ' is not recommended
|
17
|
-
* / --> / forward slash is included as it helps end an HTML entity
|
18
|
-
*
|
19
|
-
*/
|
20
|
-
static const char HTML_ESCAPE_TABLE[] = {
|
21
|
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
22
|
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
23
|
-
0, 0, 1, 0, 0, 0, 2, 3, 0, 0, 0, 0, 0, 0, 0, 4,
|
24
|
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 6, 0,
|
25
|
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
26
|
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
27
|
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
28
|
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
29
|
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
30
|
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
31
|
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
32
|
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
33
|
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
34
|
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
35
|
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
36
|
-
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
37
|
-
};
|
38
|
-
|
39
|
-
static const char *HTML_ESCAPES[] = {
|
40
|
-
"",
|
41
|
-
""",
|
42
|
-
"&",
|
43
|
-
"'",
|
44
|
-
"/",
|
45
|
-
"<",
|
46
|
-
">"
|
47
|
-
};
|
48
|
-
|
49
|
-
void
|
50
|
-
houdini_escape_html0(struct buf *ob, const uint8_t *src, size_t size, int secure)
|
51
|
-
{
|
52
|
-
size_t i = 0, org, esc;
|
53
|
-
|
54
|
-
bufgrow(ob, ESCAPE_GROW_FACTOR(size));
|
55
|
-
|
56
|
-
while (i < size) {
|
57
|
-
org = i;
|
58
|
-
while (i < size && (esc = HTML_ESCAPE_TABLE[src[i]]) == 0)
|
59
|
-
i++;
|
60
|
-
|
61
|
-
if (i > org)
|
62
|
-
bufput(ob, src + org, i - org);
|
63
|
-
|
64
|
-
/* escaping */
|
65
|
-
if (i >= size)
|
66
|
-
break;
|
67
|
-
|
68
|
-
/* The forward slash is only escaped in secure mode */
|
69
|
-
if (src[i] == '/' && !secure) {
|
70
|
-
bufputc(ob, '/');
|
71
|
-
} else {
|
72
|
-
bufputs(ob, HTML_ESCAPES[esc]);
|
73
|
-
}
|
74
|
-
|
75
|
-
i++;
|
76
|
-
}
|
77
|
-
}
|
78
|
-
|
79
|
-
void
|
80
|
-
houdini_escape_html(struct buf *ob, const uint8_t *src, size_t size)
|
81
|
-
{
|
82
|
-
houdini_escape_html0(ob, src, size, 1);
|
83
|
-
}
|
84
|
-
|