Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
Initial commit. Mandatory ASCII chicken: <")3
- Loading branch information
0 parents
commit 96e7db3
Showing
16 changed files
with
1,365 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
[submodule "upskirt"] | ||
path = upskirt | ||
url = git://github.com/tanoku/upskirt.git |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
Copyright (c) 2011, Vicent Marti | ||
|
||
Permission to use, copy, modify, and distribute this software for any | ||
purpose with or without fee is hereby granted, provided that the above | ||
copyright notice and this permission notice appear in all copies. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
require 'date' | ||
require 'rake/clean' | ||
require 'rake/extensiontask' | ||
require 'digest/md5' | ||
|
||
task :default => :test | ||
|
||
# ========================================================== | ||
# Ruby Extension | ||
# ========================================================== | ||
|
||
Rake::ExtensionTask.new('rinku') | ||
|
||
# ========================================================== | ||
# Testing | ||
# ========================================================== | ||
|
||
require 'rake/testtask' | ||
Rake::TestTask.new('test') do |t| | ||
t.test_files = FileList['test/*_test.rb'] | ||
t.ruby_opts += ['-rubygems'] if defined? Gem | ||
end | ||
task 'test' => [:compile] | ||
|
||
# PACKAGING ================================================================= | ||
|
||
require 'rubygems' | ||
$spec = eval(File.read('rinku.gemspec')) | ||
|
||
def package(ext='') | ||
"pkg/rinku-#{$spec.version}" + ext | ||
end | ||
|
||
desc 'Build packages' | ||
task :package => package('.gem') | ||
|
||
desc 'Build and install as local gem' | ||
task :install => package('.gem') do | ||
sh "gem install #{package('.gem')}" | ||
end | ||
|
||
desc 'Update the gemspec' | ||
task :update_gem => file('rinku.gemspec') | ||
|
||
directory 'pkg/' | ||
|
||
file package('.gem') => %w[pkg/ rinku.gemspec] + $spec.files do |f| | ||
sh "gem build rinku.gemspec" | ||
mv File.basename(f.name), f.name | ||
end | ||
|
||
# GEMSPEC HELPERS ========================================================== | ||
|
||
desc 'Gather required Upskirt sources into extension directory' | ||
task :gather => 'upskirt/src/markdown.h' do |t| | ||
files = | ||
FileList[ | ||
'upskirt/src/{buffer,autolink}.h', | ||
'upskirt/src/{buffer,autolink}.c', | ||
'upskirt/html/html_autolink.c' | ||
] | ||
cp files, 'ext/rinku/', | ||
:preserve => true, | ||
:verbose => true | ||
end | ||
|
||
file 'upskirt/src/markdown.h' do |t| | ||
abort "The Upskirt submodule is required." | ||
end | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
0.1.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,239 @@ | ||
/* | ||
* Copyright (c) 2011, Vicent Marti | ||
* | ||
* Permission to use, copy, modify, and distribute this software for any | ||
* purpose with or without fee is hereby granted, provided that the above | ||
* copyright notice and this permission notice appear in all copies. | ||
* | ||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
*/ | ||
|
||
#include "buffer.h" | ||
|
||
#include <string.h> | ||
#include <stdlib.h> | ||
#include <stdio.h> | ||
#include <ctype.h> | ||
|
||
int | ||
is_safe_link(const char *link, size_t link_len) | ||
{ | ||
static const size_t valid_uris_count = 4; | ||
static const char *valid_uris[] = { | ||
"http://", "https://", "ftp://", "mailto://" | ||
}; | ||
|
||
size_t i; | ||
|
||
for (i = 0; i < valid_uris_count; ++i) { | ||
size_t len = strlen(valid_uris[i]); | ||
|
||
if (link_len > len && | ||
strncasecmp(link, valid_uris[i], len) == 0 && | ||
isalnum(link[len])) | ||
return 1; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
static size_t | ||
autolink_delim(char *data, size_t link_end, size_t offset, size_t size) | ||
{ | ||
char cclose, copen = 0; | ||
|
||
while (link_end > 0) { | ||
if (strchr("?!.,", data[link_end - 1]) != NULL) | ||
link_end--; | ||
|
||
else if (data[link_end - 1] == ';') { | ||
size_t new_end = link_end - 2; | ||
|
||
while (new_end > 0 && isalpha(data[new_end])) | ||
new_end--; | ||
|
||
if (new_end < link_end - 2 && data[new_end] == '&') | ||
link_end = new_end; | ||
else | ||
link_end--; | ||
} | ||
|
||
else if (data[link_end - 1] == '>') { | ||
while (link_end > 0 && data[link_end] != '<') | ||
link_end--; | ||
} | ||
else break; | ||
} | ||
|
||
if (link_end == 0) | ||
return 0; | ||
|
||
cclose = data[link_end - 1]; | ||
|
||
switch (cclose) { | ||
case '"': copen = '"'; break; | ||
case '\'': copen = '\''; break; | ||
case ')': copen = '('; break; | ||
case ']': copen = '['; break; | ||
case '}': copen = '{'; break; | ||
} | ||
|
||
if (copen != 0) { | ||
size_t closing = 0; | ||
size_t opening = 0; | ||
size_t i = 0; | ||
|
||
/* Try to close the final punctuation sign in this same line; | ||
* if we managed to close it outside of the URL, that means that it's | ||
* not part of the URL. If it closes inside the URL, that means it | ||
* is part of the URL. | ||
* | ||
* Examples: | ||
* | ||
* foo http://www.pokemon.com/Pikachu_(Electric) bar | ||
* => http://www.pokemon.com/Pikachu_(Electric) | ||
* | ||
* foo (http://www.pokemon.com/Pikachu_(Electric)) bar | ||
* => http://www.pokemon.com/Pikachu_(Electric) | ||
* | ||
* foo http://www.pokemon.com/Pikachu_(Electric)) bar | ||
* => http://www.pokemon.com/Pikachu_(Electric)) | ||
* | ||
* (foo http://www.pokemon.com/Pikachu_(Electric)) bar | ||
* => foo http://www.pokemon.com/Pikachu_(Electric) | ||
*/ | ||
|
||
while (i < link_end) { | ||
if (data[i] == copen) | ||
opening++; | ||
else if (data[i] == cclose) | ||
closing++; | ||
|
||
i++; | ||
} | ||
|
||
if (closing != opening) | ||
link_end--; | ||
} | ||
|
||
return link_end; | ||
} | ||
|
||
size_t | ||
ups_autolink__www(size_t *rewind_p, struct buf *link, char *data, size_t offset, size_t size) | ||
{ | ||
size_t link_end; | ||
int np = 0; | ||
|
||
if (offset > 0 && !ispunct(data[-1]) && !isspace(data[-1])) | ||
return 0; | ||
|
||
if (size < 4 || memcmp(data, "www.", STRLEN("www.")) != 0) | ||
return 0; | ||
|
||
link_end = 0; | ||
while (link_end < size && !isspace(data[link_end])) { | ||
if (data[link_end] == '.') | ||
np++; | ||
|
||
link_end++; | ||
} | ||
|
||
if (np < 2) | ||
return 0; | ||
|
||
link_end = autolink_delim(data, link_end, offset, size); | ||
|
||
if (link_end == 0) | ||
return 0; | ||
|
||
bufput(link, data, link_end); | ||
*rewind_p = 0; | ||
|
||
return (int)link_end; | ||
} | ||
|
||
size_t | ||
ups_autolink__email(size_t *rewind_p, struct buf *link, char *data, size_t offset, size_t size) | ||
{ | ||
size_t link_end, rewind; | ||
int nb = 0, np = 0; | ||
|
||
for (rewind = 0; rewind < offset; ++rewind) { | ||
char c = data[-rewind - 1]; | ||
|
||
if (isalnum(c)) | ||
continue; | ||
|
||
if (strchr(".+-_", c) != NULL) | ||
continue; | ||
|
||
break; | ||
} | ||
|
||
if (rewind == 0) | ||
return 0; | ||
|
||
for (link_end = 0; link_end < size; ++link_end) { | ||
char c = data[link_end]; | ||
|
||
if (isalnum(c)) | ||
continue; | ||
|
||
if (c == '@') | ||
nb++; | ||
else if (c == '.' && link_end < size - 1) | ||
np++; | ||
else if (c != '-' && c != '_') | ||
break; | ||
} | ||
|
||
if (link_end < 2 || nb != 1 || np == 0) | ||
return 0; | ||
|
||
link_end = autolink_delim(data, link_end, offset, size); | ||
|
||
if (link_end == 0) | ||
return 0; | ||
|
||
bufput(link, data - rewind, link_end + rewind); | ||
*rewind_p = rewind; | ||
|
||
return link_end; | ||
} | ||
|
||
size_t | ||
ups_autolink__url(size_t *rewind_p, struct buf *link, char *data, size_t offset, size_t size) | ||
{ | ||
size_t link_end, rewind = 0; | ||
|
||
if (size < 4 || data[1] != '/' || data[2] != '/') | ||
return 0; | ||
|
||
while (rewind < offset && isalpha(data[-rewind - 1])) | ||
rewind++; | ||
|
||
if (!is_safe_link(data - rewind, size + rewind)) | ||
return 0; | ||
|
||
link_end = 0; | ||
while (link_end < size && !isspace(data[link_end])) | ||
link_end++; | ||
|
||
link_end = autolink_delim(data, link_end, offset, size); | ||
|
||
if (link_end == 0) | ||
return 0; | ||
|
||
bufput(link, data - rewind, link_end + rewind); | ||
*rewind_p = rewind; | ||
|
||
return link_end; | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
/* | ||
* Copyright (c) 2011, Vicent Marti | ||
* | ||
* Permission to use, copy, modify, and distribute this software for any | ||
* purpose with or without fee is hereby granted, provided that the above | ||
* copyright notice and this permission notice appear in all copies. | ||
* | ||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
*/ | ||
|
||
#ifndef UPSKIRT_AUTOLINK_H | ||
#define UPSKIRT_AUTOLINK_H_H | ||
|
||
#include "buffer.h" | ||
|
||
typedef enum { | ||
AUTOLINK_URLS = (1 << 0), | ||
AUTOLINK_EMAILS = (1 << 1), | ||
AUTOLINK_ALL = AUTOLINK_URLS|AUTOLINK_EMAILS | ||
} autolink_mode; | ||
|
||
extern size_t | ||
ups_autolink__www(size_t *rewind_p, struct buf *link, char *data, size_t offset, size_t size); | ||
|
||
extern size_t | ||
ups_autolink__email(size_t *rewind_p, struct buf *link, char *data, size_t offset, size_t size); | ||
|
||
extern size_t | ||
ups_autolink__url(size_t *rewind_p, struct buf *link, char *data, size_t offset, size_t size); | ||
|
||
#endif | ||
|
||
/* vim: set filetype=c: */ |
Oops, something went wrong.