|
Hi,
Thank you for your work on this.
I tested you Quoted printable Encode function, and I see there is some issues, I had the last few bytes in the string cut off, and I see the table should have some more NOSKIPSs. I changed this:
#define SKIP '\202'
#define NOSKIP 'A'
#define XSKIP 'B'
#define MaxLineLength 76
const char QpEncodeMap[] = {
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, XSKIP, NOSKIP, SKIP, SKIP, NOSKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, XSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, SKIP, NOSKIP, NOSKIP, SKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP,
NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP,
NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP,
NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP,
NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP,
NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP,
NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP,
NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, NOSKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP
};
The XSKIP is for handling Tab and Space at the end of lines.
Here is the new Encode function, using std::stringstream for the result, and having std::string as input and return value to have the memory handling automatically taken care of.
std::string to_hex(unsigned char z) {
std::string hexmap = "0123456789ABCDEF";
std::string res = "=";
res += hexmap[(z & 0xF0) >> 4];
res += hexmap[z & 0x0F];
return res;
}
std::string encodeQPnew ( std::string text ) {
std::stringstream res;
unsigned char mid, nchar;
size_t len = text.size();
size_t linlen = 0;
for (size_t i=0; i<len; i++) {
mid = (256 - (0 - text[i]));
if (QpEncodeMap[mid] == XSKIP) { nchar = (i + 1 == len) ? '\r' : text[i + 1];
if (nchar == '\n' || nchar == '\r') {
res << to_hex(mid); linlen += 3;
} else {
res << text[i]; linlen++;
}
} else if ( mid == '\n') {
linlen=0; res << '\n';
} else if (QpEncodeMap[mid] == SKIP) { res << to_hex(mid);
linlen += 3;
} else { res << text[i];
linlen++;
}
if (linlen >= 76) {
res << "=\r\n";
linlen = 0;
}
}
return res.str();
}
This seems to work well encoding mail bodies.
mvh
Ole K Hornnes
|
|
|
|
|
Hi, in MSDN is "realloc returns a void pointer to the reallocated (and possibly moved)"
and "moved" is problem.
*(fresult++) = '=' etc. writes to bad place
Pavel
modified 29-Mar-12 10:16am.
|
|
|
|
|
Hi, the code does not support unicod.
Anyone has a unicode version?
|
|
|
|
|
void CUFMovImage::GetData(unsigned char* str)
{
int pBuffsize =strlen((char *) str); //Set pBuffsize !!!
pBase64 = Decode((char*)str, &pBuffsize);
if (image4.m_pPicture != NULL)
image4.UnLoad();
if (image4.m_pPicture == NULL)
{
image4.LoadFromBuffer((unsigned char*)pBase64,pBuffsize);
}
}
|
|
|
|
|
I think there´s a bug in the function that decodes the mail´s header. My problem was that the realloc gets out of memory. To fix that I´ve declared another char *, malloc memory for it, operating then with that string and returning it at the end.
Gr
|
|
|
|
|
Hi there
I use CBase64Utils to decode a b64 HTML code, and get the original code back. However, there is always a at the end of the decoded HTML? I try other decoder, also try the decode the same source with some email client, with which I can get the correct HTML! I am just wondering if it is a bug.
|
|
|
|
|
The bugs are still in the source code, even they are known since some time.
Is it to difficult to update the sources?
(Lost 1 hour to understand the 8-bit sign problem)
|
|
|
|
|
I found 2 bugs: one when encoding and one when decoding.
If you attempt to encode a 1 or 2 byte buffer, nothing will encode. The fix is to add:
+ if (bufsize > 2)
+ {
while (count <= bufsize)
... (about line 266) (and, of course, the closing paren!)
When decoding, the wrong length was reported (from line 423). Delete the line
resultlen++;
in the 'for' loop, and then after the loop, add
int nBits = (count % 4) * 6;
resultlen += nBits / 8;
I tested this with:
#define MAX_BITS 2000 // I varied this, started small
...
char bits[MAX_BITS];
for (int i = 1; i < MAX_BITS; ++i)
{
for (int l = 0; l < i; ++l)
bits[l] = i;
UINT nSize = l;
Base64 encode; // my wrapper
std::string moreBits = encode.Encode(bits, nSize); // minor change to api, guts are the same
Base64 decode; // separate object as I let it do the memory management
char* pOutput;
size_t len;
decode.Decode(moreBits, bits, len);
ASSERT(len == nSize);
ASSERT(memcmp(pOutput, bits, len) == 0);
}
...
David Connet
http://www.agilityrecordbook.com
|
|
|
|
|
|
I was using your code for a some time and I found that sometimes it fails to decode quoted-printable format of some e-mail messages.
I found that the problem is that those messages don't use capital letters in QP text.
Here is a modified code to handle decoding:
bool ok = true;
for (i = 0; i < 2; i++)
{
if (hexmap[ toupper(input[i]) ] == SKIP)
{
ok = false;
if (input[i] == '\r' && input[i + 1] == '\n')
{
input += 2;
break;
}
else
{
bError = TRUE;
}
}
mid[i] = toupper(input[i]);
}
My modification was to add toupper calls in those 2 places
Best regards!
Irek
Check out my software at: http://www.ireksoftware.com
|
|
|
|
|
I'm not sure I would call that an improvement. The MIME RFC specifies that the quoted printable characters must always be in uppercase ("Uppercase letters must be used; lowercase letters are not allowed." / RFC 20459). So using toupper would violate this requirement and hence make your implementing a bit buggier..
|
|
|
|
|
I agree. But the world is not perfect. There is a lot of software around that produces non RFC content. If you want to create a reliable e-mail reader (like in my case) you need to handle also a non fully RFC compatible messages (otherwise your users will start complaing that your e-mail reader sometimes don't work (and MS Outlook has no problem to decode the message)).
Check out my software at: http://www.ireksoftware.com
|
|
|
|
|
Line: 322 in AMMimeUtils.cpp
Function: CBase64Utils::Encode(char *input, int bufsize)
320: unsigned char mid = (256 - (0 - *s));
321: tmp |= mid;
322: //tmp |= *s;
323: tmp <<= 8;
324: count++;
325: s++;
KG
|
|
|
|
|
Yes, i think it is correkt to delete line 322.
|
|
|
|
|
your softwar doesn't work if you have lot of "=?iso-8859-1?Q?" in the string (exception....)
and you've some troubles with your free !!!!
DevCrazy
|
|
|
|
|
I can't see how this class will be able to encode/decode binary data since input values are char instead of unsigned char.
I tried to encoded an array of numbers without success
|
|
|
|
|
I needed also this feature. In fact the char is not a problem here. The problem is that output is threated as a ascii string.
Here is a modified, stand alone decode funtion + unchanged hex table.
I decided also to dump some of pointers (I dont like using raw pointers too much) and added stl::string instead.
This is how I call this funtion to decode QP binnary attachment from mine message and write it to disk file:
char* pPointerToQPData;
std::string sOutput;
long lFileSize = QuotedPrintable_DecodeEx(pPointerToQPData, sOutput);
CFile file;
file.Open("C:\\file.bin", CFile::modeCreate|CFile::modeReadWrite);
file.Write(sOutput.c_str(), lFileSize);
file.Close();
----
the code:
#include <string>
#define SKIP '\202'
const char hexmap[] = {
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 ,
8 , 9 , SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, 10, 11, 12, 13, 14, 15, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP,
SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP, SKIP
};
int QuotedPrintable_DecodeEx(const char *input, std::string& a_sOutput)
{
BOOL bError = FALSE;
int iFileLen = 0;
a_sOutput.resize(strlen(input)+1);
while (*input != '\0')
{
if (*input == '=')
{
for (int i = 0; i < 3; i++)
{
if (input[i] == '\0')
{
bError = TRUE;
return iFileLen;
}
}
char mid[3];
input++;
bool ok = true;
for (i = 0; i < 2; i++)
{
if (hexmap[input[i]] == SKIP)
{
ok = false;
if (input[i] == '\r' && input[i + 1] == '\n')
{
input += 2;
break;
}
else
{
bError = TRUE;
}
}
mid[i] = input[i];
}
if (ok)
{
input += 2;
int m = hexmap[mid[0]];
m <<= 4;
m |= hexmap[mid[1]];
a_sOutput[iFileLen++] = m;
}
}
else
{
if (*input != '\0')
{
a_sOutput[iFileLen++] = *(input++);
}
}
}
return iFileLen;
}
Check out my software at: http://www.ireksoftware.com
|
|
|
|
|
Hi,
If its not too much trouble, can you tell me the algorithm that I can use with your class to predetermine the encoded length of an uncoded buffer.
For example, lets say that I will be encoding a file of data and the filelength is 100. I'm looking for an algorithm to tell me how large the encoded data will be without doing the actual encoding.
Thanks for any help that you can offer.
--Paul K.
|
|
|
|
|
I see the line in your BASE64 encoder routine:
int alsize = ((bufsize * 4) / 3);
char *finalresult = (char*)calloc(alsize + ((alsize / MaxLineLength) * 2) + (10 * sizeof(char)), sizeof(char));
So you do the standard calc. of * 4 / 3. Then to add in 2 bytes for every line break. But what about this 10 extra bytes tack on at the end. Is this to account for any possible "=" padding characters???
Would this be correct to get the EXACT number of bytes required for the encoded buffer?:
int alsize = ((bufsize * 4) / 3); // Basic calc.
alsize = alsize + ((alsize / MaxLineLength) * 2) // Add CRLFs
while( bufsize % 4 != 0 ) // Add padding amount if needed.
alsize++;
I'd just to the encoding and get the length of the string returned but in my case I have to know the length beforehand.
--Paul K.
|
|
|
|
|
That looks ok
- Anders
Money talks, but all mine ever says is "Goodbye!"
|
|
|
|
|
This code return a truncated string :
CQPUtils qp2;
char *result22 = qp2.Encode(buf);
Example: Microsoft welcome message in Outlook after calling this routine looks like:
<http: outlook="" outlook9="" specs="" welcomemsg="" icons.gif="">
<http: outlook="" outlook9="" specs="" welcomemsg="" yellowbg.gif="">
<http: outlook="" outlook9="" specs="" welcomemsg="" olicon.gif="">
Welcome to
Microsoft Outlook 2000
One Window to Your World of Information
=9
----
The string is much longer than this.
Please help
|
|
|
|
|
I think I found the bug:
when mids = "9", mids[1]='\0' and it will insert '\0' and terminate the string!
//add the hex value for the char...
char mids[3];
itoa(mid, mids, 16);
strupr(mids);
*(fresult++) = '=';
*(fresult++) = mids[0];
*(fresult++) = mids[1];
UsedSize += 3;
LineLen += 2;
s++;
|
|
|
|
|
Hey thanks, I'll take a look at it
- Anders
Money talks, but all mine ever says is "Goodbye!"
|
|
|
|
|
Change line
//check to see if it's a legal base64 char...
while (base64map[*s] == SKIP)
to
//check to see if it's a legal base64 char...
while (base64map[(unsigned char)(*s)] == SKIP)
|
|
|
|
|
I test the decode fun can decode the .txt file,but .jpg and .word can't!
|
|
|
|
|