imap: Implemented encoding RFC3501 strings.
* Was completely missing so far. * Fixed bug in decoding that handled the "&-" sequence incorrectly. * Added small test application that should easily be convertible to a unit test.
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011-2012, Axel Dörfler, [email protected].
|
* Copyright 2011-2013, Axel Dörfler, [email protected].
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <UnicodeChar.h>
|
||||||
|
|
||||||
|
|
||||||
#define TRACE_IMAP
|
#define TRACE_IMAP
|
||||||
#ifdef TRACE_IMAP
|
#ifdef TRACE_IMAP
|
||||||
@@ -53,8 +55,41 @@ RFC3501Encoding::~RFC3501Encoding()
|
|||||||
BString
|
BString
|
||||||
RFC3501Encoding::Encode(const BString& clearText) const
|
RFC3501Encoding::Encode(const BString& clearText) const
|
||||||
{
|
{
|
||||||
// TODO!
|
const char* clear = clearText.String();
|
||||||
return clearText;
|
bool shifted = false;
|
||||||
|
int32 bitsToWrite = 0;
|
||||||
|
int32 sextet = 0;
|
||||||
|
BString buffer;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
uint32 c = BUnicodeChar::FromUTF8(&clear);
|
||||||
|
if (c == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!shifted && c == '&')
|
||||||
|
buffer += "&-";
|
||||||
|
else if (c >= 0x20 && c <= 0x7e) {
|
||||||
|
_Unshift(buffer, bitsToWrite, sextet, shifted);
|
||||||
|
buffer += c;
|
||||||
|
} else {
|
||||||
|
// Enter shifted mode, encode in base64
|
||||||
|
if (!shifted) {
|
||||||
|
buffer += '&';
|
||||||
|
shifted = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bitsToWrite += 16;
|
||||||
|
while (bitsToWrite >= 6) {
|
||||||
|
bitsToWrite -= 6;
|
||||||
|
buffer += kBase64Alphabet[(sextet + (c >> bitsToWrite)) & 0x3f];
|
||||||
|
sextet = 0;
|
||||||
|
}
|
||||||
|
sextet = (c << (6 - bitsToWrite)) & 0x3f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_Unshift(buffer, bitsToWrite, sextet, shifted);
|
||||||
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -69,6 +104,7 @@ RFC3501Encoding::Decode(const BString& encodedText) const
|
|||||||
if (i < end - 1 && encodedText.ByteAt(i + 1) == '-') {
|
if (i < end - 1 && encodedText.ByteAt(i + 1) == '-') {
|
||||||
// just add an ampersand
|
// just add an ampersand
|
||||||
buffer += '&';
|
buffer += '&';
|
||||||
|
i++;
|
||||||
} else {
|
} else {
|
||||||
// base64 encoded chunk
|
// base64 encoded chunk
|
||||||
uint32 value = 0;
|
uint32 value = 0;
|
||||||
@@ -134,6 +170,23 @@ RFC3501Encoding::_ToUTF8(BString& string, uint32 c) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//! Exit base64, or "shifted" mode.
|
||||||
|
void
|
||||||
|
RFC3501Encoding::_Unshift(BString& buffer, int32& bitsToWrite, int32& sextet,
|
||||||
|
bool& shifted) const
|
||||||
|
{
|
||||||
|
if (!shifted)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (bitsToWrite != 0)
|
||||||
|
buffer += kBase64Alphabet[sextet];
|
||||||
|
buffer += '-';
|
||||||
|
sextet = 0;
|
||||||
|
bitsToWrite = 0;
|
||||||
|
shifted = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2011, Axel Dörfler, [email protected].
|
* Copyright 2011-2013, Axel Dörfler, [email protected].
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef RESPONSE_H
|
#ifndef RESPONSE_H
|
||||||
@@ -30,6 +30,8 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void _ToUTF8(BString& string, uint32 c) const;
|
void _ToUTF8(BString& string, uint32 c) const;
|
||||||
|
void _Unshift(BString& string, int32& bitsToWrite,
|
||||||
|
int32& sextet, bool& shifted) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,13 @@ SimpleTest imap_tester :
|
|||||||
: be [ TargetLibstdc++ ] [ TargetLibsupc++ ] bnetapi mail
|
: be [ TargetLibstdc++ ] [ TargetLibsupc++ ] bnetapi mail
|
||||||
;
|
;
|
||||||
|
|
||||||
|
SimpleTest rfc3501_encoding_test :
|
||||||
|
rfc3501_encoding_test.cpp
|
||||||
|
$(libSources)
|
||||||
|
|
||||||
|
: be $(TARGET_LIBSTDC++) $(TARGET_LIBSUPC++) bnetapi
|
||||||
|
;
|
||||||
|
|
||||||
SEARCH on [ FGristFiles $(libSources) ]
|
SEARCH on [ FGristFiles $(libSources) ]
|
||||||
= [ FDirName $(HAIKU_TOP) src add-ons mail_daemon inbound_protocols imap
|
= [ FDirName $(HAIKU_TOP) src add-ons mail_daemon inbound_protocols imap
|
||||||
imap_lib ] ;
|
imap_lib ] ;
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013, Axel Dörfler, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "Response.h"
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
assertEquals(const char* expected, const char* result)
|
||||||
|
{
|
||||||
|
if (strcmp(expected, result) != 0) {
|
||||||
|
printf("Expected \"%s\", got \"%s\"\n", expected, result);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
main()
|
||||||
|
{
|
||||||
|
const char* samples[] = {
|
||||||
|
"Gelöscht", "Gel&APY-scht",
|
||||||
|
"&äöß", "&-&AOQA9gDf-"
|
||||||
|
};
|
||||||
|
|
||||||
|
IMAP::RFC3501Encoding encoding;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < sizeof(samples) / sizeof(samples[0]); i += 2) {
|
||||||
|
BString encoded = encoding.Encode(samples[i]);
|
||||||
|
assertEquals(samples[i + 1], encoded);
|
||||||
|
BString decoded = encoding.Decode(encoded);
|
||||||
|
assertEquals(samples[i], decoded);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user