public static string CanonicalDecode(string text)
{
/* RFC 2047
Generally, an "encoded-word" is a sequence of printable ASCII
characters that begins with "=?", ends with "?=", and has two "?"s in
between.
Syntax: =?charSet?type[Q or B]?encoded_string?=
Examples:
=?utf-8?q?Buy a Rolex?=
=?iso-8859-1?B?bORs5D8=?=
*/
StringBuilder retVal = new StringBuilder();
int offset = 0;
while(offset < text.Length){
// Search start and end of canonical entry
int iStart = text.IndexOf("=?",offset);
int iEnd = -1;
if(iStart > -1){
// End index must be over start index position
iEnd = text.IndexOf("?=",iStart + 2);
}
if(iStart > -1 && iEnd > -1){
// Add left side non encoded text of encoded text, if there is any
if((iStart - offset) > 0){
retVal.Append(text.Substring(offset,iStart - offset));
}
while(true){
// Check if it is encoded entry
string[] charset_type_text = text.Substring(iStart + 2,iEnd - iStart - 2).Split('?');
if(charset_type_text.Length == 3){
// Try to parse encoded text
try{
Encoding enc = Encoding.GetEncoding(charset_type_text[0]);
// QEecoded text
if(charset_type_text[1].ToLower() == "q"){
retVal.Append(Core.QDecode(enc,charset_type_text[2]));
}
// Base64 encoded text
else{
retVal.Append(enc.GetString(Core.Base64Decode(Encoding.Default.GetBytes(charset_type_text[2]))));
}
}
catch{
// Parsing failed, just leave text as is.
retVal.Append(text.Substring(iStart,iEnd - iStart + 2));
}
// Move current offset in string
offset = iEnd + 2;
break;
}
// This isn't right end tag, try next
else if(charset_type_text.Length < 3){
// Try next end tag
iEnd = text.IndexOf("?=",iEnd + 2);
// No suitable end tag for active start tag, move offset over start tag.
if(iEnd == -1){
retVal.Append("=?");
offset = iStart + 2;
break;
}
}
// Illegal start tag or start tag is just in side some text, move offset over start tag.
else{
retVal.Append("=?");
offset = iStart + 2;
break;
}
}
}
// There are no more entries
else{
// Add remaining non encoded text, if there is any.
if(text.Length > offset){
retVal.Append(text.Substring(offset));
offset = text.Length;
}
}
}
return retVal.ToString();
}