Mailer
/* $Id$ */
/* Copyright (c) 2012-2018 Pierre Pronchery <khorben@defora.org> */
/* This file is part of DeforaOS Desktop Mailer */
/* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 THE COPYRIGHT
* HOLDER OR CONTRIBUTORS 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 <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "../include/Mailer/helper.h"
/* public */
/* functions */
/* mailer_helper_get_date */
static int _date_do(char const * date, char const * format, struct tm * tm);
time_t mailer_helper_get_date(char const * date, struct tm * tm)
{
time_t t;
if(date != NULL)
/* FIXME check the standard(s) again */
if(_date_do(date, "%a, %d %b %Y %T %z (%z)", tm) == 0
|| _date_do(date, "%a, %d %b %Y %T %z", tm) == 0
|| _date_do(date, "%d %b %Y %T %z", tm) == 0
|| _date_do(date, "%d/%m/%Y %T %z", tm) == 0
|| _date_do(date, "%d/%m/%Y %T", tm) == 0
|| _date_do(date, "%FT%TZ", tm) == 0)
{
/* fix the date if missing the century */
if(tm->tm_year >= -1830 && tm->tm_year < -1800)
tm->tm_year += 1900;
else if(tm->tm_year >= -1900 && tm->tm_year < -1830)
tm->tm_year += 2000;
return mktime(tm);
}
/* XXX fallback to the current time and date */
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, date);
#endif
t = time(NULL);
gmtime_r(&t, tm);
return t;
}
static int _date_do(char const * date, char const * format, struct tm * tm)
{
char const * p;
memset(tm, 0, sizeof(*tm));
if((p = strptime(date, format, tm)) != NULL && *p == '\0')
return 0;
/* check if we obtained enough information */
if(p != NULL && tm->tm_year != 0 && tm->tm_mday != 0)
/* XXX _apparently_ yes */
return 0;
return -1;
}
/* mailer_helper_get_email */
char * mailer_helper_get_email(char const * header)
{
char * ret;
size_t len;
char * buf = NULL;
if(header == NULL)
return NULL;
len = strlen(header);
if((ret = malloc(len + 1)) == NULL || (buf = malloc(len + 1)) == NULL)
{
free(buf);
free(ret);
return NULL;
}
if(mailer_helper_is_email(header))
{
strcpy(ret, header);
free(buf);
return ret;
}
if(sscanf(header, "%[^(](%[^)])", ret, buf) == 2
|| sscanf(header, "<%[^>]>", ret) == 1
|| sscanf(header, "%[^<]<%[^>]>", buf, ret) == 2)
{
for(len = strlen(ret); len > 0
&& isblank((unsigned char)ret[len - 1]); len--)
ret[len - 1] = '\0';
if(mailer_helper_is_email(ret))
{
free(buf);
return ret;
}
}
free(buf);
free(ret);
return NULL;
}
/* mailer_helper_get_name */
char * mailer_helper_get_name(char const * header)
{
char * ret;
size_t len;
char * buf = NULL;
int c;
if(header == NULL)
return NULL;
len = strlen(header);
if((ret = malloc(len + 1)) == NULL || (buf = malloc(len + 1)) == NULL)
{
free(buf);
free(ret);
return NULL;
}
if(mailer_helper_is_email(header))
{
strcpy(ret, header);
free(buf);
return ret;
}
if(sscanf(header, "%[^(](%[^)])", buf, ret) != 2
&& sscanf(header, "<%[^>]>", ret) != 1
&& sscanf(header, "%[^<]<%[^>]>", ret, buf) != 2)
{
free(buf);
free(ret);
return NULL;
}
free(buf);
/* right-trim spaces */
for(len = strlen(ret); --len > 0
&& isspace((unsigned char)ret[len]); ret[len] = '\0');
/* remove surrounding quotes */
if((len = strlen(ret)) >= 2 && ((c = ret[0]) == '"' || c == '\'')
&& ret[len - 1] == c)
{
memmove(ret, &ret[1], len - 2);
ret[len - 2] = '\0';
}
return ret;
}
/* mailer_helper_is_email */
int mailer_helper_is_email(char const * header)
{
size_t i = 0;
int c;
/* FIXME this is neither strict nor standard at the moment */
for(i = 0; (c = (unsigned char)header[i]) != '@'; i++)
if(c == '\0')
return 0;
else if(!isalnum(c) && c != '.' && c != '_')
return 0;
for(i++; (c = (unsigned char)header[i]) != '\0'; i++)
if(!isalnum(c) && c != '.' && c != '_')
return 0;
return 1;
}