src/mui/Base64Dataspace.c
/***************************************************************************
YAM - Yet Another Mailer
Copyright (C) 1995-2000 Marcel Beck
Copyright (C) 2000-2022 YAM Open Source Team
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
YAM Official Support Site : http://www.yam.ch
YAM OpenSource project : http://sourceforge.net/projects/yamos/
$Id$
Superclass: MUIC_Dataspace
Description: Dataspace object using a base64 encoded string in memory
***************************************************************************/
#include "Base64Dataspace_cl.h"
#include <stdlib.h>
#include <string.h>
#include "mime/base64.h"
#include "Debug.h"
/* CLASSDATA
struct Data
{
char *base64String;
};
*/
/* EXPORT
#define EMPTY_B64DSPACE_STRING "0;0;"
*/
/* Private Functions */
/// EncodeData
// build a base64 encoded string of the data to be added looking like this:
// llllllll;iiiiiiii;ddddddddd......
// l = data length
// i = object id
// d = data
static char *EncodeData(APTR data, LONG len, ULONG id)
{
char *b64_buffer;
size_t b64_len;
ENTER();
if((b64_len = base64encode(&b64_buffer, data, len)) > 0)
{
char *tmp;
if(asprintf(&tmp, "%08d;%08x;%s", (int)len, (int)id, b64_buffer) != -1)
{
free(b64_buffer);
b64_buffer = tmp;
}
}
RETURN(b64_buffer);
return b64_buffer;
}
///
/// DecodeData
static BOOL DecodeData(const char *base64String, APTR *pdata, LONG *plen, ULONG *pid)
{
BOOL success = FALSE;
ENTER();
if(base64String != NULL)
{
char *dupe;
// we are going to modify the string so we must operated on a copy
if((dupe = strdup(base64String)) != NULL)
{
char *data = NULL;
LONG len = 0;
ULONG id = 0;
char *word = dupe;
char *next;
int i = 0;
// parse the string, there must be 3 substrings
do
{
// split the string into words separated by semicolons
if((next = strpbrk(word, ";")) != NULL)
*next++ = '\0';
switch(i)
{
case 0:
len = strtol(word, NULL, 10);
break;
case 1:
id = strtol(word, NULL, 16);
break;
case 2:
data = word;
break;
}
word = next;
i++;
}
while(word != NULL);
if(len > 0 && id != 0 && data != NULL)
{
char *raw = NULL;
// now convert the base64 string back to raw data
// everything is ok if the decoded amount of data matches the predicted size
if(base64decode(&raw, data, strlen((char *)data)) == len)
{
*pdata = raw;
*plen = len;
*pid = id;
success = TRUE;
}
else if(raw != NULL)
free(raw);
}
free(dupe);
}
}
RETURN(success);
return success;
}
///
/// ImportBase64String
static BOOL ImportBase64String(struct IClass *cl, Object *obj, const char *base64String)
{
GETDATA;
BOOL success = FALSE;
APTR rawData;
LONG len;
ULONG id;
ENTER();
// decode the string
if(DecodeData(base64String, &rawData, &len, &id) == TRUE)
{
// now pass the data to our superclass
if(DoSuperMethod(cl, obj, MUIM_Dataspace_Add, rawData, len, id) != (IPTR)NULL)
{
// free any previous contents and remember the new one
free(data->base64String);
data->base64String = strdup(base64String);
success = TRUE;
}
// the parsed raw data are no longer needed
free(rawData);
}
RETURN(success);
return success;
}
///
/* Overloaded Methods */
/// OVERLOAD(OM_NEW)
OVERLOAD(OM_NEW)
{
ENTER();
if((obj = DoSuperNew(cl, obj,
TAG_MORE, inittags(msg))) != NULL)
{
char *base64String;
if((base64String = (char *)GetTagData(ATTR(Base64String), (IPTR)NULL, inittags(msg))) != NULL)
ImportBase64String(cl, obj, base64String);
}
RETURN((IPTR)obj);
return (IPTR)obj;
}
///
/// OVERLOAD(OM_DISPOSE)
OVERLOAD(OM_DISPOSE)
{
GETDATA;
free(data->base64String);
data->base64String = NULL;
return DoSuperMethodA(cl, obj, msg);
}
///
/// OVERLOAD(OM_GET)
OVERLOAD(OM_GET)
{
GETDATA;
IPTR *store = ((struct opGet *)msg)->opg_Storage;
switch(((struct opGet *)msg)->opg_AttrID)
{
case ATTR(Base64String):
{
// we always return a valid string
if(data->base64String != NULL)
*store = (IPTR)data->base64String;
else
*store = (IPTR)EMPTY_B64DSPACE_STRING;
return TRUE;
}
}
return DoSuperMethodA(cl, obj, msg);
}
///
/// OVERLOAD(OM_SET)
OVERLOAD(OM_SET)
{
GETDATA;
struct TagItem *tags = inittags(msg), *tag;
while((tag = NextTagItem((APTR)&tags)) != NULL)
{
switch(tag->ti_Tag)
{
case ATTR(Base64String):
{
free(data->base64String);
data->base64String = NULL;
ImportBase64String(cl, obj, (char *)tag->ti_Data);
tag->ti_Tag = TAG_IGNORE;
}
break;
}
}
return DoSuperMethodA(cl, obj, msg);
}
///
/// OVERLOAD(MUIM_Dataspace_Add)
OVERLOAD(MUIM_Dataspace_Add)
{
GETDATA;
struct MUIP_Dataspace_Add *add = (struct MUIP_Dataspace_Add *)msg;
char *base64String;
APTR result = NULL;
ENTER();
// first build our private encoded string
if((base64String = EncodeData(add->data, add->len, add->id)) != NULL)
{
// then let Dataspace.mui add the data for the given ID
if((result = (APTR)DoSuperMethodA(cl, obj, msg)) != NULL)
{
free(data->base64String);
data->base64String = base64String;
}
else
{
free(base64String);
}
}
RETURN((IPTR)result);
return (IPTR)result;
}
///
/// OVERLOAD(MUIM_Dataspace_Remove)
OVERLOAD(MUIM_Dataspace_Remove)
{
GETDATA;
APTR result;
ENTER();
if((result = (APTR)DoSuperMethodA(cl, obj, msg)) != NULL)
{
// erase the encoded string if removing the ID was successful
free(data->base64String);
data->base64String = NULL;
}
RETURN((IPTR)result);
return (IPTR)result;
}
///