else
This commit is contained in:
parent
9dd6bc8c02
commit
80966b7fb8
66 changed files with 13955 additions and 50 deletions
54
.gitignore
vendored
54
.gitignore
vendored
|
@ -1,34 +1,36 @@
|
|||
Classifieds/
|
||||
|
||||
# Windows image file caches
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
|
||||
# Folder config file
|
||||
Desktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Windows Installer files
|
||||
*.cab
|
||||
*.msi
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# =========================
|
||||
# Operating System Files
|
||||
# =========================
|
||||
|
||||
# OSX
|
||||
# =========================
|
||||
|
||||
AwfulCrateBox/
|
||||
Classifieds/
|
||||
|
||||
# Windows image file caches
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
|
||||
# Folder config file
|
||||
Desktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Windows Installer files
|
||||
*.cab
|
||||
*.msi
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# =========================
|
||||
# Operating System Files
|
||||
# =========================
|
||||
|
||||
# OSX
|
||||
# =========================
|
||||
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# Icon must end with two \r
|
||||
Icon
|
||||
Icon
|
||||
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
|
11
AHK/rapid_t.ahk
Normal file
11
AHK/rapid_t.ahk
Normal file
|
@ -0,0 +1,11 @@
|
|||
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
|
||||
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
|
||||
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
|
||||
|
||||
+T::
|
||||
While GetKeyState("t", "P")
|
||||
{
|
||||
Click WheelDown
|
||||
Sleep 20
|
||||
}
|
||||
Return
|
|
@ -3,6 +3,7 @@ import sys
|
|||
|
||||
imagename = sys.argv[1]
|
||||
image = Image.open(imagename)
|
||||
image = image.convert('RGBA')
|
||||
w = image.size[0] - 1
|
||||
h = image.size[1] - 1
|
||||
for i in range(5):
|
||||
|
|
|
@ -64,7 +64,8 @@
|
|||
import binascii
|
||||
import sys
|
||||
from PIL import Image
|
||||
|
||||
import os
|
||||
print(os.getcwd())
|
||||
try:
|
||||
INPUTFILE = sys.argv[1]
|
||||
except:
|
||||
|
|
|
@ -33,7 +33,7 @@ HELP_SENTENCE = '''
|
|||
---------------------------------------------------------------
|
||||
'''[1:-1] % (DEFAULT_SENTENCE)
|
||||
|
||||
def make_password(length=None, allowpunctuation=False, allowdigits=False):
|
||||
def make_password(length=None, allowpunctuation=False, allowdigits=False, digits_only=False, binary=False):
|
||||
'''
|
||||
Returns a string of length `length` consisting of a random selection
|
||||
of uppercase and lowercase letters, as well as punctuation and digits
|
||||
|
@ -41,12 +41,17 @@ def make_password(length=None, allowpunctuation=False, allowdigits=False):
|
|||
'''
|
||||
if length is None:
|
||||
length = DEFAULT_LENGTH
|
||||
|
||||
s = string.ascii_letters
|
||||
if allowpunctuation is True:
|
||||
s += string.punctuation
|
||||
if allowdigits is True:
|
||||
s += string.digits
|
||||
|
||||
if digits_only is False and binary is False:
|
||||
s = string.ascii_letters
|
||||
if allowpunctuation is True:
|
||||
s += string.punctuation
|
||||
if allowdigits is True:
|
||||
s += string.digits
|
||||
elif digits_only:
|
||||
s = string.digits
|
||||
elif binary:
|
||||
s = '01'
|
||||
|
||||
password = ''.join([random.choice(s) for x in range(length)])
|
||||
return password
|
||||
|
@ -100,7 +105,9 @@ if __name__ == '__main__':
|
|||
if mode == 'password':
|
||||
punc = 'p' in args
|
||||
digi = 'd' in args
|
||||
print(make_password(length, punc, digi))
|
||||
digi_only = 'dd' in args
|
||||
binary = 'b' in args
|
||||
print(make_password(length, punc, digi, digi_only, binary))
|
||||
|
||||
elif mode == 'sentence':
|
||||
if argc == 3:
|
||||
|
|
|
@ -16,7 +16,7 @@ def quadratic_formula(a, b, c):
|
|||
discriminant = math.sqrt(discriminant)
|
||||
b *= -1
|
||||
possible = (b + discriminant, b - discriminant)
|
||||
possible = [x / (2*a) for x in possible]
|
||||
possible = tuple(x / (2*a) for x in possible)
|
||||
return possible
|
||||
|
||||
def time_to_known_distance(velocity, distance, acceleration):
|
||||
|
@ -29,9 +29,11 @@ def time_to_known_distance(velocity, distance, acceleration):
|
|||
return min(possible)
|
||||
|
||||
def make_throw(starting_x, starting_y, starting_velocity, thrown_angle):
|
||||
# We don't track smallest_y because it's going to be 0!
|
||||
global smallest_x
|
||||
global largest_x
|
||||
global largest_y
|
||||
|
||||
upward = thrown_angle in range(1, 179, 1) or thrown_angle in range(-181, -359, -1)
|
||||
upward = -1 if upward else 1
|
||||
|
||||
|
@ -40,13 +42,6 @@ def make_throw(starting_x, starting_y, starting_velocity, thrown_angle):
|
|||
cos = math.cos(rads)
|
||||
tan = math.tan(rads)
|
||||
|
||||
throw = {'angle': thrown_angle}
|
||||
throw['horizontal_component'] = starting_velocity * cos * -upward
|
||||
throw['vertical_component'] = starting_velocity * sin * upward
|
||||
#print(thrown_angle, starting_velocity, throw['horizontal_component'])
|
||||
throw['hang_time'] = time_to_known_distance(throw['vertical_component'], starting_y, acceleration=9.8)
|
||||
throw['distance'] = throw['hang_time'] * throw['horizontal_component']
|
||||
|
||||
def parabola(x):
|
||||
# 100% credit goes to wikipedia authors
|
||||
# https://en.wikipedia.org/wiki/Projectile_motion#Parabolic_equation
|
||||
|
@ -56,15 +51,19 @@ def make_throw(starting_x, starting_y, starting_velocity, thrown_angle):
|
|||
y = left - (numerator / denominator)
|
||||
return y
|
||||
|
||||
throw = {'angle': thrown_angle}
|
||||
throw['parabola'] = parabola
|
||||
throw['horizontal_component'] = starting_velocity * cos * -upward
|
||||
throw['vertical_component'] = starting_velocity * sin * upward
|
||||
throw['hang_time'] = time_to_known_distance(throw['vertical_component'], starting_y, acceleration=9.8)
|
||||
throw['distance'] = throw['hang_time'] * throw['horizontal_component']
|
||||
throw['parabola_points'] = []
|
||||
#print(throw['vertical_component'], throw['hang_time'])
|
||||
|
||||
y = 1
|
||||
x = starting_x
|
||||
backwards = (thrown_angle in range(90, 270)) or (thrown_angle in range(-90, -270, -1))
|
||||
while y > 0:
|
||||
y = throw['parabola'](x) + starting_y
|
||||
y = parabola(x) + starting_y
|
||||
if y < 0:
|
||||
# To keep a smooth floor of 0, rescale the active x so that
|
||||
# it looks like it continues in the right direction underground.
|
||||
|
@ -77,7 +76,7 @@ def make_throw(starting_x, starting_y, starting_velocity, thrown_angle):
|
|||
if (smallest_x is None or x < smallest_x): smallest_x = math.floor(x)
|
||||
if (largest_x is None or x > largest_x): largest_x = math.ceil(x)
|
||||
if (largest_y is None or y > largest_y): largest_y = math.ceil(y)
|
||||
throw['parabola_points'].append([int(x), int(y)])
|
||||
throw['parabola_points'].append((int(x), int(y)))
|
||||
if backwards:
|
||||
x -= PLOT_STEP_X
|
||||
else:
|
||||
|
@ -141,12 +140,12 @@ for (index, t) in enumerate(throws):
|
|||
point_a = None
|
||||
for pointindex in range(len(t['parabola_points']) - 1):
|
||||
if point_a is None:
|
||||
point_a = t['parabola_points'][pointindex][:]
|
||||
point_a = list(t['parabola_points'][pointindex])
|
||||
point_a[0] = (round(point_a[0])) + abs(smallest_x) + PLOT_PAD_LEFT
|
||||
point_a[1] = (largest_y - round(point_a[1]))
|
||||
else:
|
||||
point_a = point_b
|
||||
point_b = t['parabola_points'][pointindex + 1][:]
|
||||
point_b = list(t['parabola_points'][pointindex + 1])
|
||||
point_b[0] = (round(point_b[0])) + abs(smallest_x) + PLOT_PAD_LEFT
|
||||
point_b[1] = (largest_y - round(point_b[1]))
|
||||
try:
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:889e3073049ed9d4b0dff0414ab769fbd9cac821177446ef9b5df08d34c8e2f5
|
||||
size 8042
|
||||
oid sha256:67e8ae6342a582acff7c6fa0904f24c5265a0bb666b132cb505dc56728bfedf9
|
||||
size 8054
|
||||
|
|
10
SnudownTest/.gitignore
vendored
Normal file
10
SnudownTest/.gitignore
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
build/
|
||||
dist/
|
||||
snudown.egg-info/
|
||||
src/html_entities.h
|
||||
*.pyc
|
||||
*.so
|
||||
*.so.*
|
||||
*.o
|
||||
/fuzzing/bin
|
||||
/fuzzing/testing
|
4
SnudownTest/.gitmodules
vendored
Normal file
4
SnudownTest/.gitmodules
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
[submodule "gumbo_snudown"]
|
||||
path = fuzzing/gumbo_snudown
|
||||
url = git@github.com:JordanMilne/gumbo-parser.git
|
||||
branch = markdown_validation
|
133
SnudownTest/Python.h
Normal file
133
SnudownTest/Python.h
Normal file
|
@ -0,0 +1,133 @@
|
|||
#ifndef Py_PYTHON_H
|
||||
#define Py_PYTHON_H
|
||||
/* Since this is a "meta-include" file, no #ifdef __cplusplus / extern "C" { */
|
||||
|
||||
/* Include nearly all Python header files */
|
||||
|
||||
#include "patchlevel.h"
|
||||
#include "pyconfig.h"
|
||||
#include "pymacconfig.h"
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#ifndef UCHAR_MAX
|
||||
#error "Something's broken. UCHAR_MAX should be defined in limits.h."
|
||||
#endif
|
||||
|
||||
#if UCHAR_MAX != 255
|
||||
#error "Python's source code assumes C's unsigned char is an 8-bit type."
|
||||
#endif
|
||||
|
||||
#if defined(__sgi) && defined(WITH_THREAD) && !defined(_SGI_MP_SOURCE)
|
||||
#define _SGI_MP_SOURCE
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#ifndef NULL
|
||||
# error "Python.h requires that stdio.h define NULL."
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
/* For size_t? */
|
||||
#ifdef HAVE_STDDEF_H
|
||||
#include <stddef.h>
|
||||
#endif
|
||||
|
||||
/* CAUTION: Build setups should ensure that NDEBUG is defined on the
|
||||
* compiler command line when building Python in release mode; else
|
||||
* assert() calls won't be removed.
|
||||
*/
|
||||
#include <assert.h>
|
||||
|
||||
#include "pyport.h"
|
||||
#include "pymacro.h"
|
||||
|
||||
#include "pyatomic.h"
|
||||
|
||||
/* Debug-mode build with pymalloc implies PYMALLOC_DEBUG.
|
||||
* PYMALLOC_DEBUG is in error if pymalloc is not in use.
|
||||
*/
|
||||
#if defined(Py_DEBUG) && defined(WITH_PYMALLOC) && !defined(PYMALLOC_DEBUG)
|
||||
#define PYMALLOC_DEBUG
|
||||
#endif
|
||||
#if defined(PYMALLOC_DEBUG) && !defined(WITH_PYMALLOC)
|
||||
#error "PYMALLOC_DEBUG requires WITH_PYMALLOC"
|
||||
#endif
|
||||
#include "pymath.h"
|
||||
#include "pytime.h"
|
||||
#include "pymem.h"
|
||||
|
||||
#include "object.h"
|
||||
#include "objimpl.h"
|
||||
#include "typeslots.h"
|
||||
#include "pyhash.h"
|
||||
|
||||
#include "pydebug.h"
|
||||
|
||||
#include "bytearrayobject.h"
|
||||
#include "bytesobject.h"
|
||||
#include "unicodeobject.h"
|
||||
#include "longobject.h"
|
||||
#include "longintrepr.h"
|
||||
#include "boolobject.h"
|
||||
#include "floatobject.h"
|
||||
#include "complexobject.h"
|
||||
#include "rangeobject.h"
|
||||
#include "memoryobject.h"
|
||||
#include "tupleobject.h"
|
||||
#include "listobject.h"
|
||||
#include "dictobject.h"
|
||||
#include "enumobject.h"
|
||||
#include "setobject.h"
|
||||
#include "methodobject.h"
|
||||
#include "moduleobject.h"
|
||||
#include "funcobject.h"
|
||||
#include "classobject.h"
|
||||
#include "fileobject.h"
|
||||
#include "pycapsule.h"
|
||||
#include "traceback.h"
|
||||
#include "sliceobject.h"
|
||||
#include "cellobject.h"
|
||||
#include "iterobject.h"
|
||||
#include "genobject.h"
|
||||
#include "descrobject.h"
|
||||
#include "warnings.h"
|
||||
#include "weakrefobject.h"
|
||||
#include "structseq.h"
|
||||
#include "namespaceobject.h"
|
||||
|
||||
#include "codecs.h"
|
||||
#include "pyerrors.h"
|
||||
|
||||
#include "pystate.h"
|
||||
|
||||
#include "pyarena.h"
|
||||
#include "modsupport.h"
|
||||
#include "pythonrun.h"
|
||||
#include "ceval.h"
|
||||
#include "sysmodule.h"
|
||||
#include "intrcheck.h"
|
||||
#include "import.h"
|
||||
|
||||
#include "abstract.h"
|
||||
#include "bltinmodule.h"
|
||||
|
||||
#include "compile.h"
|
||||
#include "eval.h"
|
||||
|
||||
#include "pyctype.h"
|
||||
#include "pystrtod.h"
|
||||
#include "pystrcmp.h"
|
||||
#include "dtoa.h"
|
||||
#include "fileutils.h"
|
||||
#include "pyfpe.h"
|
||||
|
||||
#endif /* !Py_PYTHON_H */
|
12
SnudownTest/SECURITY.md
Normal file
12
SnudownTest/SECURITY.md
Normal file
|
@ -0,0 +1,12 @@
|
|||
For safety reasons, whenever you add or change something in Snudown,
|
||||
you should add a few test-cases that demonstrate your change and do a
|
||||
fuzzing run in `/fuzzing` by running `make afl`. Make sure you have `cmake`
|
||||
installed and in your `PATH`!
|
||||
|
||||
This uses [American Fuzzy Lop](http://lcamtuf.coredump.cx/afl/) and a
|
||||
modified [Google Gumbo](https://github.com/google/gumbo-parser/) to ensure
|
||||
there is no way to generate invalid HTML, and that there are no unsafe
|
||||
memory operations.
|
||||
|
||||
See [American Fuzzy Lop](http://lcamtuf.coredump.cx/afl/)'s instructions
|
||||
for your platform to get started.
|
487
SnudownTest/autolink.c
Normal file
487
SnudownTest/autolink.c
Normal file
|
@ -0,0 +1,487 @@
|
|||
/*
|
||||
* 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 "autolink.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define strncasecmp _strnicmp
|
||||
#endif
|
||||
|
||||
int
|
||||
sd_autolink_issafe(const uint8_t *link, size_t link_len)
|
||||
{
|
||||
static const size_t valid_uris_count = 14;
|
||||
static const char *valid_uris[] = {
|
||||
"http://", "https://", "ftp://", "mailto://",
|
||||
"/", "git://", "steam://", "irc://", "news://", "mumble://",
|
||||
"ssh://", "ircs://", "ts3server://", "#"
|
||||
};
|
||||
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < valid_uris_count; ++i) {
|
||||
size_t len = strlen(valid_uris[i]);
|
||||
|
||||
if (link_len > len &&
|
||||
strncasecmp((char *)link, valid_uris[i], len) == 0 &&
|
||||
(isalnum(link[len]) || link[len] == '#' || link[len] == '/' || link[len] == '?'))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static size_t
|
||||
autolink_delim(uint8_t *data, size_t link_end, size_t max_rewind, size_t size)
|
||||
{
|
||||
uint8_t cclose, copen = 0;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < link_end; ++i)
|
||||
if (data[i] == '<') {
|
||||
link_end = i;
|
||||
break;
|
||||
}
|
||||
|
||||
while (link_end > 0) {
|
||||
uint8_t c = data[link_end - 1];
|
||||
|
||||
if (c == 0)
|
||||
break;
|
||||
|
||||
if (strchr("?!.,", c) != NULL)
|
||||
link_end--;
|
||||
|
||||
else if (c == ';') {
|
||||
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 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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks that `prefix_char` occurs on a word boundary just before `data`,
|
||||
* where `data` points to the character to search to the left of, and a word boundary
|
||||
* is (currently) a whitespace character, punctuation, or the start of the string.
|
||||
* Returns the length of the prefix.
|
||||
*/
|
||||
static int
|
||||
check_reddit_autolink_prefix(
|
||||
const uint8_t* data,
|
||||
size_t max_rewind,
|
||||
size_t max_lookbehind,
|
||||
size_t size,
|
||||
char prefix_char
|
||||
)
|
||||
{
|
||||
/* Make sure this `/` is part of `/?r/` */
|
||||
if (size < 2 || max_rewind < 1 || data[-1] != prefix_char)
|
||||
return 0;
|
||||
|
||||
/* Not at the start of the buffer, no inlines to the immediate left of the `prefix_char` */
|
||||
if (max_rewind > 1) {
|
||||
const char boundary = data[-2];
|
||||
if (boundary == '/')
|
||||
return 2;
|
||||
/**
|
||||
* Here's where our lack of unicode-awareness bites us. We don't correctly
|
||||
* match punctuation / whitespace characters for the boundary, because we
|
||||
* reject valid cases like "。r/example" (note the fullwidth period.)
|
||||
*
|
||||
* A better implementation might try to rewind over bytes with the 8th bit set, try
|
||||
* to decode them to a valid codepoint, then do a unicode-aware check on the codepoint.
|
||||
*/
|
||||
else if (ispunct(boundary) || isspace(boundary))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
} else if (max_lookbehind > 2) {
|
||||
/* There's an inline element just left of the `prefix_char`, is it an escaped forward
|
||||
* slash? bail out so we correctly handle stuff like "\/r/foo". This will also correctly
|
||||
* allow "\\/r/foo".
|
||||
*/
|
||||
if (data[-2] == '/' && data[-3] == '\\')
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Must be a new-style shortlink with nothing relevant to the left of it. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static size_t
|
||||
check_domain(uint8_t *data, size_t size, int allow_short)
|
||||
{
|
||||
size_t i, np = 0;
|
||||
|
||||
if (!isalnum(data[0]))
|
||||
return 0;
|
||||
|
||||
for (i = 1; i < size - 1; ++i) {
|
||||
if (data[i] == '.') np++;
|
||||
else if (!isalnum(data[i]) && data[i] != '-') break;
|
||||
}
|
||||
|
||||
if (allow_short) {
|
||||
/* We don't need a valid domain in the strict sense (with
|
||||
* least one dot; so just make sure it's composed of valid
|
||||
* domain characters and return the length of the the valid
|
||||
* sequence. */
|
||||
return i;
|
||||
} else {
|
||||
/* a valid domain needs to have at least a dot.
|
||||
* that's as far as we get */
|
||||
return np ? i : 0;
|
||||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
sd_autolink__www(
|
||||
size_t *rewind_p,
|
||||
struct buf *link,
|
||||
uint8_t *data,
|
||||
size_t max_rewind,
|
||||
size_t size,
|
||||
unsigned int flags)
|
||||
{
|
||||
size_t link_end;
|
||||
|
||||
if (max_rewind > 0 && !ispunct(data[-1]) && !isspace(data[-1]))
|
||||
return 0;
|
||||
|
||||
if (size < 4 || memcmp(data, "www.", strlen("www.")) != 0)
|
||||
return 0;
|
||||
|
||||
link_end = check_domain(data, size, 0);
|
||||
|
||||
if (link_end == 0)
|
||||
return 0;
|
||||
|
||||
while (link_end < size && !isspace(data[link_end]))
|
||||
link_end++;
|
||||
|
||||
link_end = autolink_delim(data, link_end, max_rewind, size);
|
||||
|
||||
if (link_end == 0)
|
||||
return 0;
|
||||
|
||||
bufput(link, data, link_end);
|
||||
*rewind_p = 0;
|
||||
|
||||
return (int)link_end;
|
||||
}
|
||||
|
||||
size_t
|
||||
sd_autolink__email(
|
||||
size_t *rewind_p,
|
||||
struct buf *link,
|
||||
uint8_t *data,
|
||||
size_t max_rewind,
|
||||
size_t size,
|
||||
unsigned int flags)
|
||||
{
|
||||
size_t link_end, rewind;
|
||||
int nb = 0, np = 0;
|
||||
|
||||
for (rewind = 0; rewind < max_rewind; ++rewind) {
|
||||
uint8_t c = data[-rewind - 1];
|
||||
|
||||
if (c == 0)
|
||||
break;
|
||||
|
||||
if (isalnum(c))
|
||||
continue;
|
||||
|
||||
if (strchr(".+-_", c) != NULL)
|
||||
continue;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (rewind == 0)
|
||||
return 0;
|
||||
|
||||
for (link_end = 0; link_end < size; ++link_end) {
|
||||
uint8_t 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, max_rewind, size);
|
||||
|
||||
if (link_end == 0)
|
||||
return 0;
|
||||
|
||||
bufput(link, data - rewind, link_end + rewind);
|
||||
*rewind_p = rewind;
|
||||
|
||||
return link_end;
|
||||
}
|
||||
|
||||
size_t
|
||||
sd_autolink__url(
|
||||
size_t *rewind_p,
|
||||
struct buf *link,
|
||||
uint8_t *data,
|
||||
size_t max_rewind,
|
||||
size_t size,
|
||||
unsigned int flags)
|
||||
{
|
||||
size_t link_end, rewind = 0, domain_len;
|
||||
|
||||
if (size < 4 || data[1] != '/' || data[2] != '/')
|
||||
return 0;
|
||||
|
||||
while (rewind < max_rewind && isalpha(data[-rewind - 1]))
|
||||
rewind++;
|
||||
|
||||
if (!sd_autolink_issafe(data - rewind, size + rewind))
|
||||
return 0;
|
||||
|
||||
link_end = strlen("://");
|
||||
|
||||
domain_len = check_domain(
|
||||
data + link_end,
|
||||
size - link_end,
|
||||
flags & SD_AUTOLINK_SHORT_DOMAINS);
|
||||
|
||||
if (domain_len == 0)
|
||||
return 0;
|
||||
|
||||
link_end += domain_len;
|
||||
while (link_end < size && !isspace(data[link_end]))
|
||||
link_end++;
|
||||
|
||||
link_end = autolink_delim(data, link_end, max_rewind, size);
|
||||
|
||||
if (link_end == 0)
|
||||
return 0;
|
||||
|
||||
bufput(link, data - rewind, link_end + rewind);
|
||||
*rewind_p = rewind;
|
||||
|
||||
return link_end;
|
||||
}
|
||||
|
||||
size_t
|
||||
sd_autolink__subreddit(
|
||||
size_t *rewind_p,
|
||||
struct buf *link,
|
||||
uint8_t *data,
|
||||
size_t max_rewind,
|
||||
size_t max_lookbehind,
|
||||
size_t size,
|
||||
int *no_slash
|
||||
)
|
||||
{
|
||||
/**
|
||||
* This is meant to handle both r/foo and /r/foo style subreddit references.
|
||||
* In a valid /?r/ link, `*data` will always point to the '/' after the first 'r'.
|
||||
* In pseudo-regex, this matches something like:
|
||||
*
|
||||
* `(/|(?<=\b))r/(all-)?%subreddit%([-+]%subreddit%)*(/[\w\-/]*)?`
|
||||
* where %subreddit% == `((t:)?\w{2,24}|reddit\.com)`
|
||||
*/
|
||||
size_t link_end;
|
||||
size_t rewind;
|
||||
int is_allminus = 0;
|
||||
|
||||
rewind = check_reddit_autolink_prefix(data, max_rewind, max_lookbehind, size, 'r');
|
||||
if (!rewind)
|
||||
return 0;
|
||||
|
||||
/* offset to the "meat" of the link */
|
||||
link_end = strlen("/");
|
||||
|
||||
if (size >= link_end + 4 && strncasecmp((char*)data + link_end, "all-", 4) == 0)
|
||||
is_allminus = 1;
|
||||
|
||||
do {
|
||||
size_t start = link_end;
|
||||
int max_length = 24;
|
||||
|
||||
/* special case: /r/reddit.com (only subreddit containing '.'). */
|
||||
if ( size >= link_end+10 && strncasecmp((char*)data+link_end, "reddit.com", 10) == 0 ) {
|
||||
link_end += 10;
|
||||
/* Make sure there are no trailing characters (don't do
|
||||
* any autolinking for /r/reddit.commission) */
|
||||
max_length = 10;
|
||||
}
|
||||
|
||||
/* If not a special case, verify it begins with (t:)?[A-Za-z0-9] */
|
||||
else {
|
||||
/* support autolinking to timereddits, /r/t:when (1 April 2012) */
|
||||
if ( size > link_end+2 && strncasecmp((char*)data+link_end, "t:", 2) == 0 )
|
||||
link_end += 2; /* Jump over the 't:' */
|
||||
|
||||
/* the first character of a subreddit name must be a letter or digit */
|
||||
if (!isalnum(data[link_end]))
|
||||
return 0;
|
||||
link_end += 1;
|
||||
}
|
||||
|
||||
/* consume valid characters ([A-Za-z0-9_]) until we run out */
|
||||
while (link_end < size && (isalnum(data[link_end]) ||
|
||||
data[link_end] == '_'))
|
||||
link_end++;
|
||||
|
||||
/* valid subreddit names are between 3 and 21 characters, with
|
||||
* some subreddits having 2-character names. Don't bother with
|
||||
* autolinking for anything outside this length range.
|
||||
* (chksrname function in reddit/.../validator.py) */
|
||||
if ( link_end-start < 2 || link_end-start > max_length )
|
||||
return 0;
|
||||
|
||||
/* If we are linking to a multireddit, continue */
|
||||
} while ( link_end < size && (data[link_end] == '+' || (is_allminus && data[link_end] == '-')) && link_end++ );
|
||||
|
||||
if (link_end < size && data[link_end] == '/') {
|
||||
while (link_end < size && (isalnum(data[link_end]) ||
|
||||
data[link_end] == '_' ||
|
||||
data[link_end] == '/' ||
|
||||
data[link_end] == '-'))
|
||||
link_end++;
|
||||
}
|
||||
|
||||
/* make the link */
|
||||
bufput(link, data - rewind, link_end + rewind);
|
||||
|
||||
*no_slash = (rewind == 1);
|
||||
*rewind_p = rewind;
|
||||
|
||||
return link_end;
|
||||
}
|
||||
|
||||
size_t
|
||||
sd_autolink__username(
|
||||
size_t *rewind_p,
|
||||
struct buf *link,
|
||||
uint8_t *data,
|
||||
size_t max_rewind,
|
||||
size_t max_lookbehind,
|
||||
size_t size,
|
||||
int *no_slash
|
||||
)
|
||||
{
|
||||
size_t link_end;
|
||||
size_t rewind;
|
||||
|
||||
if (size < 3)
|
||||
return 0;
|
||||
|
||||
rewind = check_reddit_autolink_prefix(data, max_rewind, max_lookbehind, size, 'u');
|
||||
if (!rewind)
|
||||
return 0;
|
||||
|
||||
link_end = strlen("/");
|
||||
|
||||
/* the first letter of a username must... well, be valid, we don't care otherwise */
|
||||
if (!isalnum(data[link_end]) && data[link_end] != '_' && data[link_end] != '-')
|
||||
return 0;
|
||||
link_end += 1;
|
||||
|
||||
/* consume valid characters ([A-Za-z0-9_-/]) until we run out */
|
||||
while (link_end < size && (isalnum(data[link_end]) ||
|
||||
data[link_end] == '_' ||
|
||||
data[link_end] == '/' ||
|
||||
data[link_end] == '-'))
|
||||
link_end++;
|
||||
|
||||
/* make the link */
|
||||
bufput(link, data - rewind, link_end + rewind);
|
||||
|
||||
*no_slash = (rewind == 1);
|
||||
*rewind_p = rewind;
|
||||
|
||||
return link_end;
|
||||
}
|
59
SnudownTest/autolink.h
Normal file
59
SnudownTest/autolink.h
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* 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
|
||||
|
||||
#include "buffer.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum {
|
||||
SD_AUTOLINK_SHORT_DOMAINS = (1 << 0),
|
||||
};
|
||||
|
||||
int
|
||||
sd_autolink_issafe(const uint8_t *link, size_t link_len);
|
||||
|
||||
size_t
|
||||
sd_autolink__www(size_t *rewind_p, struct buf *link,
|
||||
uint8_t *data, size_t max_rewind, size_t size, unsigned int flags);
|
||||
|
||||
size_t
|
||||
sd_autolink__email(size_t *rewind_p, struct buf *link,
|
||||
uint8_t *data, size_t max_rewind, size_t size, unsigned int flags);
|
||||
|
||||
size_t
|
||||
sd_autolink__url(size_t *rewind_p, struct buf *link,
|
||||
uint8_t *data, size_t max_rewind, size_t size, unsigned int flags);
|
||||
|
||||
extern size_t
|
||||
sd_autolink__subreddit(size_t *rewind_p, struct buf *link, uint8_t *data,
|
||||
size_t max_rewind, size_t max_lookbehind, size_t size, int *no_slash);
|
||||
|
||||
extern size_t
|
||||
sd_autolink__username(size_t *rewind_p, struct buf *link, uint8_t *data,
|
||||
size_t max_rewind, size_t max_lookbehind, size_t size, int *no_slash);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* vim: set filetype=c: */
|
236
SnudownTest/buffer.c
Normal file
236
SnudownTest/buffer.c
Normal file
|
@ -0,0 +1,236 @@
|
|||
/*
|
||||
* Copyright (c) 2008, Natacha Porté
|
||||
* Copyright (c) 2011, Vicent Martí
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define BUFFER_MAX_ALLOC_SIZE (1024 * 1024 * 16) //16mb
|
||||
|
||||
#include "buffer.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
/* MSVC compat */
|
||||
#if defined(_MSC_VER)
|
||||
# define _buf_vsnprintf _vsnprintf
|
||||
#else
|
||||
# define _buf_vsnprintf vsnprintf
|
||||
#endif
|
||||
|
||||
int
|
||||
bufprefix(const struct buf *buf, const char *prefix)
|
||||
{
|
||||
size_t i;
|
||||
assert(buf && buf->unit);
|
||||
|
||||
for (i = 0; i < buf->size; ++i) {
|
||||
if (prefix[i] == 0)
|
||||
return 0;
|
||||
|
||||
if (buf->data[i] != prefix[i])
|
||||
return buf->data[i] - prefix[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* bufgrow: increasing the allocated size to the given value */
|
||||
int
|
||||
bufgrow(struct buf *buf, size_t neosz)
|
||||
{
|
||||
size_t neoasz;
|
||||
void *neodata;
|
||||
|
||||
assert(buf && buf->unit);
|
||||
|
||||
if (neosz > BUFFER_MAX_ALLOC_SIZE)
|
||||
return BUF_ENOMEM;
|
||||
|
||||
if (buf->asize >= neosz)
|
||||
return BUF_OK;
|
||||
|
||||
neoasz = buf->asize + buf->unit;
|
||||
while (neoasz < neosz)
|
||||
neoasz += buf->unit;
|
||||
|
||||
neodata = realloc(buf->data, neoasz);
|
||||
if (!neodata)
|
||||
return BUF_ENOMEM;
|
||||
|
||||
buf->data = neodata;
|
||||
buf->asize = neoasz;
|
||||
return BUF_OK;
|
||||
}
|
||||
|
||||
|
||||
/* bufnew: allocation of a new buffer */
|
||||
struct buf *
|
||||
bufnew(size_t unit)
|
||||
{
|
||||
struct buf *ret;
|
||||
ret = malloc(sizeof (struct buf));
|
||||
|
||||
if (ret) {
|
||||
ret->data = 0;
|
||||
ret->size = ret->asize = 0;
|
||||
ret->unit = unit;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* bufnullterm: NULL-termination of the string array */
|
||||
const char *
|
||||
bufcstr(struct buf *buf)
|
||||
{
|
||||
assert(buf && buf->unit);
|
||||
|
||||
if (buf->size < buf->asize && buf->data[buf->size] == 0)
|
||||
return (char *)buf->data;
|
||||
|
||||
if (buf->size + 1 <= buf->asize || bufgrow(buf, buf->size + 1) == 0) {
|
||||
buf->data[buf->size] = 0;
|
||||
return (char *)buf->data;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* bufprintf: formatted printing to a buffer */
|
||||
void
|
||||
bufprintf(struct buf *buf, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int n;
|
||||
|
||||
assert(buf && buf->unit);
|
||||
|
||||
if (buf->size >= buf->asize && bufgrow(buf, buf->size + 1) < 0)
|
||||
return;
|
||||
va_start(ap, fmt);
|
||||
n = _buf_vsnprintf((char *)buf->data + buf->size, buf->asize - buf->size, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (n < 0) {
|
||||
#ifdef _MSC_VER
|
||||
va_start(ap, fmt);
|
||||
n = _vscprintf(fmt, ap);
|
||||
va_end(ap);
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
if ((size_t)n >= buf->asize - buf->size) {
|
||||
if (bufgrow(buf, buf->size + n + 1) < 0)
|
||||
return;
|
||||
|
||||
va_start(ap, fmt);
|
||||
n = _buf_vsnprintf((char *)buf->data + buf->size, buf->asize - buf->size, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
if (n < 0)
|
||||
return;
|
||||
|
||||
buf->size += n;
|
||||
}
|
||||
|
||||
/* bufput: appends raw data to a buffer */
|
||||
void
|
||||
bufput(struct buf *buf, const void *data, size_t len)
|
||||
{
|
||||
assert(buf && buf->unit);
|
||||
|
||||
if (buf->size + len > buf->asize && bufgrow(buf, buf->size + len) < 0)
|
||||
return;
|
||||
|
||||
memcpy(buf->data + buf->size, data, len);
|
||||
buf->size += len;
|
||||
}
|
||||
|
||||
/* bufputs: appends a NUL-terminated string to a buffer */
|
||||
void
|
||||
bufputs(struct buf *buf, const char *str)
|
||||
{
|
||||
bufput(buf, str, strlen(str));
|
||||
}
|
||||
|
||||
|
||||
/* bufputc: appends a single uint8_t to a buffer */
|
||||
void
|
||||
bufputc(struct buf *buf, int c)
|
||||
{
|
||||
assert(buf && buf->unit);
|
||||
|
||||
if (buf->size + 1 > buf->asize && bufgrow(buf, buf->size + 1) < 0)
|
||||
return;
|
||||
|
||||
buf->data[buf->size] = c;
|
||||
buf->size += 1;
|
||||
}
|
||||
|
||||
/* bufrelease: decrease the reference count and free the buffer if needed */
|
||||
void
|
||||
bufrelease(struct buf *buf)
|
||||
{
|
||||
if (!buf)
|
||||
return;
|
||||
|
||||
free(buf->data);
|
||||
free(buf);
|
||||
}
|
||||
|
||||
|
||||
/* bufreset: frees internal data of the buffer */
|
||||
void
|
||||
bufreset(struct buf *buf)
|
||||
{
|
||||
if (!buf)
|
||||
return;
|
||||
|
||||
free(buf->data);
|
||||
buf->data = NULL;
|
||||
buf->size = buf->asize = 0;
|
||||
}
|
||||
|
||||
/* bufslurp: removes a given number of bytes from the head of the array */
|
||||
void
|
||||
bufslurp(struct buf *buf, size_t len)
|
||||
{
|
||||
assert(buf && buf->unit);
|
||||
|
||||
if (len >= buf->size) {
|
||||
buf->size = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
buf->size -= len;
|
||||
memmove(buf->data, buf->data + len, buf->size);
|
||||
}
|
||||
|
||||
/* buftrucate: truncates the buffer at `size` */
|
||||
int
|
||||
buftruncate(struct buf *buf, size_t size)
|
||||
{
|
||||
if (buf->size < size || size < 0) {
|
||||
/* bail out in debug mode so we can figure out why this happened */
|
||||
assert(0);
|
||||
return BUF_EINVALIDIDX;
|
||||
}
|
||||
|
||||
buf->size = size;
|
||||
return BUF_OK;
|
||||
}
|
100
SnudownTest/buffer.h
Normal file
100
SnudownTest/buffer.h
Normal file
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* Copyright (c) 2008, Natacha Porté
|
||||
* Copyright (c) 2011, Vicent Martí
|
||||
*
|
||||
* 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 BUFFER_H__
|
||||
#define BUFFER_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define __attribute__(x)
|
||||
#define inline
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
BUF_OK = 0,
|
||||
BUF_ENOMEM = -1,
|
||||
BUF_EINVALIDIDX = -2,
|
||||
} buferror_t;
|
||||
|
||||
/* struct buf: character array buffer */
|
||||
struct buf {
|
||||
uint8_t *data; /* actual character data */
|
||||
size_t size; /* size of the string */
|
||||
size_t asize; /* allocated size (0 = volatile buffer) */
|
||||
size_t unit; /* reallocation unit size (0 = read-only buffer) */
|
||||
};
|
||||
|
||||
/* CONST_BUF: global buffer from a string litteral */
|
||||
#define BUF_STATIC(string) \
|
||||
{ (uint8_t *)string, sizeof string -1, sizeof string, 0, 0 }
|
||||
|
||||
/* VOLATILE_BUF: macro for creating a volatile buffer on the stack */
|
||||
#define BUF_VOLATILE(strname) \
|
||||
{ (uint8_t *)strname, strlen(strname), 0, 0, 0 }
|
||||
|
||||
/* BUFPUTSL: optimized bufputs of a string litteral */
|
||||
#define BUFPUTSL(output, literal) \
|
||||
bufput(output, literal, sizeof literal - 1)
|
||||
|
||||
/* bufgrow: increasing the allocated size to the given value */
|
||||
int bufgrow(struct buf *, size_t);
|
||||
|
||||
/* bufnew: allocation of a new buffer */
|
||||
struct buf *bufnew(size_t) __attribute__ ((malloc));
|
||||
|
||||
/* bufnullterm: NUL-termination of the string array (making a C-string) */
|
||||
const char *bufcstr(struct buf *);
|
||||
|
||||
/* bufprefix: compare the beginning of a buffer with a string */
|
||||
int bufprefix(const struct buf *buf, const char *prefix);
|
||||
|
||||
/* bufput: appends raw data to a buffer */
|
||||
void bufput(struct buf *, const void *, size_t);
|
||||
|
||||
/* bufputs: appends a NUL-terminated string to a buffer */
|
||||
void bufputs(struct buf *, const char *);
|
||||
|
||||
/* bufputc: appends a single char to a buffer */
|
||||
void bufputc(struct buf *, int);
|
||||
|
||||
/* bufrelease: decrease the reference count and free the buffer if needed */
|
||||
void bufrelease(struct buf *);
|
||||
|
||||
/* bufreset: frees internal data of the buffer */
|
||||
void bufreset(struct buf *);
|
||||
|
||||
/* bufslurp: removes a given number of bytes from the head of the array */
|
||||
void bufslurp(struct buf *, size_t);
|
||||
|
||||
/* bufprintf: formatted printing to a buffer */
|
||||
void bufprintf(struct buf *, const char *, ...) __attribute__ ((format (printf, 2, 3)));
|
||||
|
||||
/* buftruncate: truncates the buffer at `size` */
|
||||
int buftruncate(struct buf *buf, size_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
145
SnudownTest/debian/changelog
Normal file
145
SnudownTest/debian/changelog
Normal file
|
@ -0,0 +1,145 @@
|
|||
snudown (1.4.0) unstable; urgency=medium
|
||||
|
||||
* autolink r/subreddit and u/user
|
||||
* security: don't rewind over previous inlines when autolinking
|
||||
* email autolinks re-enabled due to ^
|
||||
* more stringent character entity checks and sanitization
|
||||
* properly handle URLs containing control characters
|
||||
|
||||
-- Jordan Milne <jordan.milne@reddit.com> Mon, 01 Jun 2015 13:04:23 -0700
|
||||
|
||||
snudown (1.3.2) unstable; urgency=medium
|
||||
|
||||
* fix alphanumeric-named entities
|
||||
|
||||
-- Neil Williams <neil@reddit.com> Wed, 25 Feb 2015 13:32:41 -0800
|
||||
|
||||
snudown (1.3.1) unstable; urgency=medium
|
||||
|
||||
* add missing entities to entity whitelist
|
||||
|
||||
-- Neil Williams <neil@reddit.com> Tue, 24 Feb 2015 22:12:29 -0800
|
||||
|
||||
snudown (1.3.0) unstable; urgency=medium
|
||||
|
||||
* validate html entities and escape unrecognized ones
|
||||
|
||||
-- Neil Williams <neil@reddit.com> Tue, 24 Feb 2015 17:55:38 -0800
|
||||
|
||||
snudown (1.2.0) unstable; urgency=medium
|
||||
|
||||
* security: fix rewind issues
|
||||
* email autolinks disabled due to ^
|
||||
* security: fix table header OOM bomb
|
||||
|
||||
-- Neil Williams <neil@reddit.com> Sat, 20 Sep 2014 11:59:34 -0700
|
||||
|
||||
snudown (1.1.6) unstable; urgency=low
|
||||
|
||||
* add ts3server url scheme to whitelist
|
||||
* redo html sanitization for wiki renderer
|
||||
|
||||
-- Neil Williams <neil@reddit.com> Tue, 01 Apr 2014 17:12:50 -0700
|
||||
|
||||
snudown (1.1.5) unstable; urgency=low
|
||||
|
||||
* bring path stuff into user/subreddit autolinking (multis, subpages etc.)
|
||||
* make /u/ autolinking case sensitive
|
||||
|
||||
-- Neil Williams <neil@reddit.com> Wed, 22 May 2013 16:09:31 -0700
|
||||
|
||||
snudown (1.1.4) unstable; urgency=low
|
||||
|
||||
* make /r/ autolinking case sensitive
|
||||
|
||||
-- Neil Williams <neil@reddit.com> Mon, 25 Feb 2013 23:27:10 -0800
|
||||
|
||||
snudown (1.1.3) unstable; urgency=low
|
||||
|
||||
* add support for /r/all-minus
|
||||
|
||||
-- Neil Williams <neil@reddit.com> Tue, 08 Jan 2013 12:55:40 -0800
|
||||
|
||||
snudown (1.1.2) unstable; urgency=low
|
||||
|
||||
* don't close the toc div if there wasn't a toc :(
|
||||
|
||||
-- Neil Williams <neil@reddit.com> Wed, 12 Dec 2012 17:38:05 -0800
|
||||
|
||||
snudown (1.1.1) unstable; urgency=low
|
||||
|
||||
* minor code cleanup
|
||||
* add a div around wiki table of contents for styling purposes
|
||||
|
||||
-- Neil Williams <neil@reddit.com> Wed, 12 Dec 2012 13:47:49 -0800
|
||||
|
||||
snudown (1.1.0) unstable; urgency=low
|
||||
|
||||
* add wiki variant of markdown syntax (allows links, and
|
||||
some raw html)
|
||||
|
||||
-- Neil Williams <neil@reddit.com> Wed, 05 Sep 2012 23:30:34 -0700
|
||||
|
||||
snudown (1.0.7) unstable; urgency=low
|
||||
|
||||
* add python-setuptools to build-depends
|
||||
|
||||
-- Neil Williams <neil@reddit.com> Thu, 09 Aug 2012 14:46:49 -0700
|
||||
|
||||
snudown (1.0.6) unstable; urgency=low
|
||||
|
||||
* made subreddit autolinking more robust thanks to nandhp
|
||||
* cleaned up packaging
|
||||
* merged upstream fixes:
|
||||
* fix blockquotes nested inside paragraphs
|
||||
* improve parsing of continuous list items
|
||||
* fix infinite loop parsing strikethrouhgs
|
||||
|
||||
-- Neil Williams <neil@reddit.com> Thu, 09 Aug 2012 13:06:38 -0700
|
||||
|
||||
snudown (1.0.5) unstable; urgency=low
|
||||
|
||||
* require a space between url and title
|
||||
* merged upstream fixes:
|
||||
* whitespace after tables prevent them from rendering
|
||||
* escape html in contents of tables
|
||||
|
||||
-- Neil Williams <neil@reddit.com> Thu, 23 Feb 2012 08:40:39 -0800
|
||||
|
||||
snudown (1.0.4) unstable; urgency=low
|
||||
|
||||
* change username autolinking to /u/username
|
||||
* properly handle backslash at end of message
|
||||
|
||||
-- Neil Williams <neil@reddit.com> Thu, 26 Jan 2012 18:26:45 -0800
|
||||
|
||||
snudown (1.0.3) unstable; urgency=low
|
||||
|
||||
* ~username auto-linking
|
||||
* make table headers less strict
|
||||
* correctly handle ) in link title text
|
||||
* synced with upstream
|
||||
* code clean-up
|
||||
* utf-8 fixes
|
||||
|
||||
-- Neil Williams <neil@reddit.com> Wed, 18 Jan 2012 15:20:35 -0800
|
||||
|
||||
snudown (1.0.2) unstable; urgency=low
|
||||
|
||||
* synced up with upstream
|
||||
* more safelink relaxation based on community requests
|
||||
* fixed nesting unordered lists within ordered lists and vice versa
|
||||
|
||||
-- Neil Williams <neil@reddit.com> Sat, 19 Nov 2011 17:16:47 -0800
|
||||
|
||||
snudown (1.0.1) unstable; urgency=low
|
||||
|
||||
* new version, new package
|
||||
|
||||
-- Neil Williams <neil@reddit.com> Thu, 17 Nov 2011 14:22:26 -0800
|
||||
|
||||
snudown (1.0.0) unstable; urgency=low
|
||||
|
||||
* source package automatically created by stdeb 0.6.0+git
|
||||
|
||||
-- Neil Williams <neil@reddit.com> Wed, 16 Nov 2011 10:36:53 -0800
|
1
SnudownTest/debian/compat
Normal file
1
SnudownTest/debian/compat
Normal file
|
@ -0,0 +1 @@
|
|||
7
|
15
SnudownTest/debian/control
Normal file
15
SnudownTest/debian/control
Normal file
|
@ -0,0 +1,15 @@
|
|||
Source: snudown
|
||||
Maintainer: Neil Williams <neil@reddit.com>
|
||||
Section: python
|
||||
Priority: optional
|
||||
Build-Depends: python-all-dev (>= 2.6.6-3), debhelper (>= 7), python-setuptools, gperf
|
||||
Standards-Version: 3.9.3
|
||||
Homepage: https://github.com/reddit/snudown
|
||||
Vcs-Git: git://github.com/reddit/snudown.git
|
||||
|
||||
Package: python-snudown
|
||||
Architecture: any
|
||||
Depends: ${misc:Depends}, ${python:Depends}, ${shlibs:Depends}
|
||||
Breaks: ${python:Breaks}
|
||||
Description: reddit's python wrapper and customization of the Sundown Markdown interpreter.
|
||||
|
30
SnudownTest/debian/copyright
Normal file
30
SnudownTest/debian/copyright
Normal file
|
@ -0,0 +1,30 @@
|
|||
Format: http://dep.debian.net/deps/dep5
|
||||
Upstream-Name: snudown
|
||||
Source: https://github.com/reddit/snudown
|
||||
|
||||
Files: *
|
||||
Copyright: 2011-2012 Vicent Marti
|
||||
2011-2012 reddit Inc.
|
||||
License: MIT
|
||||
|
||||
Files: debian/*
|
||||
Copyright: 2011-2012 reddit Inc.
|
||||
License: MIT
|
||||
|
||||
Files: test_snudown.py
|
||||
Copyright: 2011-2012 reddit Inc.
|
||||
License: MIT
|
||||
|
||||
License: MIT
|
||||