358 lines
7.0 KiB
C
358 lines
7.0 KiB
C
|
/*
|
||
|
* Copyright (C) 2017-2023 Adrien Gesta-Fline
|
||
|
*
|
||
|
* This file is part of libAAF.
|
||
|
*
|
||
|
* This program is free software; you can redistribute it and/or modify
|
||
|
* it under the terms of the GNU General Public License as published by
|
||
|
* the Free Software Foundation; either version 2 of the License, or
|
||
|
* (at your option) any later version.
|
||
|
*
|
||
|
* This program is distributed in the hope that it will be useful,
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
* GNU General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU General Public License along
|
||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||
|
*/
|
||
|
|
||
|
#include <ctype.h>
|
||
|
#include <stdint.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include <wchar.h>
|
||
|
|
||
|
#include "aaf/utils.h"
|
||
|
|
||
|
#define BUILD_PATH_DEFAULT_BUF_SIZE 1024
|
||
|
|
||
|
int
|
||
|
laaf_util_wstr_contains_nonlatin (const wchar_t* str)
|
||
|
{
|
||
|
for (size_t i = 0; str[i] != 0x0000; i++) {
|
||
|
/* if char is out of the Basic Latin range */
|
||
|
if (str[i] > 0xff) {
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
char*
|
||
|
laaf_util_clean_filename (char* fname)
|
||
|
{
|
||
|
/*
|
||
|
* sanitize file/dir name
|
||
|
* https://stackoverflow.com/a/31976060
|
||
|
*/
|
||
|
size_t len = strlen (fname);
|
||
|
|
||
|
for (size_t i = 0; i < len; i++) {
|
||
|
unsigned char c = fname[i];
|
||
|
|
||
|
if (c == '/' ||
|
||
|
c == '<' ||
|
||
|
c == '>' ||
|
||
|
c == ':' ||
|
||
|
c == '"' ||
|
||
|
c == '|' ||
|
||
|
c == '?' ||
|
||
|
c == '*' ||
|
||
|
c == '\\' ||
|
||
|
(c > 0 && c < 0x20)) {
|
||
|
fname[i] = '_';
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* windows filenames can't end with ' ' or '.' */
|
||
|
for (int i = len - 1; i > 0; i--) {
|
||
|
char c = fname[i];
|
||
|
if (c != ' ' && c != '.') {
|
||
|
break;
|
||
|
}
|
||
|
fname[i] = '_';
|
||
|
}
|
||
|
|
||
|
return fname;
|
||
|
}
|
||
|
|
||
|
const char*
|
||
|
laaf_util_fop_get_file (const char* filepath)
|
||
|
{
|
||
|
if (filepath == NULL) {
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
const char* end = filepath + strlen (filepath);
|
||
|
|
||
|
while (end > filepath && !IS_DIR_SEP (*end)) {
|
||
|
--end;
|
||
|
}
|
||
|
|
||
|
return (IS_DIR_SEP (*end)) ? end + 1 : end;
|
||
|
}
|
||
|
|
||
|
char*
|
||
|
laaf_util_build_path (const char* sep, const char* first, ...)
|
||
|
{
|
||
|
char* str = malloc (BUILD_PATH_DEFAULT_BUF_SIZE);
|
||
|
|
||
|
if (str == NULL) {
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
size_t len = BUILD_PATH_DEFAULT_BUF_SIZE;
|
||
|
size_t offset = 0;
|
||
|
|
||
|
va_list args;
|
||
|
|
||
|
if (!sep) {
|
||
|
sep = DIR_SEP_STR;
|
||
|
}
|
||
|
|
||
|
int element_count = 0;
|
||
|
|
||
|
va_start (args, first);
|
||
|
|
||
|
const char* arg = first;
|
||
|
|
||
|
do {
|
||
|
int arglen = strlen (arg);
|
||
|
int argstart = 0;
|
||
|
int has_leading_sep = 0;
|
||
|
|
||
|
/* trim leading DIR_SEP */
|
||
|
for (int i = 0; arg[i] != 0x00; i++) {
|
||
|
if (IS_DIR_SEP (arg[i])) {
|
||
|
has_leading_sep = 1;
|
||
|
argstart++;
|
||
|
} else {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* trim trailing DIR_SEP */
|
||
|
for (int i = arglen - 1; i >= argstart; i--) {
|
||
|
if (IS_DIR_SEP (arg[i])) {
|
||
|
arglen--;
|
||
|
} else {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* TODO ? */
|
||
|
if (element_count == 0 && has_leading_sep) {
|
||
|
} else {
|
||
|
}
|
||
|
|
||
|
size_t reqlen = snprintf (NULL, 0, "%.*s", arglen - argstart, arg + argstart) + 1;
|
||
|
|
||
|
if (offset + reqlen >= len) {
|
||
|
reqlen = ((offset + reqlen) > (len + BUILD_PATH_DEFAULT_BUF_SIZE)) ? (offset + reqlen) : (len + BUILD_PATH_DEFAULT_BUF_SIZE);
|
||
|
|
||
|
char* tmp = realloc (str, (offset + reqlen));
|
||
|
|
||
|
if (tmp) {
|
||
|
str = tmp;
|
||
|
len = (offset + reqlen);
|
||
|
} else {
|
||
|
free (str);
|
||
|
return NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
offset += snprintf (str + offset, len - offset, "%s%.*s",
|
||
|
((element_count == 0 && has_leading_sep) || (element_count > 0)) ? sep : "",
|
||
|
arglen - argstart,
|
||
|
arg + argstart);
|
||
|
|
||
|
element_count++;
|
||
|
|
||
|
} while ((arg = va_arg (args, char*)) != NULL);
|
||
|
|
||
|
va_end (args);
|
||
|
|
||
|
return str;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
laaf_util_snprintf_realloc (char** str, int* size, size_t offset, const char* format, ...)
|
||
|
{
|
||
|
int tmpsize = 0;
|
||
|
|
||
|
if (!size) {
|
||
|
size = &tmpsize;
|
||
|
}
|
||
|
|
||
|
int retval, needed;
|
||
|
va_list ap;
|
||
|
|
||
|
va_start (ap, format);
|
||
|
|
||
|
while (0 <= (retval = vsnprintf ((*str) + offset, (*size) - offset, format, ap)) && (int64_t) ((*size) - offset) < (needed = retval + 1)) {
|
||
|
va_end (ap);
|
||
|
|
||
|
*size *= 2;
|
||
|
|
||
|
if ((int64_t) ((*size) - offset) < needed)
|
||
|
*size = needed + offset;
|
||
|
|
||
|
char* p = realloc (*str, *size);
|
||
|
|
||
|
if (p) {
|
||
|
*str = p;
|
||
|
} else {
|
||
|
free (*str);
|
||
|
*str = NULL;
|
||
|
*size = 0;
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
va_start (ap, format);
|
||
|
}
|
||
|
|
||
|
va_end (ap);
|
||
|
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
laaf_util_vsnprintf_realloc (char** str, int* size, int offset, const char* fmt, va_list* args)
|
||
|
{
|
||
|
va_list args2, args3;
|
||
|
|
||
|
va_copy (args2, *args);
|
||
|
va_copy (args3, *args);
|
||
|
|
||
|
int needed = vsnprintf (NULL, 0, fmt, args2) + 1;
|
||
|
|
||
|
if (needed >= (*size) - offset) {
|
||
|
char* p = realloc (*str, offset + needed);
|
||
|
|
||
|
if (p) {
|
||
|
*str = p;
|
||
|
*size = offset + needed;
|
||
|
} else {
|
||
|
/* If realloc() fails, the original block is left untouched; it is not freed or moved. */
|
||
|
va_end (args2);
|
||
|
va_end (args3);
|
||
|
|
||
|
return -1;
|
||
|
}
|
||
|
}
|
||
|
va_end (args2);
|
||
|
|
||
|
int written = vsnprintf ((*str) + offset, (*size) - offset, fmt, args3);
|
||
|
|
||
|
va_end (args3);
|
||
|
|
||
|
return written;
|
||
|
}
|
||
|
|
||
|
char*
|
||
|
laaf_util_c99strdup (const char* src)
|
||
|
{
|
||
|
if (!src) {
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
int len = 0;
|
||
|
|
||
|
while (src[len]) {
|
||
|
len++;
|
||
|
}
|
||
|
|
||
|
char* str = malloc (len + 1);
|
||
|
|
||
|
if (!str)
|
||
|
return NULL;
|
||
|
|
||
|
char* p = str;
|
||
|
|
||
|
while (*src) {
|
||
|
*(p++) = *(src++);
|
||
|
}
|
||
|
|
||
|
*p = '\0';
|
||
|
|
||
|
return str;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
laaf_util_dump_hex (const unsigned char* stream, size_t stream_sz, char** buf, int* bufsz, int offset)
|
||
|
{
|
||
|
if (stream == NULL) {
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
int initialOffset = offset;
|
||
|
uint32_t i = 0;
|
||
|
|
||
|
char hex[49];
|
||
|
char ascii[19];
|
||
|
|
||
|
uint32_t count = 0;
|
||
|
|
||
|
offset += laaf_util_snprintf_realloc (buf, bufsz, offset, " ______________________________ Hex Dump ______________________________\n\n");
|
||
|
|
||
|
while (count < stream_sz) {
|
||
|
uint32_t lineLen = (stream_sz - count) / 16;
|
||
|
|
||
|
if (lineLen <= 0)
|
||
|
lineLen = (stream_sz) % 16;
|
||
|
else
|
||
|
lineLen = 16;
|
||
|
|
||
|
memset (&hex, 0x20, sizeof (hex));
|
||
|
memset (&ascii, 0x00, sizeof (ascii));
|
||
|
|
||
|
uint32_t linepos = 0;
|
||
|
|
||
|
for (i = 0; i < lineLen; i++) {
|
||
|
linepos += snprintf (&hex[linepos], sizeof (hex) - (linepos), "%02x%s", *(const unsigned char*)(stream + count + i), (i == 7) ? " " : " ");
|
||
|
|
||
|
if (i < 8) {
|
||
|
if (isalnum (*(stream + count + i)))
|
||
|
ascii[i] = *(const unsigned char*)(stream + count + i);
|
||
|
else
|
||
|
ascii[i] = '.';
|
||
|
} else if (i > 8) {
|
||
|
if (isalnum (*(stream + count + i)))
|
||
|
ascii[i + 1] = *(const unsigned char*)(stream + count + i);
|
||
|
else
|
||
|
ascii[i + 1] = '.';
|
||
|
} else {
|
||
|
if (isalnum (*(stream + count + i))) {
|
||
|
ascii[i] = ' ';
|
||
|
ascii[i + 1] = *(const unsigned char*)(stream + count + i);
|
||
|
} else {
|
||
|
ascii[i] = ' ';
|
||
|
ascii[i + 1] = '.';
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Fill with blank the rest of the line */
|
||
|
if (lineLen < 16) {
|
||
|
for (i = linepos; i < 48; i++) {
|
||
|
hex[linepos++] = 0x20;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* terminate the line */
|
||
|
hex[48] = 0x00;
|
||
|
|
||
|
count += lineLen;
|
||
|
|
||
|
offset += laaf_util_snprintf_realloc (buf, bufsz, offset, " %s | %s\n", hex, ascii);
|
||
|
}
|
||
|
|
||
|
offset += laaf_util_snprintf_realloc (buf, bufsz, offset, " ______________________________________________________________________\n\n");
|
||
|
|
||
|
return offset - initialOffset; /* bytes written */
|
||
|
}
|