2084 lines
48 KiB
C
Executable File
2084 lines
48 KiB
C
Executable File
/* general utility routines */
|
|
|
|
#include <mutils.h>
|
|
|
|
/* file descriptor dot lock file */
|
|
static int
|
|
lock_fd=(-1);
|
|
|
|
static const char basis_64[] =
|
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
|
|
/* taken from Parrot code */
|
|
const char Parrot_utf8skip[256] =
|
|
{
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ascii */
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ascii */
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ascii */
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ascii */
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ascii */
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ascii */
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ascii */
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ascii */
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* bogus */
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* bogus */
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* bogus */
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* bogus */
|
|
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* scripts */
|
|
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* scripts */
|
|
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* cjk etc. */
|
|
4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6 /* cjk etc. */
|
|
};
|
|
|
|
#define UTF8_IS_START(c) ((c) >= 0xC2 && (c) <= 0xF4)
|
|
#define UTF8SKIP(c) Parrot_utf8skip[c]
|
|
#define UTF8_IS_CONTINUATION(c) (((c) & 0xC0) == 0x80)
|
|
|
|
|
|
|
|
|
|
void mutils_liberate_memory(void **memory)
|
|
{
|
|
if (memory == NULL)
|
|
return;
|
|
|
|
if (*memory)
|
|
free(*memory);
|
|
*memory=(void *) NULL;
|
|
}
|
|
void mutils_liberate(void **memory)
|
|
{
|
|
if (memory == NULL)
|
|
return;
|
|
|
|
if (*memory)
|
|
free(*memory);
|
|
*memory=(void *) NULL;
|
|
}
|
|
void mutils_free_zero(void *buf,int size)
|
|
{
|
|
if (buf)
|
|
{
|
|
memset(buf,0,size);
|
|
mutils_liberate_memory(&buf);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief same as mutils_acquire_memory
|
|
*/
|
|
void *mutils_acquire_memory(size_t size)
|
|
{
|
|
void
|
|
*ptr;
|
|
|
|
if (size == 0)
|
|
{
|
|
mutils_error("%s (%d) - allocation size is specified as 0\n",MUTILS_CFL);
|
|
return(NULL);
|
|
}
|
|
ptr=malloc(size);
|
|
if (ptr)
|
|
{
|
|
memset(ptr,0,size);
|
|
}
|
|
|
|
return(ptr);
|
|
}
|
|
|
|
/*
|
|
** changes the size of the memory and returns a pointer to the (possibly
|
|
** moved) block. The contents will be unchanged up to the lesser of the new
|
|
** and old sizes.
|
|
*/
|
|
void mutils_reacquire_memory(void **memory,const size_t size)
|
|
{
|
|
void
|
|
*allocation;
|
|
|
|
if (memory == NULL)
|
|
return;
|
|
|
|
if (*memory == (void *) NULL)
|
|
{
|
|
*memory=mutils_acquire_memory(size);
|
|
return;
|
|
}
|
|
allocation=realloc(*memory,size);
|
|
|
|
if (allocation == (void *) NULL)
|
|
mutils_liberate_memory((void **) memory);
|
|
|
|
*memory=allocation;
|
|
}
|
|
|
|
|
|
/* from my hod program, muquit, Nov-10-2000 */
|
|
static void mutils_hex_or_oct_dump(FILE *fp,int base,unsigned char *buf,int length)
|
|
{
|
|
int
|
|
ii,
|
|
i;
|
|
|
|
unsigned char
|
|
hexbuf[16];
|
|
|
|
int
|
|
count=0;
|
|
|
|
int
|
|
line = 0;
|
|
|
|
int
|
|
c;
|
|
|
|
unsigned char
|
|
*p=buf;
|
|
|
|
|
|
if (length <= 0)
|
|
return;
|
|
|
|
*hexbuf='\0';
|
|
|
|
|
|
(void) fprintf (fp,
|
|
(base == 16) ? "%11d" : "%11d",0);
|
|
|
|
(void) fflush (fp);
|
|
|
|
for (i=1; i<base;i++)
|
|
{
|
|
(void) fprintf (fp,
|
|
(base == 16) ? "%3x" : "%4o", i);
|
|
}
|
|
|
|
(void) fprintf (fp,
|
|
(base == 16) ? " " : " ");
|
|
|
|
for (i=0; i <base; i++)
|
|
{
|
|
(void) fprintf (fp, "%x", i);
|
|
}
|
|
(void) fprintf (fp,"\n");
|
|
|
|
|
|
|
|
for (ii=0; ii < length; ii++, p++)
|
|
{
|
|
c=*p;
|
|
hexbuf[count] = (unsigned char) c;
|
|
if (count++ == 0)
|
|
{
|
|
if (base == 16)
|
|
{
|
|
/*
|
|
(void) fprintf (fp, "%8x: ",line * 0x10);
|
|
*/
|
|
/* print offset in decimal */
|
|
(void) fprintf(fp,"%8d: ",line * base);
|
|
}
|
|
else
|
|
{
|
|
(void) fprintf (fp, "%8o: ",line * 0x08);
|
|
}
|
|
|
|
}
|
|
(void) fprintf (fp,
|
|
(base == 16) ? "%02x " : "%03o ", hexbuf[count-1]);
|
|
|
|
if (count == base)
|
|
{
|
|
(void) fprintf (fp," ");
|
|
for (i=0; i <base; i++)
|
|
{
|
|
/* 127 is non-printable - muquit@muquit.com Oct-03-2002 */
|
|
if (hexbuf[i] >= 32 && hexbuf[i] < 127)
|
|
(void) fprintf (fp,"%c", hexbuf[i]);
|
|
else
|
|
(void) fprintf (fp,".");
|
|
}
|
|
count=0;
|
|
line++;
|
|
(void) fprintf (fp,"\n");
|
|
}
|
|
} /* while c!= EOF*/
|
|
(void) fflush (fp);
|
|
|
|
/*
|
|
** pad if necessary
|
|
*/
|
|
if (count < base)
|
|
{
|
|
int
|
|
j;
|
|
|
|
for (j=count; j <base; j++)
|
|
{
|
|
(void) fprintf (fp,
|
|
(base == 16) ? " " : " ");
|
|
}
|
|
|
|
(void) fprintf (fp," ");
|
|
|
|
for (i=0; i < count; i++)
|
|
{
|
|
/* 127 is non-printable - muquit@muquit.com Oct-03-2002 */
|
|
if (hexbuf[i] >= 32 && hexbuf[i] < 127)
|
|
{
|
|
(void) fprintf (fp,"%c", hexbuf[i]);
|
|
}
|
|
else
|
|
(void) fprintf (fp,".");
|
|
}
|
|
(void) fprintf (fp,"\n");
|
|
(void) fflush (fp);
|
|
} /* count < base .. */
|
|
}
|
|
|
|
void mutils_hex_dump(FILE *fp,unsigned char *buf,int length)
|
|
{
|
|
mutils_hex_or_oct_dump(fp,16,buf,length);
|
|
}
|
|
|
|
void mutils_hex_print(FILE *fp,unsigned char *bytes,int len)
|
|
{
|
|
int
|
|
i;
|
|
for (i=0; i < len; i++)
|
|
{
|
|
(void) fprintf(fp,"%02x ",bytes[i]);
|
|
if ((i % 16) == 15)
|
|
fprintf(fp, "\n");
|
|
|
|
}
|
|
(void) fprintf(fp,"\n");
|
|
}
|
|
|
|
|
|
|
|
void mutils_oct_dump(FILE *fp,unsigned char *buf,int length)
|
|
{
|
|
mutils_hex_or_oct_dump(fp,8,buf,length);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
** mutilsHowmanyCommas()
|
|
** calculates how many commas will be added to the buffer
|
|
**
|
|
** RCS
|
|
** $Revision: 1 $
|
|
** $Date: 2/24/04 8:38p $
|
|
** Return Values:
|
|
** no of commas
|
|
**
|
|
** Parameters:
|
|
** buf buf to scan
|
|
**
|
|
** Side Effects:
|
|
** none
|
|
**
|
|
** Limitations and Comments:
|
|
** buf must be a initialized string (at least)
|
|
**
|
|
** Development History:
|
|
** who when why
|
|
** ma_muquit@fccc.edu Oct-18-1997 first cut
|
|
*/
|
|
int mutilsHowmanyCommas(char *buf)
|
|
{
|
|
int
|
|
n=0,
|
|
length;
|
|
|
|
if (*buf == '\0')
|
|
return(0);
|
|
|
|
length=strlen(buf);
|
|
|
|
if ((length % 3) == 0)
|
|
n=(length/3)-1;
|
|
else
|
|
n=length/3;
|
|
|
|
if ( n < 0)
|
|
n=0;
|
|
|
|
return(n);
|
|
}
|
|
|
|
/*
|
|
** mutilsCommaize()
|
|
** add a comma after every 3rd digit from right
|
|
**
|
|
** RCS
|
|
** $Revision: 1 $
|
|
** $Date: 2/24/04 8:38p $
|
|
** Return Values:
|
|
** none
|
|
**
|
|
** Parameters:
|
|
** buf buf to modify
|
|
**
|
|
** Side Effects:
|
|
** buf is modified
|
|
**
|
|
** Limitations and Comments:
|
|
** buf must have enough space to hold the extra , characters
|
|
**
|
|
** Development History:
|
|
** who when why
|
|
** ma_muquit@fccc.edu no idea first cut
|
|
** Oct-18-97 added dynamic buffer
|
|
** May-26-1999 rewrote as the old version has
|
|
** memory overstepping bug. Code adapted from
|
|
** C-Snippets, file commaflt.c by Bruce Wedding and
|
|
** and Kurt Kuzba
|
|
*/
|
|
void mutilsCommaize(char *buf)
|
|
{
|
|
char
|
|
*pbuf=(char *) NULL;
|
|
|
|
int
|
|
bf=0,
|
|
cm=0,
|
|
tm=0;
|
|
|
|
if (*buf != '\0')
|
|
{
|
|
pbuf=mutilsStrdup(buf);
|
|
if (pbuf == (char *) NULL)
|
|
return; /* malloc failed, return quitely */
|
|
|
|
mutilsReverseString(pbuf);
|
|
while ((buf[bf++]=pbuf[tm++]) != 0)
|
|
{
|
|
if(++cm % 3 == 0 && pbuf[tm])
|
|
buf[bf++]=',';
|
|
}
|
|
if (pbuf)
|
|
(void) free((char *) pbuf);
|
|
|
|
mutilsReverseString(buf);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
** NULL terminate the buffer at the first sight of a non-digit character
|
|
*/
|
|
|
|
/*
|
|
** mutilsCleanBuf()
|
|
* NULL terminate the buffer at the first sight of a non-digit character
|
|
**
|
|
** Parameters:
|
|
** char *buf the buffer to clean
|
|
** char *bytes_in_buf the buffer size
|
|
** int *length returns, bytes in buffer after cleaning
|
|
**
|
|
** Return Values:
|
|
**
|
|
**
|
|
** Limitations and Comments:
|
|
** buf is modified
|
|
**
|
|
** Development History:
|
|
** who when why
|
|
** ma_muquit@fccc.edu Jul-31-1999 first cut
|
|
*/
|
|
void mutilsCleanBuf(buf,bytes_in_buf,length)
|
|
char
|
|
*buf;
|
|
int
|
|
bytes_in_buf;
|
|
int
|
|
*length;
|
|
{
|
|
int
|
|
i;
|
|
|
|
|
|
int
|
|
c=0;
|
|
for (i=0; i < bytes_in_buf; i++)
|
|
{
|
|
if (!isdigit(buf[i]))
|
|
{
|
|
buf[i]='\0';
|
|
break;
|
|
}
|
|
c++;
|
|
}
|
|
|
|
*length=c;
|
|
}
|
|
|
|
/*
|
|
** mutilsParseURL()
|
|
** parse a URL of the form
|
|
** http://host:port/thepage.html
|
|
** http://host/thepage.html
|
|
**
|
|
** Parameters:
|
|
** char *url the url to parse
|
|
** char *hostname the hostname (returns)
|
|
** int hostname_len allocated space length in hostname
|
|
** int *port the port (returns)
|
|
** char *page the page (returns)
|
|
** int page_len the alloacated space length in page
|
|
**
|
|
** Return Values:
|
|
** 0 on success
|
|
** -1 on failure
|
|
**
|
|
** Limitations and Comments:
|
|
** - not much error checking.
|
|
** - hostname and page must have enough space preallocated by the caller.
|
|
**
|
|
** Development History:
|
|
** who when why
|
|
** ma_muquit@fccc.edu Jul-10-1999 first cut
|
|
** Jul-20-1999 handle buffer overflow
|
|
*/
|
|
int mutilsParseURL(url,hostname,hostname_len,port,page,page_len)
|
|
char
|
|
*url;
|
|
|
|
char
|
|
*hostname;
|
|
|
|
int
|
|
hostname_len;
|
|
|
|
int
|
|
*port;
|
|
|
|
char
|
|
*page;
|
|
|
|
int
|
|
page_len;
|
|
|
|
{
|
|
char
|
|
tmpbuf[32],
|
|
*q,
|
|
*r,
|
|
*p,
|
|
*ptmp;
|
|
|
|
int
|
|
tmpbuf_len,
|
|
hlen=0,
|
|
tlen=0;
|
|
|
|
if (url == NULL || *url == '\0')
|
|
return(-1);
|
|
|
|
/* initialize */
|
|
*port=80;
|
|
*hostname = *page = *tmpbuf = '\0';
|
|
|
|
tmpbuf_len=sizeof(tmpbuf);
|
|
|
|
ptmp=mutilsStrdup(url);
|
|
if (!ptmp)
|
|
return (-1);
|
|
if (strlen(ptmp) < 7)
|
|
{
|
|
(void) free(ptmp);
|
|
return (-1);
|
|
}
|
|
|
|
/* skip http:// */
|
|
if ( (ptmp[0] == 'h' || ptmp[0] == 'H') &&
|
|
(ptmp[1] == 't' || ptmp[1] == 'T') &&
|
|
(ptmp[2] == 't' || ptmp[2] == 'T') &&
|
|
(ptmp[3] == 'p' || ptmp[3] == 'P') &&
|
|
(ptmp[4] == ':') &&
|
|
(ptmp[5] == '/') &&
|
|
(ptmp[6] == '/'))
|
|
{
|
|
p = ptmp+7;
|
|
}
|
|
else
|
|
{
|
|
(void) free(ptmp);
|
|
return (-1);
|
|
}
|
|
|
|
hlen=0;
|
|
tlen=0;
|
|
q=hostname;
|
|
r=tmpbuf;
|
|
for (; (*p != '/') && (*p != '\0'); p++)
|
|
{
|
|
/* get host part out */
|
|
if (*p != ':' && !isdigit(*p))
|
|
{
|
|
if (++hlen > hostname_len-1)
|
|
{
|
|
continue;
|
|
}
|
|
*q++ = *p;
|
|
}
|
|
|
|
/* get port out if any */
|
|
if (isdigit(*p))
|
|
{
|
|
if (++tlen > tmpbuf_len-1)
|
|
continue;
|
|
*r++ = *p;
|
|
}
|
|
}
|
|
/* NULL terminate */
|
|
*q='\0';
|
|
*r='\0';
|
|
|
|
|
|
if (*tmpbuf != '\0')
|
|
*port=atoi(tmpbuf);
|
|
|
|
/* the rest is the page */
|
|
if (*p == '\0')
|
|
return (-1);
|
|
|
|
(void) mutilsStrncpy(page,p,page_len);
|
|
|
|
(void) free(ptmp);
|
|
return (0);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
** mutilsSpacesToChar()
|
|
** converts all spaces to a single character
|
|
**
|
|
** Parameters:
|
|
** char *str - spaces to collapse from
|
|
** int c - to this character
|
|
**
|
|
** Return Values:
|
|
** pointer to the string
|
|
**
|
|
** Limitations and Comments:
|
|
** str is modified.
|
|
**
|
|
** adapted from C snipptes lib: lv1ws
|
|
**
|
|
** Development History:
|
|
** who when why
|
|
** muquit@lucent.com Mar-27-2001 first cut
|
|
*/
|
|
char *mutilsSpacesToChar(char *str,int c)
|
|
{
|
|
char
|
|
*ibuf,
|
|
*obuf;
|
|
|
|
register int
|
|
i,
|
|
n;
|
|
|
|
if (str)
|
|
{
|
|
ibuf=obuf=str;
|
|
i=n=0;
|
|
|
|
while (*ibuf)
|
|
{
|
|
if (isspace(*ibuf) && n)
|
|
ibuf++;
|
|
else
|
|
{
|
|
if (!isspace(*ibuf))
|
|
n=0;
|
|
else
|
|
{
|
|
*ibuf=c;
|
|
n=1;
|
|
}
|
|
obuf[i++] = *ibuf++;
|
|
}
|
|
}
|
|
obuf[i]='\0';
|
|
|
|
}
|
|
return (str);
|
|
}
|
|
|
|
/*
|
|
** mutilsRmallws()
|
|
** remove all whitespace (leading or trailing) from a string.
|
|
**
|
|
** Parameters:
|
|
** char *str
|
|
**
|
|
** Return Values:
|
|
** pointer to the string
|
|
**
|
|
** Limitations and Comments:
|
|
** str is modified. borrowed from public domain c snippets libraray.
|
|
**
|
|
** Development History:
|
|
** who when why
|
|
** ma_muquit@fccc.edu Jul-31-1999 first cut
|
|
*/
|
|
char *mutilsRmallws(char *str)
|
|
{
|
|
char
|
|
*obuf,
|
|
*nbuf;
|
|
|
|
if (str)
|
|
{
|
|
for (obuf=str, nbuf=str; *obuf; ++obuf)
|
|
{
|
|
if (!isspace(*obuf))
|
|
*nbuf++ = *obuf;
|
|
}
|
|
*nbuf='\0';
|
|
}
|
|
return (str);
|
|
}
|
|
/*
|
|
** mutilsStristr()
|
|
** case insensitive version of ANSI strstr()
|
|
**
|
|
** Parameters:
|
|
** char *s hay stack
|
|
** char *t needle
|
|
**
|
|
** Return Values:
|
|
** pointer to hay stack where the needle is found
|
|
** NULL if not found
|
|
**
|
|
** Limitations and Comments:
|
|
** from swish package by kevin h , kevin called it lstrstr()
|
|
**
|
|
** Development History:
|
|
** who when why
|
|
** ma_muquit@fccc.edu Jul-31-1999 first cut
|
|
*/
|
|
char *mutilsStristr(s,t)
|
|
char
|
|
*s;
|
|
char
|
|
*t;
|
|
{
|
|
|
|
int
|
|
i,
|
|
j,
|
|
k,
|
|
l;
|
|
|
|
for (i = 0; s[i]; i++)
|
|
{
|
|
for (j = 0, l = k = i; s[k] && t[j] &&
|
|
tolower(s[k]) == tolower(t[j]); j++, k++)
|
|
;
|
|
if (t[j] == '\0')
|
|
return s + l;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
** mutilsIsinname()
|
|
** checks if the mask fits in the string
|
|
**
|
|
** RCS
|
|
** $Revision: 1 $
|
|
** $Date: 2/24/04 8:38p $
|
|
** Return Values:
|
|
** 1 if fits
|
|
** 0 if not
|
|
** -1 if there's a memory allocation problem
|
|
**
|
|
** Parameters:
|
|
** string source string
|
|
** mask mask string
|
|
**
|
|
** Example:
|
|
** www.fccc.edu *.fccc.edu fits
|
|
** www.fccc.edu www* fits
|
|
** www.fccc.edu *fccc* fits
|
|
** 132.138.4.6 132* fits
|
|
** etc.....
|
|
**
|
|
** Side Effects:
|
|
** none
|
|
**
|
|
** Limitations and Comments:
|
|
** borrowed from swish by Kevin H
|
|
**
|
|
** Development History:
|
|
** who when why
|
|
** ma_muquit@fccc.edu Oct-18-1997 first cut
|
|
*/
|
|
int mutilsIsinname(string,mask)
|
|
char
|
|
*string;
|
|
char
|
|
*mask;
|
|
{
|
|
int
|
|
i,
|
|
j;
|
|
|
|
char
|
|
firstchar,
|
|
lastchar,
|
|
*tempmask;
|
|
|
|
if ((*string == '\0') || (*mask == '\0'))
|
|
return (0); /* mm */
|
|
|
|
if (!strcmp(mask, "*"))
|
|
return 1;
|
|
|
|
firstchar=mask[0];
|
|
lastchar=mask[(strlen(mask) - 1)];
|
|
tempmask=(char *) malloc(strlen(mask)*sizeof(char)+1);
|
|
if (tempmask == NULL)
|
|
{
|
|
(void) fprintf(stderr,"libmutils.a-mutilsIsinname(), malloc failed\n");
|
|
return(-1);
|
|
}
|
|
|
|
for (i = j = 0; mask[i]; i++)
|
|
if (mask[i] != '*')
|
|
tempmask[j++] = mask[i];
|
|
|
|
tempmask[j]='\0';
|
|
if (firstchar == '*')
|
|
{
|
|
if (lastchar == '*')
|
|
{
|
|
if ((char *) mutilsStristr(string, tempmask))
|
|
{
|
|
free(tempmask);
|
|
return 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((char *) mutilsStristr(string, tempmask) ==
|
|
string + strlen(string) - strlen(tempmask))
|
|
{
|
|
free(tempmask);
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
else if (lastchar == '*')
|
|
{
|
|
if ((char *) mutilsStristr(string, tempmask) == string)
|
|
{
|
|
free(tempmask);
|
|
return 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
** changed from strcmp(), patch sent my
|
|
** Takeshi OKURA <okura@osa.ncs.co.jp>
|
|
** Oct-30-1997
|
|
*/
|
|
if (!mutilsStrcasecmp(string, tempmask))
|
|
{
|
|
free(tempmask);
|
|
return 1;
|
|
}
|
|
}
|
|
free(tempmask);
|
|
|
|
return 0;
|
|
}
|
|
/*
|
|
** mutilsGetTIme()
|
|
** get current time, ex: Wed Jun 30 21:49:08 1993
|
|
**
|
|
** Parameters:
|
|
** none
|
|
**
|
|
** Return Values:
|
|
** pointer a string containing time
|
|
**
|
|
** Limitations and Comments:
|
|
** remove the trailing new line from ctime(). subsequent call will
|
|
** destroy the buffer. ctime() retuns pointer to a static buffer.
|
|
**
|
|
** Development History:
|
|
** who when why
|
|
** ma_muquit@fccc.edu Jul-31-1999 first cut
|
|
*/
|
|
char *mutilsGetTime ()
|
|
{
|
|
time_t
|
|
tm;
|
|
|
|
char
|
|
*times;
|
|
|
|
tm=time (NULL);
|
|
times=ctime(&tm);
|
|
times[(int) strlen(times)-1] = '\0';
|
|
return (times);
|
|
}
|
|
|
|
/* chop new line from a string */
|
|
/* string is modifiled */
|
|
char mutilsChopNL(string)
|
|
char
|
|
*string;
|
|
{
|
|
char
|
|
c;
|
|
char
|
|
*ptr;
|
|
|
|
c='\0';
|
|
|
|
if (string == NULL || *string == '\0')
|
|
return(c);
|
|
|
|
for (ptr = string; *ptr; ptr++);
|
|
|
|
if (ptr != string)
|
|
{
|
|
c = *(--ptr);
|
|
|
|
if (c == '\n')
|
|
{
|
|
*ptr='\0';
|
|
}
|
|
}
|
|
|
|
return (c);
|
|
}
|
|
|
|
/*
|
|
* mutilsStripLeadingSpace () - strips leading space/s from a string
|
|
*
|
|
* Description:
|
|
* This function strips leading spaces from a string and
|
|
* null terminates it.
|
|
*
|
|
* Input Parameters:
|
|
* char *str
|
|
*
|
|
* Output Parameters:
|
|
* char *str
|
|
*
|
|
* Return Values:
|
|
* one
|
|
*
|
|
* Side Effects:
|
|
* str is modified
|
|
*
|
|
* Limitations and Comments:
|
|
* str must points to a pre-allocated static or dynamic space
|
|
*
|
|
* Development History:
|
|
* who when why
|
|
* MA_Muquit@fccc.edu 18-Jun-96 first cut
|
|
*/
|
|
void mutilsStripLeadingSpace(char *s)
|
|
{
|
|
int i,
|
|
n=0;
|
|
|
|
char
|
|
*ls;
|
|
|
|
if (s == NULL || *s == '\0')
|
|
return;
|
|
|
|
for (i=0; i < (int) strlen(s); i++)
|
|
{
|
|
if ((s[i] == ' ' ) || (s[i] == '\t'))
|
|
n++;
|
|
else
|
|
break;
|
|
}
|
|
|
|
if (n)
|
|
{
|
|
ls= (char *) malloc(strlen(s)*sizeof(char)+1);
|
|
if (ls != (char *) NULL)
|
|
{
|
|
(void) strcpy (ls,s+n);
|
|
(void) strcpy (s,ls);
|
|
(void) free ((char *) ls);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
** mutilsStripTrailingSpace()
|
|
** strips trailing spaces at the end of a string.
|
|
**
|
|
** Parameters:
|
|
** char *str the string
|
|
**
|
|
** Return Values:
|
|
** none
|
|
**
|
|
** Limitations and Comments:
|
|
** the string is modified
|
|
**
|
|
**
|
|
** Development History:
|
|
** who when why
|
|
** ma_muquit@fccc.edu Jul-04-1998 first cut
|
|
*/
|
|
void mutilsStripTrailingSpace (char *str)
|
|
{
|
|
register int
|
|
i;
|
|
|
|
if (str == NULL || *str == '\0')
|
|
return;
|
|
for ((i=(int) strlen(str)-1); i >= 0; i--)
|
|
{
|
|
if ((str[i] == ' ') || (str[i] == '\t'))
|
|
{
|
|
str[i] = '\0';
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** make a temporary filename
|
|
** filename - returns
|
|
*/
|
|
#if 0
|
|
int mutilsTmpFilename(char *filename)
|
|
{
|
|
#define TMP_DIR "/tmp"
|
|
#define TMP_TEMPLATE "%s/editdb.XXXXXX"
|
|
char
|
|
*dir;
|
|
|
|
dir=(char *) getenv("TMPDIR");
|
|
if (dir == (char *) NULL)
|
|
dir=TMP_DIR;
|
|
|
|
(void) sprintf(filename,TMP_TEMPLATE,dir);
|
|
#ifdef HAVE_MKSTEMP
|
|
return(mkstemp(filename));
|
|
#else
|
|
return(mktemp(filename));
|
|
#endif /* ! HAVE_MKSTEMP */
|
|
}
|
|
#endif /* 0 */
|
|
|
|
|
|
/*
|
|
* basename() - return a file's basename
|
|
*
|
|
* RCS:
|
|
* $Revision: 1 $
|
|
* $Date: 2/24/04 8:38p $
|
|
*
|
|
* Security:
|
|
* Unclassified
|
|
*
|
|
* Description:
|
|
* Basename parses a char string containing a path name and
|
|
* returns a pointer to the file's base name.
|
|
*
|
|
* Input Parameters:
|
|
* char *path - the fully qualified path to parse
|
|
*
|
|
* Output Parameters:
|
|
* None.
|
|
*
|
|
* Return Values:
|
|
* (char *) - a pointer to the start of the base name within
|
|
* 'path'
|
|
*
|
|
* Side Effects:
|
|
* None.
|
|
*
|
|
* Limitations and Comments:
|
|
* Basename handles both DOS and UNIX path separators; it also
|
|
* handles the DOS device delimiter.
|
|
*
|
|
* I renamed it to mutilsBasename() as basename() will have collision
|
|
* now a days. -- mm, augh-11-1999
|
|
*
|
|
* Note that this function can return NULL.
|
|
*
|
|
* Development History:
|
|
* 3/26/92, jps, first cut
|
|
*/
|
|
char *mutilsBasename(char *path)
|
|
{
|
|
char
|
|
*cptr;
|
|
|
|
for (cptr = path + strlen(path); cptr >= path; --cptr)
|
|
{
|
|
switch (*cptr)
|
|
{
|
|
case ':':
|
|
case '/':
|
|
case '\\':
|
|
return ++cptr;
|
|
}
|
|
}
|
|
return (path);
|
|
}
|
|
|
|
|
|
/*
|
|
** Return the extension of a file in a path
|
|
** Parameters:
|
|
** path - path of a file
|
|
** Return Values:
|
|
** pointer to the extension
|
|
** Side Effects:
|
|
** none
|
|
** Comments:
|
|
** If that is /usr/local/file.pdf, pointer to
|
|
** pdf will be returned
|
|
** Development History:
|
|
** muquit@muquit.com Dec-15-2013 - needed to detect mime type based on extension
|
|
*/
|
|
char *mutilsExtension(char *path)
|
|
{
|
|
char
|
|
*base,
|
|
*cptr;
|
|
|
|
base = mutilsBasename(path);
|
|
for (cptr = base + strlen(base); cptr >= base; --cptr)
|
|
{
|
|
switch (*cptr)
|
|
{
|
|
case '.':
|
|
{
|
|
return ++cptr;
|
|
}
|
|
}
|
|
}
|
|
return path;
|
|
}
|
|
|
|
char *mutilsExtensionLower(char *path)
|
|
{
|
|
char
|
|
*ext;
|
|
return (mutilsStrLower(mutilsExtension(path)));
|
|
}
|
|
|
|
|
|
/*
|
|
** Return the basename of a path
|
|
** Parameters:
|
|
** path - path in Unix or windows style
|
|
**
|
|
** Return Values:
|
|
** pointer to the basename on success
|
|
** pointer to the path on failure
|
|
** Side Effects:
|
|
** no memory is allocated, pointer is returned
|
|
** pointing to the basename
|
|
** Comments:
|
|
** If path is say /usr/local/foo, foo will be returned
|
|
** on success. if path is c:\foo\bar, pointer to bar
|
|
** will be returned. if path is blah, pointer ot
|
|
** blah will be returned
|
|
** Development History:
|
|
** muquit@muquit.com Dec-15-2013
|
|
** didn't know I already had it
|
|
*/
|
|
char *mutils_basename(const char *path)
|
|
{
|
|
char
|
|
*bn = path;
|
|
bn = strrchr(path,'/');
|
|
if (bn == NULL)
|
|
{
|
|
bn = strrchr(path,'\\');
|
|
}
|
|
return (bn == NULL) ? path : ++bn;
|
|
}
|
|
|
|
/*
|
|
** mutilsDotLock()
|
|
** open a file for locking purpose. If the system is Unix, use
|
|
** Kernel lock on the file.
|
|
**
|
|
** Parameters:
|
|
** char *lockfile_path - full path of the lock file
|
|
** char *errbuf - feels this errbuf in case of error
|
|
**
|
|
** Return Values:
|
|
** none
|
|
**
|
|
** Limitations and Comments:
|
|
** if you're on Unix, make sure the partition is not NFS mounted, if i
|
|
** is NFS mounted, the counter might hang.
|
|
** errbuf must have enough space to hold the message
|
|
**
|
|
** Development History:
|
|
** who when why
|
|
** ma_muquit@fccc.edu Aug-16-1999 first cut
|
|
*/
|
|
|
|
static char
|
|
s_lockfile[BUFSIZ];
|
|
|
|
void mutilsDotLock(char *filepath,char *errbuf)
|
|
{
|
|
*errbuf='\0';
|
|
*s_lockfile='\0';
|
|
|
|
#ifdef SYS_WIN32
|
|
lock_fd=sopen(filepath,_O_RDWR|_O_CREAT,SH_DENYWR,_S_IREAD|_S_IWRITE);
|
|
#else
|
|
lock_fd=open(filepath,O_RDWR|O_CREAT,0644);
|
|
#endif
|
|
|
|
if (lock_fd < 0) /* open failed */
|
|
{
|
|
(void) sprintf(errbuf,"Could open counter database lock file for writing:\n%s",filepath);
|
|
return;
|
|
}
|
|
(void) strcpy(s_lockfile,filepath);
|
|
|
|
#ifdef SYS_UNIX
|
|
mutilsSetLock(lock_fd);
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
/* unlock the file */
|
|
void mutilsDotUnlock(int delete)
|
|
{
|
|
if (lock_fd >= 0)
|
|
{
|
|
/* closing also unlocks kernel locking */
|
|
(void) close(lock_fd);
|
|
lock_fd=(-1);
|
|
if (delete == 1)
|
|
unlink(s_lockfile);
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef SYS_UNIX
|
|
void mutilsSetLock (int fd)
|
|
{
|
|
#ifdef HAVE_FLOCK
|
|
(void) flock(fd,LOCK_EX);
|
|
#else
|
|
lseek(fd,0L,0);
|
|
(void) lockf(fd,F_LOCK,0L);
|
|
#endif
|
|
}
|
|
|
|
void mutilsUnsetLock (int fd)
|
|
{
|
|
#ifdef HAVE_FLOCK
|
|
(void) flock(fd,LOCK_UN);
|
|
#else
|
|
lseek(fd,0L,0);
|
|
(void) lockf(fd,F_ULOCK,0L);
|
|
#endif
|
|
}
|
|
#endif /* SYS_UNIX */
|
|
|
|
|
|
/*
|
|
** mutilsWhich()
|
|
** returns 0 if the program is found in path
|
|
** -1 otherwise
|
|
**
|
|
** modified from: /usr3/doc/which-1.0/which.c on RH 5.2
|
|
*/
|
|
|
|
int mutilsWhich(char *name)
|
|
{
|
|
#ifndef X_OK
|
|
#define X_OK 0x01
|
|
#endif /* X_OK */
|
|
|
|
char
|
|
s,
|
|
*p,
|
|
*path,
|
|
szbuf[BUFSIZ];
|
|
int
|
|
found=0,
|
|
len;
|
|
|
|
/* check if the program exists and executable */
|
|
if (access(name,X_OK) == 0) /* found it */
|
|
return(0);
|
|
|
|
/* go through the PATH */
|
|
path=getenv("PATH");
|
|
if (path == NULL)
|
|
return(-1);
|
|
|
|
p=path;
|
|
found=0;
|
|
while (*p != '\0' && found == 0)
|
|
{
|
|
len=0;
|
|
while (*p != ':' && *p != '\0')
|
|
{
|
|
len++;
|
|
p++;
|
|
}
|
|
s=(char) *p;
|
|
*p='\0';
|
|
(void) sprintf(szbuf,"%s/%s",p-len,name);
|
|
*p=s;
|
|
if (*p)
|
|
p++;
|
|
|
|
if (access(szbuf,X_OK) == 0)
|
|
found=1;
|
|
}
|
|
if (found == 0)
|
|
found=(-1);
|
|
|
|
if (found == 1) /* found */
|
|
found=0;
|
|
|
|
return(found);
|
|
}
|
|
|
|
/* eat white space from a open FILE pointer */
|
|
/* return -1 if fp is NULL */
|
|
int mutilsEatWhitespace(FILE *fp)
|
|
{
|
|
int
|
|
c;
|
|
|
|
if (fp == NULL)
|
|
return(-1);
|
|
|
|
for(c =getc(fp);isspace(c) && ('\n' != c); c=getc(fp))
|
|
;
|
|
return (c);
|
|
|
|
}
|
|
|
|
/* eat comments space from a open FILE pointer */
|
|
/* this function is called after seeing the comment character, so the */
|
|
/* function actually eats the line till sees a new line */
|
|
/* return -1 if fp is NULL */
|
|
int mutilsEatComment(FILE *fp)
|
|
{
|
|
int
|
|
c;
|
|
|
|
if (fp == NULL)
|
|
return(-1);
|
|
|
|
for(c=getc(fp); ('\n' != c) && (EOF != c ) && (c > 0); c=getc(fp))
|
|
;
|
|
|
|
return(c);
|
|
}
|
|
|
|
/*
|
|
** mutilsGgetDirname()
|
|
** returns the base directory of file (Unix or Windows)
|
|
** if fails returns NULL
|
|
** Note: returns pointer to a malloc'd space, caller is responsible to
|
|
** free it.
|
|
*/
|
|
char *mutilsGetDirname(file)
|
|
char
|
|
*file;
|
|
{
|
|
char
|
|
*f,
|
|
*p;
|
|
|
|
if (file == NULL || *file == '\0')
|
|
return (NULL);
|
|
|
|
f=strdup(file);
|
|
if (f == NULL)
|
|
return(NULL);
|
|
|
|
if ((p=strrchr(f,'/')) || (p=strrchr(f,'\\')))
|
|
{
|
|
*p='\0';
|
|
if (f)
|
|
return(f);
|
|
}
|
|
else
|
|
{
|
|
p=strdup("./");
|
|
return(p);
|
|
}
|
|
return (NULL);
|
|
}
|
|
|
|
/**
|
|
* @brief Free memory associated with tokens
|
|
* @param tokens The tokens to free
|
|
* @param ntokens Number of tokens in tokens
|
|
*/
|
|
void mutilsFreeTokens(char **tokens,int ntokens)
|
|
{
|
|
int
|
|
i;
|
|
|
|
/* free memory allocated for each token */
|
|
for (i=0; i < ntokens; i++)
|
|
{
|
|
if (tokens[i])
|
|
(void) free((char *) tokens[i]);
|
|
}
|
|
|
|
/* free the tokens itself */
|
|
if (tokens)
|
|
(void) free((char *) tokens);
|
|
}
|
|
|
|
/**
|
|
* @brief Tokenizes a string separated by delimiter
|
|
* @param str The string to tokenize
|
|
* @param delip The delimeter e.g. ' '
|
|
* @param ntoken Number of tokens in the string (returns)
|
|
* @return tokens on success, NULL on failure
|
|
*
|
|
* Example:
|
|
* int n=0;
|
|
* char **tokens=mutils_tokenize("this is"," ",&n);
|
|
*
|
|
* The caller should free the tokens by calling:
|
|
* mutils_free_tokens(tokens,ntokens)
|
|
* Note: A token can be of MUTILS_MAX_TOKEN_LEN long
|
|
*/
|
|
char **mutilsTokenize(char *str,int delim,int *ntokens)
|
|
{
|
|
char
|
|
tbuf[MUTILS_MAX_TOKEN_LEN],
|
|
**tokens=NULL;
|
|
|
|
int
|
|
j=0,
|
|
count=0,
|
|
allocated=0,
|
|
i=0;
|
|
|
|
char
|
|
*p;
|
|
|
|
*ntokens=0;
|
|
if (str == NULL || *str == '\0')
|
|
return(NULL);
|
|
|
|
/* count how many token there first */
|
|
for (p=str; *p; p++)
|
|
{
|
|
if (*p == delim)
|
|
{
|
|
count++;
|
|
}
|
|
}
|
|
count++;
|
|
/* allocate memory for tokens */
|
|
tokens=(char **) malloc(count * sizeof(char *));
|
|
MUTILS_CHECK_MALLOC(tokens);
|
|
|
|
allocated=0;
|
|
for (i=0; i < count; i++)
|
|
{
|
|
/*
|
|
** allocate memory for each token string, a token can
|
|
** be of MUTILS_MAX_TOKEN_LEN characters long maximum
|
|
*/
|
|
tokens[i]=(char *) malloc(MUTILS_MAX_TOKEN_LEN*sizeof(char));
|
|
MUTILS_CHECK_MALLOC(tokens[i]);
|
|
allocated++;
|
|
}
|
|
|
|
j=0;
|
|
count=0;
|
|
for (p=str; *p; p++)
|
|
{
|
|
if (*p != delim && *p != '\0')
|
|
{
|
|
if (j >= MUTILS_MAX_TOKEN_LEN)
|
|
{
|
|
(void) fprintf(stderr,"Buffer overflow detected\n");
|
|
/* buffer overfow */
|
|
goto ExitProcessing;
|
|
}
|
|
tbuf[j++]=*p;
|
|
}
|
|
else
|
|
{
|
|
/* we're in a new token */
|
|
tbuf[j++]='\0';
|
|
strcpy(tokens[count],tbuf);
|
|
count++;
|
|
j=0;
|
|
}
|
|
}
|
|
if (j > 0 && j < MUTILS_MAX_TOKEN_LEN)
|
|
{
|
|
tbuf[j]='\0';
|
|
mutilsStrncpy(tokens[count],tbuf,MUTILS_MAX_TOKEN_LEN-1);
|
|
}
|
|
|
|
count++;
|
|
|
|
*ntokens=count;
|
|
return(tokens);
|
|
|
|
ExitProcessing:
|
|
mutilsFreeTokens(tokens,allocated);
|
|
|
|
return(NULL);
|
|
}
|
|
|
|
static void *_fs_get (size_t size)
|
|
{
|
|
void *block =(void *) malloc (size ? size : (size_t) 1);
|
|
return (block);
|
|
}
|
|
|
|
static void _fs_give (void **block)
|
|
{
|
|
free (*block);
|
|
*block = NULL;
|
|
}
|
|
|
|
/*
|
|
**
|
|
** Given the length of a plain text string, return the
|
|
** length
|
|
**
|
|
** Parameters:
|
|
** len - length of plain text string
|
|
**
|
|
** Side Effects:
|
|
** none
|
|
**
|
|
** Comments:
|
|
** taken from apache apr util library
|
|
**
|
|
** Return Values:
|
|
** length of base64 encoded string
|
|
**
|
|
** Development History:
|
|
** muquit@muquit.com Oct-12-2013 first cut
|
|
*/
|
|
int mutils_base64_encode_len(int len)
|
|
{
|
|
return ((len + 2) / 3 * 4) + 1;
|
|
}
|
|
|
|
|
|
/**
|
|
* @Deprecated
|
|
* @brief encode content to base64
|
|
* @param src pointer to source
|
|
* @param srcl Length of the source
|
|
* @param len length of base64 encoded string (returns)
|
|
*
|
|
* @return Ponter to encoded strin gon success, NULL on failure. The
|
|
* caller is responsile to free the memory
|
|
*
|
|
* Adapted from from c-client source
|
|
*/
|
|
unsigned char *mutils_encode_base64(void *src,unsigned long srcl,unsigned long *len)
|
|
{
|
|
unsigned char
|
|
*ret,
|
|
*d;
|
|
|
|
unsigned char *s = (unsigned char *) src;
|
|
char *v="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
unsigned long i = ((srcl + 2) / 3) * 4;
|
|
*len = i += 2 * ((i / 60) + 1);
|
|
d = ret = (unsigned char *) _fs_get ((size_t) ++i);
|
|
if (d == NULL)
|
|
{
|
|
(void) fprintf(stderr,"%s (%d) - memory allocation failed\n",MUTILS_CFL);
|
|
return(NULL);
|
|
}
|
|
/* process tuplets */
|
|
for (i = 0; srcl >= 3; s += 3, srcl -= 3)
|
|
{
|
|
*d++ = v[s[0] >> 2]; /* byte 1: high 6 bits (1) */
|
|
/* byte 2: low 2 bits (1), high 4 bits (2) */
|
|
*d++ = v[((s[0] << 4) + (s[1] >> 4)) & 0x3f];
|
|
/* byte 3: low 4 bits (2), high 2 bits (3) */
|
|
*d++ = v[((s[1] << 2) + (s[2] >> 6)) & 0x3f];
|
|
*d++ = v[s[2] & 0x3f]; /* byte 4: low 6 bits (3) */
|
|
if ((++i) == 15)
|
|
{ /* output 60 characters? */
|
|
i = 0; /* restart line break count, insert CRLF */
|
|
*d++ = '\015';
|
|
*d++ = '\012';
|
|
}
|
|
}
|
|
if (srcl)
|
|
{
|
|
*d++ = v[s[0] >> 2]; /* byte 1: high 6 bits (1) */
|
|
/* byte 2: low 2 bits (1), high 4 bits (2) */
|
|
*d++ = v[((s[0] << 4) + (--srcl ? (s[1] >> 4) : 0)) & 0x3f];
|
|
/* byte 3: low 4 bits (2), high 2 bits (3) */
|
|
*d++ = srcl ? v[((s[1] << 2) + (--srcl ? (s[2] >> 6) : 0)) & 0x3f] : '='; /* byte 4: low 6 bits (3) */
|
|
*d++ = srcl ? v[s[2] & 0x3f] : '=';
|
|
if (srcl)
|
|
srcl--; /* count third character if processed */
|
|
if ((++i) == 15)
|
|
{ /* output 60 characters? */
|
|
i = 0; /* restart line break count, insert CRLF */
|
|
*d++ = '\015';
|
|
*d++ = '\012';
|
|
}
|
|
}
|
|
*d++ = '\015';
|
|
*d++ = '\012'; /* insert final CRLF */
|
|
*d = '\0'; /* tie off string */
|
|
if (((unsigned long) (d - ret)) != *len)
|
|
{
|
|
(void) fprintf(stderr,"%s (%d) - logic flow in encode base64\n",MUTILS_CFL);
|
|
(void) free((char *) ret);
|
|
return(NULL);
|
|
}
|
|
return (ret); /* return the resulting string */
|
|
}
|
|
|
|
/*
|
|
** Endode a string to base64
|
|
**
|
|
** Parameters:
|
|
** string - plain text/binary string
|
|
** len - length of the plain text string
|
|
**
|
|
** Return Values:
|
|
** Pointer to null terminated base 64 string. Memory is allocated for
|
|
** the string
|
|
** NULL in case of error.
|
|
** Comments:
|
|
** reason not to use mutils_encode_base64(), it adds crlf after 60
|
|
** characters, which broke smtp auth with longer base64 encoded string.
|
|
**
|
|
** The caller is responsible to free the memory of the returned string.
|
|
**
|
|
** Adapted from apache apr util library. Does not support EBCDIC.
|
|
**
|
|
** Side Effects:
|
|
** none
|
|
**
|
|
** Development History:
|
|
** muquit@muquit.com Oct-12-2013 first cut
|
|
*/
|
|
char *mutils_encode_base64_noformat(const char *string, int len)
|
|
{
|
|
int
|
|
encode_len,
|
|
i;
|
|
|
|
char
|
|
*p,
|
|
*encoded = NULL;
|
|
|
|
if (len == 0)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
encode_len = mutils_base64_encode_len(len);
|
|
encoded = (char *) malloc(encode_len);
|
|
MUTILS_CHECK_MALLOC(encoded);
|
|
memset(encoded, 0, encode_len);
|
|
p = encoded;
|
|
for (i = 0; i < len - 2; i += 3)
|
|
{
|
|
*p++ = basis_64[(string[i] >> 2) & 0x3F];
|
|
*p++ = basis_64[((string[i] & 0x3) << 4) | ((int) (string[i + 1] & 0xF0) >> 4)];
|
|
*p++ = basis_64[((string[i + 1] & 0xF) << 2) | ((int) (string[i + 2] & 0xC0) >> 6)];
|
|
*p++ = basis_64[string[i + 2] & 0x3F];
|
|
}
|
|
if (i < len)
|
|
{
|
|
*p++ = basis_64[(string[i] >> 2) & 0x3F];
|
|
if (i == (len - 1))
|
|
{
|
|
*p++ = basis_64[((string[i] & 0x3) << 4)];
|
|
*p++ = '=';
|
|
}
|
|
else
|
|
{
|
|
*p++ = basis_64[((string[i] & 0x3) << 4) | ((int) (string[i + 1] & 0xF0) >> 4)];
|
|
*p++ = basis_64[((string[i + 1] & 0xF) << 2)];
|
|
}
|
|
*p++ = '=';
|
|
}
|
|
|
|
*p++ = '\0';
|
|
return encoded;
|
|
ExitProcessing:
|
|
return NULL;
|
|
|
|
return strdup("fuck");
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief converts base64 contents to binary
|
|
* @param src The source
|
|
* @param srcl Length of the source
|
|
* @param len length of converted binary content (returns)
|
|
*
|
|
* @return Pointer to biary destination on success, NULL on failure. The
|
|
* caller is responsible to free ths memory.
|
|
*
|
|
* Adapted from c-client source
|
|
*/
|
|
void *mutils_decode_base64(unsigned char *src,unsigned long srcl,unsigned long *len)
|
|
{
|
|
char c,*s,tmp[BUFSIZ];
|
|
void *ret = _fs_get ((size_t) (*len = 4 + ((srcl * 3) / 4)));
|
|
char *d = (char *) ret;
|
|
int e;
|
|
#define JNK 0177
|
|
#define PAD 0100
|
|
static char decode[256] = {
|
|
JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,
|
|
JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,
|
|
JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,076,JNK,JNK,JNK,077,
|
|
064,065,066,067,070,071,072,073,074,075,JNK,JNK,JNK,PAD,JNK,JNK,
|
|
JNK,000,001,002,003,004,005,006,007,010,011,012,013,014,015,016,
|
|
017,020,021,022,023,024,025,026,027,030,031,JNK,JNK,JNK,JNK,JNK,
|
|
JNK,032,033,034,035,036,037,040,041,042,043,044,045,046,047,050,
|
|
051,052,053,054,055,056,057,060,061,062,063,JNK,JNK,JNK,JNK,JNK,
|
|
JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,
|
|
JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,
|
|
JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,
|
|
JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,
|
|
JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,
|
|
JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,
|
|
JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,
|
|
JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK,JNK
|
|
};
|
|
|
|
if (ret == NULL)
|
|
{
|
|
(void) fprintf(stderr,"%s (%d) - memory allocation failed\n",MUTILS_CFL);
|
|
return(NULL);
|
|
}
|
|
memset (ret,0,(size_t) *len); /* initialize block */
|
|
*len = 0; /* in case we return an error */
|
|
|
|
/* simple-minded decode */
|
|
for (e = 0; srcl--; )
|
|
switch (c = decode[*src++])
|
|
{
|
|
default: /* valid BASE64 data character */
|
|
switch (e++)
|
|
{ /* install based on quantum position */
|
|
case 0:
|
|
*d = c << 2; /* byte 1: high 6 bits */
|
|
break;
|
|
case 1:
|
|
*d++ |= c >> 4; /* byte 1: low 2 bits */
|
|
*d = c << 4; /* byte 2: high 4 bits */
|
|
break;
|
|
case 2:
|
|
*d++ |= c >> 2; /* byte 2: low 4 bits */
|
|
*d = c << 6; /* byte 3: high 2 bits */
|
|
break;
|
|
case 3:
|
|
*d++ |= c; /* byte 3: low 6 bits */
|
|
e = 0; /* reinitialize mechanism */
|
|
break;
|
|
}
|
|
break;
|
|
case JNK: /* junk character */
|
|
break;
|
|
case PAD: /* padding */
|
|
switch (e++)
|
|
{ /* check quantum position */
|
|
case 3: /* one = is good enough in quantum 3 */
|
|
/* make sure no data characters in remainder */
|
|
for (; srcl; --srcl)
|
|
switch (decode[*src++])
|
|
{
|
|
case JNK:
|
|
case PAD: /* ignore junk and extraneous padding */
|
|
break;
|
|
default: /* valid BASE64 data character */
|
|
/* This indicates bad MIME. One way that it can
|
|
be caused is if a single-section message was
|
|
BASE64 encoded and then something (e.g. a
|
|
mailing list processor) appended text. The
|
|
problem is that in 1 out of 3 cases, there is
|
|
no padding and hence no way to detect the end
|
|
of the data. Consequently, prudent software
|
|
will always encapsulate a BASE64 segment inside
|
|
a MULTIPART.*/
|
|
sprintf (tmp,"Possible data truncation in rfc822_base64(): %.80s", (char *) src - 1);
|
|
if (s = strpbrk (tmp,"\015\012"))
|
|
*s = 0;
|
|
/*mm_log (tmp,PARSE);*/
|
|
srcl = 1; /* don't issue any more messages */
|
|
break;
|
|
}
|
|
break;
|
|
case 2: /* expect a second = in quantum 2 */
|
|
if (srcl && (*src == '='))
|
|
break;
|
|
default: /* impossible quantum position */
|
|
_fs_give (&ret);
|
|
return(NULL);
|
|
}
|
|
break;
|
|
}
|
|
*len = d - (char *) ret; /* calculate data length */
|
|
return ret; /* return the string */
|
|
}
|
|
|
|
unsigned char mutils_hex_char_to_bin(char x)
|
|
{
|
|
if (x >= '0' && x <= '9')
|
|
return(x - '0');
|
|
|
|
x=toupper(x);
|
|
return((x - 'A') + 10);
|
|
}
|
|
/**
|
|
* convert a hex string to it's binary format.
|
|
* @param hex_string - The hex string to convert
|
|
* @param len - length of the hex string
|
|
* @param *olen - The length of the binary string - returns
|
|
*
|
|
* @return pointer to a unsigned char holding the binary version of the
|
|
* hex string. returns NULL on failure. The caller should check
|
|
* olen (> 0) before using the binary
|
|
*
|
|
* @note Memory is allocated for the retured unsigned char pointer
|
|
* The caller is responsible to free it
|
|
*
|
|
* The format of the hex string can be any of:
|
|
* 0xde:ad:be:ef:ca:fe
|
|
* de:ad:be:ef:ca:fe
|
|
* de-ad-be-ef-ca-fe
|
|
* 0xde-ad-be-ef-ca-fe
|
|
* de:ad-be_ef:ca:fe
|
|
*
|
|
* The converted binary value will be: de ad be ef ca fe
|
|
*
|
|
* It will only convert valid hex strings to binary, for example, if
|
|
* the string is like: de:gh:ad:ff:bb:kk:cc
|
|
* The binary value will contain: de ad ff bb cc
|
|
* Note, gh and kk are ignored
|
|
*/
|
|
unsigned char *mutils_hex_to_bin(char *hex_string,int len,int *olen)
|
|
{
|
|
int
|
|
j=0;
|
|
int
|
|
bin_len=0,
|
|
n=0,
|
|
i;
|
|
|
|
unsigned char
|
|
value,
|
|
*out,
|
|
space[4];
|
|
|
|
char
|
|
*cp=hex_string;
|
|
|
|
if (! hex_string || ! len)
|
|
return(NULL);
|
|
|
|
if ((*cp == '0') && ((*(cp + 1) == 'x') || (*(cp + 1) == 'X')))
|
|
{
|
|
cp += 2;
|
|
n=2;
|
|
}
|
|
|
|
/*
|
|
** allocate half of hex_string as the length of binary.
|
|
** we may be allocated more than needed as : - etc may be
|
|
** part of the hex string
|
|
*/
|
|
bin_len=(len >> 1);
|
|
if (bin_len <= 0)
|
|
return(NULL);
|
|
|
|
out=(unsigned char *) malloc(bin_len*sizeof(unsigned char));
|
|
memset(out,0,bin_len);
|
|
for (i=n; i < len; i += 2)
|
|
{
|
|
if (hex_string[i] == '\n' || hex_string[i] == '\r' ||
|
|
hex_string[i] == ' ' || hex_string[i] == '\t' ||
|
|
hex_string[i] == ':' ||
|
|
hex_string[i] == '-' ||
|
|
hex_string[i] == '_')
|
|
{
|
|
i--;
|
|
continue;
|
|
}
|
|
if (isxdigit(hex_string[i]) && isxdigit(hex_string[i+1]))
|
|
{
|
|
value=(mutils_hex_char_to_bin (hex_string[i]) << 4) & 0xf0;
|
|
value |= (mutils_hex_char_to_bin(hex_string[i+1]) & 0x0f);
|
|
out[j++]=value;
|
|
}
|
|
}
|
|
*olen=j;
|
|
|
|
return(out);
|
|
}
|
|
|
|
/**
|
|
* @brief convert binary to hex
|
|
* @param input - binary data
|
|
* @param len - length of input data
|
|
* @param output - NULL terminated string equivalent in hex
|
|
* @return length of output string (not including NULL) on success, -1
|
|
* on failure
|
|
*
|
|
* Note: *output points to a malloc'd space, caller is responsible to
|
|
* to free it
|
|
* adapted from net-snmp 5.0.6 code (tools.c)
|
|
*/
|
|
int mutils_binary_to_hex(unsigned char *input,int len,char **output)
|
|
{
|
|
int
|
|
olen;
|
|
char
|
|
*s,
|
|
*op;
|
|
|
|
unsigned char
|
|
*ip;
|
|
|
|
olen=(len * 2) + 1;
|
|
s=(char *) calloc(1,olen);
|
|
if (s == NULL)
|
|
return (-1);
|
|
op=s;
|
|
|
|
ip=input;
|
|
while ((ip - input) < len)
|
|
{
|
|
*op++ = MUTILS_VAL2_HEX((*ip >> 4) & 0xf);
|
|
*op++ = MUTILS_VAL2_HEX(*ip & 0xf);
|
|
ip++;
|
|
}
|
|
*op='\0';
|
|
*output=s;
|
|
|
|
return(olen);
|
|
}
|
|
|
|
/**
|
|
* @brief convert binary to hex
|
|
* @param in binary data
|
|
* @param in_len length of input in bytes
|
|
* @param out output buffer to hold the converted hex data. in/out. The buffer is
|
|
* NULL terminated.
|
|
* @param out_len bytes of memroy pre allocated in out. out_len must be
|
|
* greater than in_len*2
|
|
* @return length of converted hex buffer on success, -1 on failure
|
|
*
|
|
* Note: this function is similar to mutils_binary_to_hex(), only differece is
|
|
* that in this function, the caller passes the pre-allocated buffer.
|
|
*/
|
|
int mutils_binary_to_hex_buf(unsigned char *in,int in_len,char *out,int *out_len)
|
|
{
|
|
char
|
|
*op;
|
|
|
|
unsigned char
|
|
*ip;
|
|
|
|
op=out;
|
|
ip=in;
|
|
if (*out_len < (in_len * 2) + 1)
|
|
{
|
|
*out_len=(-1);
|
|
(void) fprintf(stderr,"%s (%d) - outbuf must have atlease %d bytes of space pre-allocated\n",
|
|
MUTILS_CFL,((in_len * 2) + 1));
|
|
return(-1);
|
|
}
|
|
|
|
*out_len=(in_len * 2);
|
|
while ((ip - in) < in_len)
|
|
{
|
|
*op++ = MUTILS_VAL2_HEX((*ip >> 4) & 0xf);
|
|
*op++ = MUTILS_VAL2_HEX(*ip & 0xf);
|
|
ip++;
|
|
}
|
|
*op='\0';
|
|
return(*out_len);
|
|
}
|
|
|
|
|
|
/*
|
|
** return MUTILS_TRUE if the file is binary. MUTILS_FALSE otherwise.
|
|
** return -1 on error
|
|
** The algorithm is adapted from Perl pp_fttext()
|
|
** 512 bytes of file is used.
|
|
**
|
|
** here is the algorithm (perldoc -I -B|more)
|
|
The "-T" and "-B" switches work as follows. The first block or
|
|
so of the file is examined for odd characters such as strange
|
|
control codes or characters with the high bit set. If too many
|
|
strange characters (>30%) are found, it's a "-B" file;
|
|
otherwise it's a "-T" file. Also, any file containing a zero
|
|
byte in the first block is considered a binary file
|
|
*/
|
|
int mutils_file_is_binary(const char *file)
|
|
{
|
|
struct stat
|
|
sbuf;
|
|
|
|
FILE
|
|
*fp = NULL;
|
|
|
|
char
|
|
*s,
|
|
buf[513];
|
|
|
|
size_t
|
|
len;
|
|
int
|
|
i,
|
|
sz,
|
|
n;
|
|
|
|
int
|
|
odd = 0;
|
|
|
|
float
|
|
x;
|
|
|
|
sz = sizeof(buf) - 1;
|
|
if (stat(file, &sbuf) != 0)
|
|
{
|
|
(void) fprintf(stderr,"Could not stat file %s\n",file);
|
|
return(-1);
|
|
}
|
|
len = sbuf.st_size;
|
|
if (len > 512)
|
|
{
|
|
len = 512;
|
|
}
|
|
fp = fopen(file, "rb");
|
|
if (fp == NULL)
|
|
{
|
|
(void) fprintf(stderr,"Error reading file: %s\n",file);
|
|
return(-1);
|
|
}
|
|
memset(buf, 0, sizeof(buf));
|
|
n = fread(buf, 1, len, fp);
|
|
if (n != len)
|
|
{
|
|
(void) fprintf(stderr,"read error\n");
|
|
return(-1);
|
|
}
|
|
|
|
s = buf;
|
|
|
|
if (len && len < sizeof(buf) && buf[len - 1] == 0x1a)
|
|
{
|
|
--len;
|
|
}
|
|
for (i=0; i < len; i++, s++)
|
|
{
|
|
if (!*s)
|
|
{
|
|
odd += len;
|
|
break;
|
|
}
|
|
else if (*s & 128)
|
|
{
|
|
if (UTF8_IS_START(*s))
|
|
{
|
|
int ulen = UTF8SKIP(*s);
|
|
if (ulen < len - i)
|
|
{
|
|
int
|
|
j;
|
|
for (j = 1; j < ulen; j++)
|
|
{
|
|
if (!UTF8_IS_CONTINUATION(s[j]))
|
|
{
|
|
goto NotUtf8;
|
|
}
|
|
}
|
|
--ulen;
|
|
s += ulen;
|
|
i += ulen;
|
|
continue;
|
|
}
|
|
}
|
|
NotUtf8:
|
|
odd++;
|
|
}
|
|
else
|
|
{
|
|
if (*s < 32 && *s != '\n' && *s != '\r' && *s != '\b' &&
|
|
*s != '\t' && *s != '\f' && *s != 27)
|
|
{
|
|
odd++;
|
|
}
|
|
}
|
|
}
|
|
x = ((odd * 1.0) / (len * 1.0));
|
|
if (x < 0.30)
|
|
{
|
|
return MUTILS_FALSE;
|
|
}
|
|
else
|
|
{
|
|
return MUTILS_TRUE;
|
|
}
|
|
|
|
|
|
ExitProcessing:
|
|
if (fp)
|
|
{
|
|
(void) fclose(fp);
|
|
}
|
|
return(-1);
|
|
}
|
|
|
|
|
|
|
|
#ifdef TEST
|
|
|
|
int main (int argc,char **argv)
|
|
{
|
|
int
|
|
rc;
|
|
|
|
rc=mutilsWhich(argv[1]);
|
|
(void) fprintf(stderr,"rc=%d\n",rc);
|
|
return(0);
|
|
}
|
|
#endif /* TEST */
|