mirror of https://github.com/asterisk/asterisk
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
413 lines
8.3 KiB
413 lines
8.3 KiB
/*
|
|
* $Id$
|
|
*
|
|
* MiniMIME - a library for handling MIME messages
|
|
*
|
|
* Copyright (C) 2003 Jann Fischer <rezine@mistrust.net>
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* 3. Neither the name of the author nor the names of the contributors
|
|
* may be used to endorse or promote products derived from this software
|
|
* without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY JANN FISCHER AND CONTRIBUTORS ``AS IS'' AND
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL JANN FISCHER OR THE VOICES IN HIS HEAD
|
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
#include <assert.h>
|
|
|
|
#include "mm_internal.h"
|
|
|
|
/** @file mm_util.c
|
|
*
|
|
* This module contains utility functions for the MiniMIME library
|
|
*/
|
|
|
|
/** @defgroup util General purpose utility functions */
|
|
|
|
#ifndef __HAVE_LEAK_DETECTION
|
|
/**
|
|
* Allocates a block of memory
|
|
*
|
|
* @param size The size of the memory region to allocate
|
|
* @return A pointer to the allocated memory region
|
|
* @ingroup util
|
|
*
|
|
* xmalloc() calls abort() if either the size argument is negative or the
|
|
* requested memory amount could not be allocated via an assert() call.
|
|
*/
|
|
void *
|
|
xmalloc(size_t size)
|
|
{
|
|
void *p;
|
|
|
|
assert(size > 0);
|
|
p = malloc(size);
|
|
assert(p != NULL);
|
|
|
|
return p;
|
|
}
|
|
|
|
/**
|
|
* realloc() wrapper
|
|
*
|
|
* @param p Pointer to a memory region which should be reallocated
|
|
* @param size The new size of the memory region
|
|
* @return A pointer to the reallocated memory region
|
|
* @ingroup util
|
|
*
|
|
* xrealloc() is a wrapper around realloc() which calls abort() if either the
|
|
* size argument is negative or the requested memory amount could not be
|
|
* allocated.
|
|
*/
|
|
void *
|
|
xrealloc(void *p, size_t size)
|
|
{
|
|
void *n;
|
|
|
|
assert(size > 0);
|
|
n = realloc(p, size);
|
|
assert(n != NULL);
|
|
|
|
return n;
|
|
}
|
|
|
|
char *
|
|
xstrdup(const char *str)
|
|
{
|
|
char *p;
|
|
|
|
assert(str != NULL);
|
|
p = strdup(str);
|
|
assert(p != NULL);
|
|
|
|
return p;
|
|
}
|
|
|
|
void
|
|
xfree(void *p)
|
|
{
|
|
assert(p != NULL);
|
|
free(p);
|
|
p = NULL;
|
|
assert(p == NULL);
|
|
}
|
|
#endif /* ! __HAVE_LEAK_DETECTION */
|
|
|
|
/**
|
|
* Unquotes a string
|
|
*
|
|
* @param string The quoted string to unquote
|
|
* @return A pointer to the unquoted string
|
|
* @ingroup util
|
|
*
|
|
* This function unquotes a string. That is, it returns a pointer to a newly
|
|
* allocated memory region in which the unquoted string is stored. Only
|
|
* leading and trailing double-qoutes are removed. The string needs to be
|
|
* freed when it is not needed anymore.
|
|
*/
|
|
char *
|
|
mm_unquote(const char *string)
|
|
{
|
|
char *ret;
|
|
|
|
if (string[0] != '\"' || string[strlen(string)-1] != '\"')
|
|
return xstrdup(string);
|
|
|
|
ret = xstrdup(string + 1);
|
|
ret[strlen(ret)-1] = '\0';
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
/**
|
|
* Removes MIME comments from a string
|
|
*
|
|
* @param string The string to uncomment
|
|
* @return A pointer to the uncommented string or NULL on error. Sets mm_errno.
|
|
* @ingroup util
|
|
*
|
|
* This function removes MIME comments from a string (included in parantheses).
|
|
* It returns a pointer to a newly allocated memory region in which the
|
|
* uncommented string is stored. The returned string needs to be freed when
|
|
* it's not used anymore.
|
|
*/
|
|
char *
|
|
mm_uncomment(const char *string)
|
|
{
|
|
char *buf, *new, *orig, *token;
|
|
size_t new_size;
|
|
int found;
|
|
int open;
|
|
|
|
assert(string != NULL);
|
|
|
|
new_size = strlen(string) + 1;
|
|
new = NULL;
|
|
buf = NULL;
|
|
orig = NULL;
|
|
found = 0;
|
|
open = 0;
|
|
mm_errno = MM_ERROR_NONE;
|
|
|
|
buf = xstrdup(string);
|
|
orig = buf;
|
|
|
|
while (*buf != '\0') {
|
|
if (*buf == '(') {
|
|
open++;
|
|
new_size--;
|
|
found++;
|
|
} else if (*buf == ')') {
|
|
open--;
|
|
new_size--;
|
|
} else {
|
|
if (open)
|
|
new_size--;
|
|
}
|
|
buf++;
|
|
}
|
|
|
|
if (open != 0) {
|
|
mm_errno = MM_ERROR_PARSE;
|
|
mm_error_setmsg("Uncommenting: parantheses are unbalanced");
|
|
goto cleanup;
|
|
}
|
|
|
|
if (!found) {
|
|
new = orig;
|
|
return orig;
|
|
}
|
|
|
|
new = xmalloc(new_size + 1);
|
|
*new = '\0';
|
|
buf = orig;
|
|
token = buf;
|
|
|
|
/* Tokenize our string by parentheses, and copy the portions which are
|
|
* not commented to our destination.
|
|
*/
|
|
open = 0;
|
|
while (*buf != '\0') {
|
|
if (*buf == '(') {
|
|
if (!open) {
|
|
*buf = '\0';
|
|
strlcat(new, token, new_size);
|
|
token = buf+1;
|
|
}
|
|
open++;
|
|
}
|
|
if (*buf == ')') {
|
|
open--;
|
|
token = buf + 1;
|
|
}
|
|
buf++;
|
|
}
|
|
|
|
strlcat(new, token, new_size);
|
|
|
|
cleanup:
|
|
if (orig != NULL) {
|
|
xfree(orig);
|
|
orig = NULL;
|
|
}
|
|
|
|
if (mm_errno != MM_ERROR_NONE) {
|
|
if (new != NULL) {
|
|
xfree(new);
|
|
new = NULL;
|
|
}
|
|
return NULL;
|
|
} else {
|
|
return new;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* separate strings
|
|
*
|
|
* @param stringp A pointer to the string being splitted
|
|
* @param delim The delimeter string
|
|
* @ingroup util
|
|
*
|
|
* This function works similar to strsep(), with the difference that delim is
|
|
* treated as a whole.
|
|
*/
|
|
char *
|
|
xstrsep(char **stringp, const char *delim)
|
|
{
|
|
char *p;
|
|
char *s;
|
|
char *r;
|
|
|
|
if (*stringp == NULL || *stringp == '\0')
|
|
return NULL;
|
|
|
|
p = *stringp;
|
|
|
|
if ((s = strstr(p, delim)) == NULL) {
|
|
r = p;
|
|
while (*p != '\0')
|
|
p++;
|
|
*stringp = NULL;
|
|
return r;
|
|
} else {
|
|
r = p;
|
|
p += strlen(p) - strlen(s);
|
|
*p = '\0';
|
|
*stringp = p + strlen(delim);
|
|
return r;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Strips a given character set from a string
|
|
*
|
|
* @param input The string which to strip
|
|
* @param strip The character set to strip off
|
|
* @return A copy of the original string with all chars stripped
|
|
* @ingroup util
|
|
*/
|
|
char *
|
|
mm_stripchars(char *input, char *strip)
|
|
{
|
|
char *output, *orig;
|
|
int i, j, chars;
|
|
|
|
assert(input != NULL);
|
|
assert(strip != '\0');
|
|
|
|
chars = 0;
|
|
orig = input;
|
|
|
|
while (*orig != '\0') {
|
|
for (i = 0; i < strlen(strip); i++) {
|
|
if (*orig == strip[i]) {
|
|
chars++;
|
|
break;
|
|
}
|
|
}
|
|
orig++;
|
|
}
|
|
|
|
/* If we have not found any char in the input, return a dup of the orig
|
|
string */
|
|
if (chars == 0)
|
|
return(xstrdup(input));
|
|
|
|
output = (char *)xmalloc(strlen(input) - chars);
|
|
orig = output;
|
|
|
|
for (i = 0; i < strlen(input); i++) {
|
|
int stripc;
|
|
stripc = 0;
|
|
for (j = 0; j < strlen(strip); j++) {
|
|
if (input[i] == strip[j]) {
|
|
stripc = 1;
|
|
break;
|
|
}
|
|
}
|
|
if (stripc == 0) {
|
|
*output = input[i];
|
|
output++;
|
|
}
|
|
}
|
|
|
|
*output = '\0';
|
|
|
|
return(orig);
|
|
}
|
|
|
|
/**
|
|
* Adds characters to a string at given positions
|
|
*
|
|
* @param input The string to which to add characters
|
|
* @param add The character string to add
|
|
* @param linelength The position where to add the character
|
|
* @return A copy of the string with characters added
|
|
* @ingroup util
|
|
*
|
|
* This function adds the characters add at each linelength positions and
|
|
* returns this new string.
|
|
*/
|
|
char *
|
|
mm_addchars(char *input, char *add, uint16_t linelength)
|
|
{
|
|
uint32_t len;
|
|
uint32_t i;
|
|
uint32_t l;
|
|
uint32_t j;
|
|
uint16_t addcrlf;
|
|
char *output;
|
|
char *orig;
|
|
|
|
len = strlen(input);
|
|
if (len <= linelength)
|
|
return(xstrdup(input));
|
|
|
|
addcrlf = len / linelength;
|
|
|
|
output = (char *)xmalloc(len + (addcrlf * strlen(add)));
|
|
orig = output;
|
|
|
|
for (i = 0, l = 0; i < len; i++, l++) {
|
|
if (l == linelength) {
|
|
for (j = 0; j < strlen(add); j++) {
|
|
*output = add[j];
|
|
output++;
|
|
}
|
|
l = 0;
|
|
}
|
|
*output = input[i];
|
|
output++;
|
|
}
|
|
|
|
*output = '\0';
|
|
output = orig;
|
|
|
|
return(orig);
|
|
}
|
|
|
|
void
|
|
mm_striptrailing(char **what, const char *charset)
|
|
{
|
|
size_t eos, i, hit;
|
|
char *str;
|
|
|
|
str = *what;
|
|
for (eos = strlen(str)-1; eos >= 0; eos--) {
|
|
hit = 0;
|
|
for (i = 0; i < strlen(charset); i++) {
|
|
if (str[eos] == charset[i]) {
|
|
str[eos] = '\0';
|
|
hit = 1;
|
|
break;
|
|
}
|
|
}
|
|
if (!hit)
|
|
break;
|
|
}
|
|
}
|