7#include <ascii-chat/util/string.h>
8#include <ascii-chat/util/utf8.h>
9#include <ascii-chat/common.h>
10#include <ascii-chat/platform/system.h>
11#include <ascii-chat/platform/terminal.h>
12#include <ascii-chat/options/rcu.h>
13#include <ascii-chat/log/logging.h>
17void escape_ascii(
const char *str,
const char *escape_char,
char *out_buffer,
size_t out_buffer_size) {
18 if (escape_char == NULL || str == NULL || !out_buffer || out_buffer_size == 0) {
19 SET_ERRNO(ERROR_INVALID_PARAM,
"Invalid string or escape character or output buffer");
24 size_t escape_count = 0;
25 for (
size_t i = 0; i < strlen(str); i++) {
26 for (
size_t j = 0; j < strlen(escape_char); j++) {
27 if (str[i] == escape_char[j]) {
34 size_t total_len = strlen(str) + escape_count;
35 if (out_buffer_size < total_len) {
36 SET_ERRNO(ERROR_INVALID_PARAM,
"Output buffer is too small");
41 for (
size_t i = 0; i < strlen(str); i++) {
42 bool needs_escape =
false;
43 for (
size_t j = 0; j < strlen(escape_char); j++) {
44 if (str[i] == escape_char[j]) {
51 out_buffer[out_pos++] =
'\\';
53 out_buffer[out_pos++] = str[i];
56 out_buffer[out_pos] =
'\0';
66 const char *dangerous =
";|$`\\\"'<>()[]{}*?!~#@ \t\n\r";
76 const uint8_t *p = (
const uint8_t *)str;
86 if (codepoint <= 127) {
87 unsigned char c = (
unsigned char)codepoint;
97 bool is_allowed =
false;
98 for (
size_t j = 0; allowed_chars[j] !=
'\0'; j++) {
99 if (c == (
unsigned char)allowed_chars[j]) {
111 bool is_dangerous =
false;
112 for (
size_t j = 0; dangerous[j] !=
'\0'; j++) {
113 if (c == (
unsigned char)dangerous[j]) {
130 if (!str || !out_buffer || out_buffer_size == 0) {
136 size_t required_size = 2;
137 for (
size_t i = 0; str[i] !=
'\0'; i++) {
138 if (str[i] ==
'\'') {
145 if (out_buffer_size < required_size) {
146 SET_ERRNO(ERROR_BUFFER_OVERFLOW,
"Output buffer too small for shell escaping");
151 out_buffer[out_pos++] =
'\'';
153 for (
size_t i = 0; str[i] !=
'\0'; i++) {
154 if (str[i] ==
'\'') {
156 out_buffer[out_pos++] =
'\'';
157 out_buffer[out_pos++] =
'\\';
158 out_buffer[out_pos++] =
'\'';
159 out_buffer[out_pos++] =
'\'';
161 out_buffer[out_pos++] = str[i];
165 out_buffer[out_pos++] =
'\'';
166 out_buffer[out_pos] =
'\0';
172 if (!str || !out_buffer || out_buffer_size == 0) {
179 size_t required_size = 2;
180 for (
size_t i = 0; str[i] !=
'\0'; i++) {
181 if (str[i] ==
'"' || str[i] ==
'\\') {
188 if (out_buffer_size < required_size) {
189 SET_ERRNO(ERROR_BUFFER_OVERFLOW,
"Output buffer too small for shell escaping");
194 out_buffer[out_pos++] =
'"';
196 for (
size_t i = 0; str[i] !=
'\0'; i++) {
199 out_buffer[out_pos++] =
'\\';
200 out_buffer[out_pos++] =
'"';
201 }
else if (str[i] ==
'\\') {
203 out_buffer[out_pos++] =
'\\';
204 out_buffer[out_pos++] =
'\\';
206 out_buffer[out_pos++] = str[i];
210 out_buffer[out_pos++] =
'"';
211 out_buffer[out_pos] =
'\0';
217 if (!str || str[0] ==
'\0') {
222 for (
size_t i = 0; str[i] !=
'\0'; i++) {
226 if (c ==
' ' || c ==
'\t' || c ==
'\n' || c ==
'\r') {
231 if (c ==
'"' || c ==
'\'' || c ==
'$' || c ==
'`' || c ==
'\\' || c ==
'<' || c ==
'>' || c ==
'&' || c ==
';' ||
232 c ==
'|' || c ==
'(' || c ==
')' || c ==
'[' || c ==
']' || c ==
'{' || c ==
'}' || c ==
'*' || c ==
'?' ||
233 c ==
'!' || c ==
'~' || c ==
'#' || c ==
'@') {
242 if (!path || !out_buffer || out_buffer_size == 0) {
243 SET_ERRNO(ERROR_INVALID_PARAM,
"Invalid path or output buffer");
250 size_t path_len = strlen(path);
251 if (out_buffer_size <= path_len) {
252 SET_ERRNO(ERROR_BUFFER_OVERFLOW,
"Output buffer too small for path");
255 SAFE_STRNCPY(out_buffer, path, out_buffer_size);
272#define COLORED_BUFFERS 4
273#define COLORED_BUFFER_SIZE 256
275 static int buffer_idx = 0;
286 bool use_colors =
false;
305 char *current_buf = buffers[buffer_idx];
ASCIICHAT_API bool g_color_flag_value
ASCIICHAT_API bool g_color_flag_passed
const char * log_level_color(log_color_t color)
int safe_snprintf(char *buffer, size_t buffer_size, const char *format,...)
Safe formatted string printing to buffer.
bool utf8_is_valid(const char *str)
int utf8_decode(const uint8_t *s, uint32_t *codepoint)
const char * colored_string(log_color_t color, const char *text)
bool escape_shell_double_quotes(const char *str, char *out_buffer, size_t out_buffer_size)
bool escape_shell_single_quotes(const char *str, char *out_buffer, size_t out_buffer_size)
#define COLORED_BUFFER_SIZE
bool string_needs_shell_quoting(const char *str)
bool validate_shell_safe(const char *str, const char *allowed_chars)
void escape_ascii(const char *str, const char *escape_char, char *out_buffer, size_t out_buffer_size)
bool escape_path_for_shell(const char *path, char *out_buffer, size_t out_buffer_size)