ascii-chat
Binary v0.15.83-53-gb711d8720
Library lib/v0.3.2-701-gb711d8720
Video chat in your terminal
Loading...
Searching...
No Matches
input.c File Reference

Go to the source code of this file.

Functions

asciichat_error_t media_input_normalize (const char *text, char *output, size_t capacity)

Function Documentation

◆ media_input_normalize()

asciichat_error_t media_input_normalize ( const char * text,
char * output,
size_t capacity )

Normalize one dropped/pasted path or URL without interpreting shell commands.

Definition at line 14 of file media/input.c.

14 {
15 if (!text || !output || capacity < 2)
16 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid media input buffer");
17 output[0] = '\0';
18 while (isspace((unsigned char)*text))
19 ++text;
20 size_t length = strlen(text);
21 while (length && isspace((unsigned char)text[length - 1]))
22 --length;
23 if (!length)
24 return SET_ERRNO(ERROR_INVALID_PARAM, "Enter one media path or URL");
25 if (length > 2 && text[0] == '&' && text[1] == ' ') {
26 text += 2;
27 length -= 2;
28 }
29 char quote = (*text == '\'' || *text == '"') ? *text : 0;
30 if (quote) {
31 if (length < 2 || text[length - 1] != quote)
32 return SET_ERRNO(ERROR_INVALID_PARAM, "Choose one file with matching quotes");
33 ++text;
34 length -= 2;
35 }
36 bool uri = length >= 7 && strncmp(text, "file://", sizeof("file://") - 1) == 0;
37 bool url = !uri && (strstr(text, "://") != NULL);
38 if (uri) {
39 text += 7;
40 length -= 7;
41 if (length >= 10 && strncmp(text, "localhost/", sizeof("localhost/") - 1) == 0) {
42 text += 9;
43 length -= 9;
44 } else if (*text != '/') {
45 return SET_ERRNO(ERROR_INVALID_PARAM, "Only local file URIs are supported");
46 }
47#ifdef _WIN32
48 if (length >= 3 && text[0] == '/' && isalpha((unsigned char)text[1]) && text[2] == ':') {
49 ++text;
50 --length;
51 }
52#endif
53 }
54 bool windows_path = length >= 2 && (text[1] == ':' || (text[0] == '\\' && text[1] == '\\'));
55 size_t used = 0;
56 size_t i = 0;
57 while (i < length) {
58 unsigned char c = (unsigned char)text[i];
59 if (uri && c == '%') {
60 if (i + 2 >= length || hex_digit((unsigned char)text[i + 1]) < 0 || hex_digit((unsigned char)text[i + 2]) < 0)
61 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid escape in file URI");
62 c = (unsigned char)(hex_digit((unsigned char)text[i + 1]) * 16 + hex_digit((unsigned char)text[i + 2]));
63 i += 2;
64 } else if (!url && !uri && !quote && !windows_path && c == '\\' && i + 1 < length &&
65 (text[i + 1] == ' ' || text[i + 1] == '\'' || text[i + 1] == '"' || text[i + 1] == '\\')) {
66 c = (unsigned char)text[++i];
67 } else if (!url && !uri && (c == '\'' || c == '"')) {
68 if (quote && c == (unsigned char)quote)
69 return SET_ERRNO(ERROR_INVALID_PARAM, "Choose one media file at a time");
70 }
71 if (c < 32 || c == 127)
72 return SET_ERRNO(ERROR_INVALID_PARAM, "Choose one media path or URL without control characters");
73 if (used + 1 >= capacity)
74 return SET_ERRNO(ERROR_INVALID_PARAM, "Media path or URL is too long");
75 output[used++] = (char)c;
76 ++i;
77 }
78 output[used] = '\0';
79 if (!utf8_is_valid(output))
80 return SET_ERRNO(ERROR_INVALID_PARAM, "Media path or URL is not valid UTF-8");
81 return used ? ASCIICHAT_OK : SET_ERRNO(ERROR_INVALID_PARAM, "Empty media path");
82}
#define SET_ERRNO(code,...)
@ ASCIICHAT_OK
Definition error_codes.h:46
@ ERROR_INVALID_PARAM
bool utf8_is_valid(const char *str)
Check if a string is valid UTF-8.
Definition utf8.c:128

References ASCIICHAT_OK, ERROR_INVALID_PARAM, SET_ERRNO, and utf8_is_valid().

Referenced by media_playlist_append().