mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-06-13 14:33:17 -04:00
Compare commits
18 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ca73ec71d5 | ||
|
|
8b047852f3 | ||
|
|
75e201608b | ||
|
|
c9c448e611 | ||
|
|
35f30e6451 | ||
|
|
7aa880654a | ||
|
|
66ec9fad88 | ||
|
|
382e9a31c5 | ||
|
|
d7742d0312 | ||
|
|
f66a020bba | ||
|
|
8038adedf0 | ||
|
|
4bf60d0fbc | ||
|
|
b18d8aa2f1 | ||
|
|
2eaa7beba1 | ||
|
|
5335cec322 | ||
|
|
f35e60577f | ||
|
|
2d11b36a24 | ||
|
|
ab1660ef62 |
12 changed files with 373 additions and 50 deletions
5
.clangd
Normal file
5
.clangd
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# -*- yaml -*-
|
||||
|
||||
CompileFlags:
|
||||
Add:
|
||||
- -Wno-c2y-extensions
|
||||
51
CHANGELOG.md
51
CHANGELOG.md
|
|
@ -1,5 +1,6 @@
|
|||
# Changelog
|
||||
|
||||
* [Unreleased](#unreleased)
|
||||
* [1.27.0](#1-27-0)
|
||||
* [1.26.1](#1-26-1)
|
||||
* [1.26.0](#1-26-0)
|
||||
|
|
@ -69,6 +70,56 @@
|
|||
* [1.2.0](#1-2-0)
|
||||
|
||||
|
||||
## Unreleased
|
||||
### Added
|
||||
### Changed
|
||||
|
||||
* Do not allow codepoints to be merged into grapheme clusters directly
|
||||
after a cursor move ([#2383][2383]).
|
||||
* Dracula theme updated to latest official, and light theme alucard
|
||||
added.
|
||||
* Sixels: pan/pad clamped to 5 ([#2371][2371]).
|
||||
|
||||
[2383]: https://codeberg.org/dnkl/foot/issues/2383
|
||||
[2371]: https://codeberg.org/dnkl/foot/issues/2371
|
||||
|
||||
|
||||
### Deprecated
|
||||
### Removed
|
||||
### Fixed
|
||||
|
||||
* Out-of-bounds read when parsing URIs with malformed %-encoded
|
||||
content ([#2353][2353]).
|
||||
* DECCRA not clamping or verifying the destination rectangle
|
||||
([#2352][2352]).
|
||||
* Empty selection clearing the clipboard ([#2327][2327]).
|
||||
* Require xkbcommon >= 1.6.0. This has been the case for a while, due
|
||||
to our use of `XKB_KEYSYM_MAX`. Now it is formalized in
|
||||
`meson.build` ([#2379][2379]).
|
||||
* Block selection area incorrectly updated when selecting back
|
||||
across the starting column.
|
||||
* Passing a very large value as CHT/CBT argument hangs the terminal
|
||||
([#2360][2360]).
|
||||
* Sixel: crash when using a shared palette and gamma-correct blending
|
||||
has been enabled, or foot is using 10-bit surface ([#2370][2370]).
|
||||
* Kitty text-size protocol: fix crash when text is zero-length
|
||||
([#2364][2364]).
|
||||
* Escape quotes in file names being DnD:ed on the command line
|
||||
([#2363][2363]).
|
||||
|
||||
[2353]: https://codeberg.org/dnkl/foot/issues/2353
|
||||
[2352]: https://codeberg.org/dnkl/foot/issues/2352
|
||||
[2327]: https://codeberg.org/dnkl/foot/issues/2327
|
||||
[2379]: https://codeberg.org/dnkl/foot/issues/2379
|
||||
[2360]: https://codeberg.org/dnkl/foot/issues/2360
|
||||
[2370]: https://codeberg.org/dnkl/foot/issues/2370
|
||||
[2364]: https://codeberg.org/dnkl/foot/issues/2364
|
||||
|
||||
|
||||
### Security
|
||||
### Contributors
|
||||
|
||||
|
||||
## 1.27.0
|
||||
|
||||
### Added
|
||||
|
|
|
|||
42
csi.c
42
csi.c
|
|
@ -774,7 +774,7 @@ params_to_rectangular_area(const struct terminal *term, int first_idx,
|
|||
int rel_bottom = vt_param_get(term, first_idx + 2, term->rows) - 1;
|
||||
*right = min(vt_param_get(term, first_idx + 3, term->cols) - 1, term->cols - 1);
|
||||
|
||||
if (rel_top > rel_bottom || *left > *right)
|
||||
if (unlikely(rel_top > rel_bottom || *left > *right))
|
||||
return false;
|
||||
|
||||
*top = term_row_rel_to_abs(term, rel_top);
|
||||
|
|
@ -1171,37 +1171,40 @@ csi_dispatch(struct terminal *term, uint8_t final)
|
|||
|
||||
case 'I': {
|
||||
/* CHT - Tab Forward (param is number of tab stops to move through) */
|
||||
for (int i = 0; i < vt_param_get(term, 0, 1); i++) {
|
||||
int new_col = term->cols - 1;
|
||||
int count = vt_param_get(term, 0, 1);
|
||||
int new_col = term->grid->cursor.point.col;
|
||||
tll_foreach(term->tab_stops, it) {
|
||||
if (it->item > term->grid->cursor.point.col) {
|
||||
new_col = it->item;
|
||||
if (it->item > new_col) {
|
||||
if (--count < 0) {
|
||||
break;
|
||||
}
|
||||
new_col = it->item;
|
||||
}
|
||||
}
|
||||
xassert(new_col >= term->grid->cursor.point.col);
|
||||
|
||||
bool lcf = term->grid->cursor.lcf;
|
||||
term_cursor_right(term, new_col - term->grid->cursor.point.col);
|
||||
term->grid->cursor.lcf = lcf;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'Z':
|
||||
case 'Z': {
|
||||
/* CBT - Back tab (param is number of tab stops to move back through) */
|
||||
for (int i = 0; i < vt_param_get(term, 0, 1); i++) {
|
||||
int new_col = 0;
|
||||
int count = vt_param_get(term, 0, 1);
|
||||
int new_col = term->grid->cursor.point.col;
|
||||
tll_rforeach(term->tab_stops, it) {
|
||||
if (it->item < term->grid->cursor.point.col) {
|
||||
new_col = it->item;
|
||||
if (it->item < new_col) {
|
||||
if (--count < 0) {
|
||||
break;
|
||||
}
|
||||
new_col = it->item;
|
||||
}
|
||||
}
|
||||
xassert(term->grid->cursor.point.col >= new_col);
|
||||
term_cursor_left(term, term->grid->cursor.point.col - new_col);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'h':
|
||||
case 'l': {
|
||||
|
|
@ -2005,9 +2008,8 @@ csi_dispatch(struct terminal *term, uint8_t final)
|
|||
}
|
||||
|
||||
int src_page = vt_param_get(term, 4, 1);
|
||||
|
||||
int dst_rel_top = vt_param_get(term, 5, 1) - 1;
|
||||
int dst_left = vt_param_get(term, 6, 1) - 1;
|
||||
int dst_left = min(vt_param_get(term, 6, 1) - 1, term->cols - 1);
|
||||
int dst_page = vt_param_get(term, 7, 1);
|
||||
|
||||
if (unlikely(src_page != 1 || dst_page != 1)) {
|
||||
|
|
@ -2021,6 +2023,18 @@ csi_dispatch(struct terminal *term, uint8_t final)
|
|||
int dst_top = term_row_rel_to_abs(term, dst_rel_top);
|
||||
int dst_bottom = term_row_rel_to_abs(term, dst_rel_bottom);
|
||||
|
||||
if (unlikely(dst_left > dst_right || dst_top > dst_bottom))
|
||||
break;
|
||||
|
||||
/*
|
||||
* src validated by params_to_rectangular_area()
|
||||
* dst validated above
|
||||
*/
|
||||
xassert(src_bottom - src_top >= 0);
|
||||
xassert(dst_bottom - dst_top >= 0);
|
||||
xassert(src_right - src_left >= 0);
|
||||
xassert(dst_right - dst_left >= 0);
|
||||
|
||||
/* Target area outside the screen is clipped */
|
||||
const size_t row_count = min(src_bottom - src_top,
|
||||
dst_bottom - dst_top) + 1;
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ wayland_protocols = dependency('wayland-protocols', version: '>=1.41',
|
|||
default_options: ['tests=false'])
|
||||
wayland_client = dependency('wayland-client')
|
||||
wayland_cursor = dependency('wayland-cursor')
|
||||
xkb = dependency('xkbcommon', version: '>=1.0.0')
|
||||
xkb = dependency('xkbcommon', version: '>=1.6.0')
|
||||
fontconfig = dependency('fontconfig')
|
||||
utf8proc = dependency('libutf8proc', required: get_option('grapheme-clustering'))
|
||||
|
||||
|
|
|
|||
3
osc.c
3
osc.c
|
|
@ -1149,6 +1149,9 @@ kitty_text_size(struct terminal *term, char *string)
|
|||
*text = '\0';
|
||||
text++;
|
||||
|
||||
if (text[0] == '\0')
|
||||
return;
|
||||
|
||||
char32_t *wchars = ambstoc32(text);
|
||||
if (wchars == NULL)
|
||||
return;
|
||||
|
|
|
|||
19
selection.c
19
selection.c
|
|
@ -1145,7 +1145,7 @@ selection_update(struct terminal *term, int col, int row)
|
|||
struct coord *pivot_end = &term->selection.pivot.end;
|
||||
|
||||
if (term->selection.kind == SELECTION_BLOCK) {
|
||||
if (new_end.col > pivot_start->col)
|
||||
if (new_end.col >= pivot_start->col)
|
||||
new_direction = SELECTION_RIGHT;
|
||||
else
|
||||
new_direction = SELECTION_LEFT;
|
||||
|
|
@ -1948,6 +1948,9 @@ static const struct zwp_primary_selection_source_v1_listener primary_selection_s
|
|||
bool
|
||||
text_to_clipboard(struct seat *seat, struct terminal *term, char *text, uint32_t serial)
|
||||
{
|
||||
if (text == NULL || text[0] == '\0')
|
||||
return false;
|
||||
|
||||
xassert(serial != 0);
|
||||
|
||||
struct wl_clipboard *clipboard = &seat->clipboard;
|
||||
|
|
@ -2095,7 +2098,16 @@ decode_one_uri(struct clipboard_receive *ctx, char *uri, size_t len)
|
|||
if (ctx->quote_paths)
|
||||
ctx->cb("'", 1, ctx->user);
|
||||
|
||||
ctx->cb(path, strlen(path), ctx->user);
|
||||
char *path_remaining = path;
|
||||
for (char *next_quote = strchr(path_remaining, '\'');
|
||||
next_quote != NULL;
|
||||
path_remaining = next_quote + 1,
|
||||
next_quote = strchr(path_remaining, '\''))
|
||||
{
|
||||
ctx->cb(path_remaining, next_quote - path_remaining, ctx->user);
|
||||
ctx->cb("\\'", 2, ctx->user);
|
||||
}
|
||||
ctx->cb(path_remaining, strlen(path_remaining), ctx->user);
|
||||
|
||||
if (ctx->quote_paths)
|
||||
ctx->cb("'", 1, ctx->user);
|
||||
|
|
@ -2418,6 +2430,9 @@ selection_from_clipboard(struct seat *seat, struct terminal *term, uint32_t seri
|
|||
bool
|
||||
text_to_primary(struct seat *seat, struct terminal *term, char *text, uint32_t serial)
|
||||
{
|
||||
if (text == NULL || text[0] == '\0')
|
||||
return false;
|
||||
|
||||
if (term->wl->primary_selection_device_manager == NULL)
|
||||
return false;
|
||||
|
||||
|
|
|
|||
12
sixel.c
12
sixel.c
|
|
@ -169,10 +169,10 @@ sixel_init(struct terminal *term, int p1, int p2, int p3)
|
|||
|
||||
if (term->sixel.linear_blending || term->sixel.use_10bit) {
|
||||
for (size_t i = 0; i < active_palette_entries; i++) {
|
||||
uint8_t r = (term->sixel.private_palette[i] >> 16) & 0xff;
|
||||
uint8_t g = (term->sixel.private_palette[i] >> 8) & 0xff;
|
||||
uint8_t b = (term->sixel.private_palette[i] >> 0) & 0xff;
|
||||
term->sixel.private_palette[i] = color_decode_srgb(term, r, g, b);
|
||||
uint8_t r = (term->sixel.shared_palette[i] >> 16) & 0xff;
|
||||
uint8_t g = (term->sixel.shared_palette[i] >> 8) & 0xff;
|
||||
uint8_t b = (term->sixel.shared_palette[i] >> 0) & 0xff;
|
||||
term->sixel.shared_palette[i] = color_decode_srgb(term, r, g, b);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -1888,8 +1888,8 @@ decgra(struct terminal *term, uint8_t c)
|
|||
unsigned ph = nparams > 2 ? term->sixel.params[2] : 0;
|
||||
unsigned pv = nparams > 3 ? term->sixel.params[3] : 0;
|
||||
|
||||
pan = pan > 0 ? pan : 1;
|
||||
pad = pad > 0 ? pad : 1;
|
||||
pan = pan > 0 ? min(pan, 5) : 1;
|
||||
pad = pad > 0 ? min(pad, 5) : 1;
|
||||
|
||||
if (likely(term->sixel.image.width == 0 &&
|
||||
term->sixel.image.height == 0))
|
||||
|
|
|
|||
13
terminal.c
13
terminal.c
|
|
@ -4086,6 +4086,10 @@ term_print(struct terminal *term, char32_t wc, int width, bool insert_mode_disab
|
|||
xassert(!grid->cursor.lcf);
|
||||
|
||||
grid->cursor.point.col = col;
|
||||
|
||||
#if defined(FOOT_GRAPHEME_CLUSTERING)
|
||||
term->vt.codepoint_merging_ok = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -4126,6 +4130,9 @@ ascii_printer_fast(struct terminal *term, char32_t wc)
|
|||
xassert(!grid->cursor.lcf);
|
||||
|
||||
grid->cursor.point.col = col;
|
||||
#if defined(FOOT_GRAPHEME_CLUSTERING)
|
||||
term->vt.codepoint_merging_ok = true;
|
||||
#endif
|
||||
|
||||
if (unlikely(row->extra != NULL)) {
|
||||
grid_row_uri_range_erase(row, uri_start, uri_start);
|
||||
|
|
@ -4210,7 +4217,11 @@ term_process_and_print_non_ascii(struct terminal *term, char32_t wc)
|
|||
{
|
||||
int width = c32width(wc);
|
||||
bool insert_mode_disable = false;
|
||||
const bool grapheme_clustering = term->grapheme_shaping;
|
||||
const bool grapheme_clustering = term->grapheme_shaping
|
||||
#if defined(FOOT_GRAPHEME_CLUSTERING)
|
||||
&& term->vt.codepoint_merging_ok
|
||||
#endif
|
||||
;
|
||||
|
||||
#if !defined(FOOT_GRAPHEME_CLUSTERING)
|
||||
xassert(!grapheme_clustering);
|
||||
|
|
|
|||
|
|
@ -264,6 +264,7 @@ struct vt {
|
|||
char32_t last_printed;
|
||||
#if defined(FOOT_GRAPHEME_CLUSTERING)
|
||||
utf8proc_int32_t grapheme_state;
|
||||
bool codepoint_merging_ok;
|
||||
#endif
|
||||
char32_t utf8;
|
||||
struct {
|
||||
|
|
@ -994,5 +995,6 @@ static inline void term_reset_grapheme_state(struct terminal *term)
|
|||
{
|
||||
#if defined(FOOT_GRAPHEME_CLUSTERING)
|
||||
term->vt.grapheme_state = 0;
|
||||
term->vt.codepoint_merging_ok = false;
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
26
themes/ayu-dark
Normal file
26
themes/ayu-dark
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
# -*- conf -*-
|
||||
# theme: Ayu Dark
|
||||
# upstream: https://github.com/ayu-theme/ayu-colors/blob/master/themes/dark.yaml
|
||||
|
||||
[colors-dark]
|
||||
background=0d1017
|
||||
foreground=bfbdb6
|
||||
cursor=0d1017 ffb454
|
||||
|
||||
regular0=0a0000 # black
|
||||
regular1=d75b63 # red
|
||||
regular2=94c230 # green
|
||||
regular3=e79e3a # yellow
|
||||
regular4=40abe7 # blue
|
||||
regular5=bc90e7 # magenta
|
||||
regular6=7ecfb5 # cyan
|
||||
regular7=ffffff # white
|
||||
|
||||
bright0=0a0000 # bright black
|
||||
bright1=f07178 # bright red
|
||||
bright2=aad94c # bright green
|
||||
bright3=ffb454 # bright yellow
|
||||
bright4=59c2ff # bright blue
|
||||
bright5=d2a6ff # bright magenta
|
||||
bright6=95e6cb # bright cyan
|
||||
bright7=ffffff # bright white
|
||||
|
|
@ -1,23 +1,43 @@
|
|||
# -*- conf -*-
|
||||
# Dracula
|
||||
# Dracula / Alucard
|
||||
# Source: https://github.com/dracula/foot
|
||||
|
||||
[colors-dark]
|
||||
cursor=282a36 f8f8f2
|
||||
foreground=f8f8f2
|
||||
background=282a36
|
||||
regular0=000000 # black
|
||||
regular0=21222c # black
|
||||
regular1=ff5555 # red
|
||||
regular2=50fa7b # green
|
||||
regular3=f1fa8c # yellow
|
||||
regular4=bd93f9 # blue
|
||||
regular5=ff79c6 # magenta
|
||||
regular6=8be9fd # cyan
|
||||
regular7=bfbfbf # white
|
||||
bright0=4d4d4d # bright black
|
||||
bright1=ff6e67 # bright red
|
||||
bright2=5af78e # bright green
|
||||
bright3=f4f99d # bright yellow
|
||||
bright4=caa9fa # bright blue
|
||||
bright5=ff92d0 # bright magenta
|
||||
bright6=9aedfe # bright cyan
|
||||
bright7=e6e6e6 # bright white
|
||||
regular7=f8f8f2 # white
|
||||
bright0=6272a4 # bright black
|
||||
bright1=ff6e6e # bright red
|
||||
bright2=69ff94 # bright green
|
||||
bright3=ffffa5 # bright yellow
|
||||
bright4=d6acff # bright blue
|
||||
bright5=ff92df # bright magenta
|
||||
bright6=a4ffff # bright cyan
|
||||
bright7=ffffff # bright white
|
||||
|
||||
[colors-light]
|
||||
foreground=1f1f1f
|
||||
background=fffbeb
|
||||
regular0=fffbeb # white
|
||||
regular1=cb3a2a # red
|
||||
regular2=14710a # green
|
||||
regular3=846e15 # yellow
|
||||
regular4=644ac9 # blue
|
||||
regular5=a3144d # magenta
|
||||
regular6=036a96 # cyan
|
||||
regular7=1f1f1f # white
|
||||
bright0=6c664b # bright black
|
||||
bright1=d74c3d # bright red
|
||||
bright2=198d0c # bright green
|
||||
bright3=9e841a # bright yellow
|
||||
bright4=7862d0 # bright blue
|
||||
bright5=bf185a # bright magenta
|
||||
bright6=047fb4 # bright cyan
|
||||
bright7=2c2b31 # bright white
|
||||
|
|
|
|||
178
uri.c
178
uri.c
|
|
@ -195,7 +195,9 @@ uri_parse(const char *uri, size_t len,
|
|||
encoded_len -= prefix_len;
|
||||
decoded_len += prefix_len;
|
||||
|
||||
if (hex2nibble(next[1]) <= 15 && hex2nibble(next[2]) <= 15) {
|
||||
if (encoded_len >= 3 &&
|
||||
hex2nibble(next[1]) <= 15 && hex2nibble(next[2]) <= 15)
|
||||
{
|
||||
*p++ = hex2nibble(next[1]) << 4 | hex2nibble(next[2]);
|
||||
decoded_len++;
|
||||
encoded_len -= 3;
|
||||
|
|
@ -269,3 +271,177 @@ hostname_is_localhost(const char *hostname)
|
|||
streq(hostname, "localhost") ||
|
||||
streq(hostname, this_host)));
|
||||
}
|
||||
|
||||
UNITTEST
|
||||
{
|
||||
/* Valid URI, all components */
|
||||
const char uri[] = "http://john:wick@www.foobar.com:80/this/is/the%20path?query1=abc&query2=def#fragment";
|
||||
|
||||
char *scheme, *user, *password, *host, *path, *query, *fragment;
|
||||
uint16_t port = 0;
|
||||
|
||||
uri_parse(
|
||||
uri, sizeof(uri) - 1, &scheme, &user, &password, &host, &port, &path,
|
||||
&query, &fragment);
|
||||
xassert(streq(scheme, "http")); free(scheme);
|
||||
xassert(streq(user, "john")); free(user);
|
||||
xassert(streq(password, "wick")); free(password);
|
||||
xassert(streq(host, "www.foobar.com")); free(host);
|
||||
xassert(port == 80);
|
||||
xassert(streq(path, "/this/is/the path")); free(path);
|
||||
xassert(streq(query, "query1=abc&query2=def")); free(query);
|
||||
xassert(streq(fragment, "fragment")); free(fragment);
|
||||
}
|
||||
|
||||
UNITTEST
|
||||
{
|
||||
/* Valid URI, all components. Using file scheme, so query+fragment is treated as part of the path */
|
||||
const char uri[] = "file://john:wick@www.foobar.com:80/this/is/the%20path?query1=abc&query2=def#fragment";
|
||||
|
||||
char *scheme, *user, *password, *host, *path, *query, *fragment;
|
||||
uint16_t port = 0;
|
||||
|
||||
uri_parse(
|
||||
uri, sizeof(uri) - 1, &scheme, &user, &password, &host, &port, &path,
|
||||
&query, &fragment);
|
||||
xassert(streq(scheme, "file")); free(scheme);
|
||||
xassert(streq(user, "john")); free(user);
|
||||
xassert(streq(password, "wick")); free(password);
|
||||
xassert(streq(host, "www.foobar.com")); free(host);
|
||||
xassert(port == 80);
|
||||
xassert(streq(path, "/this/is/the path?query1=abc&query2=def#fragment")); free(path);
|
||||
xassert(query == NULL);
|
||||
xassert(fragment == NULL);
|
||||
}
|
||||
|
||||
UNITTEST
|
||||
{
|
||||
/* Test a valid URI containing all components, except password */
|
||||
const char uri[] = "http://john@www.foobar.com:80/this/is/the%20path?query1=abc&query2=def#fragment";
|
||||
|
||||
char *scheme, *user, *password, *host, *path, *query, *fragment;
|
||||
uint16_t port = 0;
|
||||
|
||||
uri_parse(
|
||||
uri, sizeof(uri) - 1, &scheme, &user, &password, &host, &port, &path,
|
||||
&query, &fragment);
|
||||
xassert(streq(scheme, "http")); free(scheme);
|
||||
xassert(streq(user, "john")); free(user);
|
||||
xassert(password == NULL);
|
||||
xassert(streq(host, "www.foobar.com")); free(host);
|
||||
xassert(port == 80);
|
||||
xassert(streq(path, "/this/is/the path")); free(path);
|
||||
xassert(streq(query, "query1=abc&query2=def")); free(query);
|
||||
xassert(streq(fragment, "fragment")); free(fragment);
|
||||
}
|
||||
|
||||
UNITTEST
|
||||
{
|
||||
/* Valid URI, all components, except user+password */
|
||||
const char uri[] = "http://www.foobar.com:80/this/is/the%20path?query1=abc&query2=def#fragment";
|
||||
|
||||
char *scheme, *user, *password, *host, *path, *query, *fragment;
|
||||
uint16_t port = 0;
|
||||
|
||||
uri_parse(
|
||||
uri, sizeof(uri) - 1, &scheme, &user, &password, &host, &port, &path,
|
||||
&query, &fragment);
|
||||
xassert(streq(scheme, "http")); free(scheme);
|
||||
xassert(user == NULL);
|
||||
xassert(password == NULL);
|
||||
xassert(streq(host, "www.foobar.com")); free(host);
|
||||
xassert(port == 80);
|
||||
xassert(streq(path, "/this/is/the path")); free(path);
|
||||
xassert(streq(query, "query1=abc&query2=def")); free(query);
|
||||
xassert(streq(fragment, "fragment")); free(fragment);
|
||||
}
|
||||
|
||||
UNITTEST
|
||||
{
|
||||
/* Valid URI, fragment, no query */
|
||||
const char uri[] = "http://www.foobar.com:80/this/is/the%20path#fragment";
|
||||
|
||||
char *scheme, *user, *password, *host, *path, *query, *fragment;
|
||||
uint16_t port = 0;
|
||||
|
||||
uri_parse(
|
||||
uri, sizeof(uri) - 1, &scheme, &user, &password, &host, &port, &path,
|
||||
&query, &fragment);
|
||||
xassert(streq(scheme, "http")); free(scheme);
|
||||
xassert(user == NULL);
|
||||
xassert(password == NULL);
|
||||
xassert(streq(host, "www.foobar.com")); free(host);
|
||||
xassert(port == 80);
|
||||
xassert(streq(path, "/this/is/the path")); free(path);
|
||||
xassert(query == NULL);
|
||||
xassert(streq(fragment, "fragment")); free(fragment);
|
||||
}
|
||||
|
||||
UNITTEST
|
||||
{
|
||||
/* Valid URI, query, no fragment */
|
||||
const char uri[] = "http://www.foobar.com:80/this/is/the%20path?query1=abc&query2=def";
|
||||
|
||||
char *scheme, *user, *password, *host, *path, *query, *fragment;
|
||||
uint16_t port = 0;
|
||||
|
||||
uri_parse(
|
||||
uri, sizeof(uri) - 1, &scheme, &user, &password, &host, &port, &path,
|
||||
&query, &fragment);
|
||||
xassert(streq(scheme, "http")); free(scheme);
|
||||
xassert(user == NULL);
|
||||
xassert(password == NULL);
|
||||
xassert(streq(host, "www.foobar.com")); free(host);
|
||||
xassert(port == 80);
|
||||
xassert(streq(path, "/this/is/the path")); free(path);
|
||||
xassert(streq(query, "query1=abc&query2=def")); free(query);
|
||||
xassert(fragment == NULL);
|
||||
}
|
||||
|
||||
UNITTEST
|
||||
{
|
||||
/* Malformed URI, fragment before query (treated as part of path instead) */
|
||||
const char uri[] = "http://www.foobar.com:80/this/is/the%20path#fragment?query1=abc&query2=def";
|
||||
|
||||
char *scheme, *user, *password, *host, *path, *query, *fragment;
|
||||
uint16_t port = 0;
|
||||
|
||||
uri_parse(
|
||||
uri, sizeof(uri) - 1, &scheme, &user, &password, &host, &port, &path,
|
||||
&query, &fragment);
|
||||
xassert(streq(scheme, "http")); free(scheme);
|
||||
xassert(user == NULL);
|
||||
xassert(password == NULL);
|
||||
xassert(streq(host, "www.foobar.com")); free(host);
|
||||
xassert(port == 80);
|
||||
xassert(streq(path, "/this/is/the path#fragment?query1=abc&query2=def")); free(path);
|
||||
xassert(query == NULL);
|
||||
xassert(fragment == NULL);
|
||||
}
|
||||
|
||||
UNITTEST
|
||||
{
|
||||
/* Malformed URI, trailing '%' */
|
||||
const char uri[] = "file:///%ABNOT-PART-OF-INPUT";
|
||||
char *path;
|
||||
uri_parse(uri, 9, NULL, NULL, NULL, NULL, NULL, &path, NULL, NULL);
|
||||
xassert(streq(path, "/%")); free(path);
|
||||
}
|
||||
|
||||
UNITTEST
|
||||
{
|
||||
/* Malformed URI, trailing '%2' */
|
||||
const char uri[] = "file:///%2ANOT-PART-OF-INPUT";
|
||||
char *path;
|
||||
uri_parse(uri, 10, NULL, NULL, NULL, NULL, NULL, &path, NULL, NULL);
|
||||
xassert(streq(path, "/%2")); free(path);
|
||||
}
|
||||
|
||||
UNITTEST
|
||||
{
|
||||
/* Malformed URI, trailing '%ag' */
|
||||
const char uri[] = "file:///%ag";
|
||||
char *path;
|
||||
uri_parse(uri, sizeof(uri) - 1, NULL, NULL, NULL, NULL, NULL, &path, NULL, NULL);
|
||||
xassert(streq(path, "/%ag")); free(path);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue