#include "SDL_internal.h"
#include "SDL_dialog_utils.h"
char *convert_filters(const SDL_DialogFileFilter *filters, int nfilters,
NameTransform ntf, const char *prefix,
const char *separator, const char *suffix,
const char *filt_prefix, const char *filt_separator,
const char *filt_suffix, const char *ext_prefix,
const char *ext_separator, const char *ext_suffix)
{
char *combined;
char *new_combined;
char *converted;
const char *terminator;
size_t new_length;
int i;
if (!filters) {
SDL_SetError("Called convert_filters() with NULL filters (SDL bug)");
return NULL;
}
combined = SDL_strdup(prefix);
if (!combined) {
return NULL;
}
for (i = 0; i < nfilters; i++) {
const SDL_DialogFileFilter *f = &filters[i];
converted = convert_filter(*f, ntf, filt_prefix, filt_separator,
filt_suffix, ext_prefix, ext_separator,
ext_suffix);
if (!converted) {
SDL_free(combined);
return NULL;
}
terminator = ((i + 1) < nfilters) ? separator : suffix;
new_length = SDL_strlen(combined) + SDL_strlen(converted)
+ SDL_strlen(terminator) + 1;
new_combined = (char *)SDL_realloc(combined, new_length);
if (!new_combined) {
SDL_free(converted);
SDL_free(combined);
return NULL;
}
combined = new_combined;
SDL_strlcat(combined, converted, new_length);
SDL_strlcat(combined, terminator, new_length);
SDL_free(converted);
}
new_length = SDL_strlen(combined) + SDL_strlen(suffix) + 1;
new_combined = (char *)SDL_realloc(combined, new_length);
if (!new_combined) {
SDL_free(combined);
return NULL;
}
combined = new_combined;
SDL_strlcat(combined, suffix, new_length);
return combined;
}
char *convert_filter(SDL_DialogFileFilter filter, NameTransform ntf,
const char *prefix, const char *separator,
const char *suffix, const char *ext_prefix,
const char *ext_separator, const char *ext_suffix)
{
char *converted;
char *name_filtered;
size_t total_length;
char *list;
list = convert_ext_list(filter.pattern, ext_prefix, ext_separator,
ext_suffix);
if (!list) {
return NULL;
}
if (ntf) {
name_filtered = ntf(filter.name);
} else {
name_filtered = SDL_strdup(filter.name);
}
if (!name_filtered) {
SDL_free(list);
return NULL;
}
total_length = SDL_strlen(prefix) + SDL_strlen(name_filtered)
+ SDL_strlen(separator) + SDL_strlen(list)
+ SDL_strlen(suffix) + 1;
converted = (char *) SDL_malloc(total_length);
if (!converted) {
SDL_free(list);
SDL_free(name_filtered);
return NULL;
}
SDL_snprintf(converted, total_length, "%s%s%s%s%s", prefix, name_filtered,
separator, list, suffix);
SDL_free(list);
SDL_free(name_filtered);
return converted;
}
char *convert_ext_list(const char *list, const char *prefix,
const char *separator, const char *suffix)
{
char *converted;
int semicolons;
size_t total_length;
semicolons = 0;
for (const char *c = list; *c; c++) {
semicolons += (*c == ';');
}
total_length =
SDL_strlen(list) - semicolons + semicolons * SDL_strlen(separator) + SDL_strlen(prefix) + SDL_strlen(suffix) + 1;
converted = (char *) SDL_malloc(total_length);
if (!converted) {
return NULL;
}
*converted = '\0';
SDL_strlcat(converted, prefix, total_length);
if (SDL_strcmp(list, "*") == 0) {
SDL_strlcat(converted, "*", total_length);
} else {
for (const char *c = list; *c; c++) {
if ((*c >= 'a' && *c <= 'z') || (*c >= 'A' && *c <= 'Z')
|| (*c >= '0' && *c <= '9') || *c == '-' || *c == '_'
|| *c == '.') {
char str[2];
str[0] = *c;
str[1] = '\0';
SDL_strlcat(converted, str, total_length);
} else if (*c == ';') {
if (c == list || c[-1] == ';') {
SDL_SetError("Empty pattern not allowed");
SDL_free(converted);
return NULL;
}
SDL_strlcat(converted, separator, total_length);
} else {
SDL_SetError("Invalid character '%c' in pattern (Only [a-zA-Z0-9_.-] allowed, or a single *)", *c);
SDL_free(converted);
return NULL;
}
}
}
if (list[SDL_strlen(list) - 1] == ';') {
SDL_SetError("Empty pattern not allowed");
SDL_free(converted);
return NULL;
}
SDL_strlcat(converted, suffix, total_length);
return converted;
}
const char *validate_filters(const SDL_DialogFileFilter *filters, int nfilters)
{
if (filters) {
for (int i = 0; i < nfilters; i++) {
const char *msg = validate_list(filters[i].pattern);
if (msg) {
return msg;
}
}
}
return NULL;
}
const char *validate_list(const char *list)
{
if (SDL_strcmp(list, "*") == 0) {
return NULL;
} else {
for (const char *c = list; *c; c++) {
if ((*c >= 'a' && *c <= 'z') || (*c >= 'A' && *c <= 'Z')
|| (*c >= '0' && *c <= '9') || *c == '-' || *c == '_'
|| *c == '.') {
continue;
} else if (*c == ';') {
if (c == list || c[-1] == ';') {
return "Empty pattern not allowed";
}
} else {
return "Invalid character in pattern (Only [a-zA-Z0-9_.-] allowed, or a single *)";
}
}
}
if (list[SDL_strlen(list) - 1] == ';') {
return "Empty pattern not allowed";
}
return NULL;
}