/// <summary> /// Decoded and merges all the token from the specified list. /// </summary> public void Decode() { StringBuilder sb = new StringBuilder(); EncodedWord previousEncodedWord = null; foreach (EncodedWord encodedWord in _encodedWords) { string value = encodedWord.ReadableValue; if (encodedWord.IsEncoded) { if (previousEncodedWord != null) { if (!previousEncodedWord.IsEncoded) { value = encodedWord.Prefix + value; } } } sb.Append(value); previousEncodedWord = encodedWord; } _decoded = sb.ToString(); }
/// <summary> /// Determines if the current encoded word has the same encoding name and encoding type /// </summary> public bool IsCompatibleWith(EncodedWord other) { if (!IsEncoded || !other.IsEncoded) { return(false); } return(string.Equals(EncodingName, other.EncodingName, StringComparison.InvariantCultureIgnoreCase) && string.Equals(EncodingType, other.EncodingType, StringComparison.InvariantCultureIgnoreCase)); }
/// <summary> /// Determines if the next token in the list (if any) match the encoded word regular expression and has the same encoding and charset values /// </summary> private bool NextTokenIsCompatible(EncodedWord encodedWord, int currentIndex) { if (currentIndex + 1 >= _encodedWords.Count) { return(false); } var nextEncodedWord = _encodedWords[currentIndex + 1]; return(encodedWord.IsCompatibleWith(nextEncodedWord)); }
/// <summary> /// Ctor /// </summary> public EncodedWords(string value) { if (string.IsNullOrWhiteSpace(value)) { _decoded = null; } else { _encodedWords = EncodedWord.Parse(value); MergeContiguousCompatibleEncodedTokens(); Decode(); } }
/// <summary> /// Merges together two encoded words and returns the correct encoded word string that will match the regular expression /// </summary> private string MergeEncodedValues(EncodedWord encodedWord) { string encodedData1 = EncodedData; string encodedData2 = encodedWord.EncodedData; string encodingType = EncodingType; string encodedData; if (encodingType == "B") { byte[] decodedData1 = Convert.FromBase64String(encodedData1); byte[] decodedData2 = Convert.FromBase64String(encodedData2); encodedData = Convert.ToBase64String(decodedData1.Concat(decodedData2).ToArray()); } else { encodedData = encodedData1 + encodedData2; } return(string.Format("=?{0}?{1}?{2}?=", EncodingName, encodingType, encodedData)); }
/// <summary> /// If happens that when having multiple contiguous encoded words (specially binary, an encoded word is splitted on a byte boundary example : C3 A9 /// represents the à character and the first encoded word can contain the C3 and the second encoded word contains A0. This method with modify /// the list of tokens so when the same encoding and charset are used for multiple tokens, they will be merge together /// </summary> private void MergeContiguousCompatibleEncodedTokens() { bool doneSomeThing = false; do { doneSomeThing = false; for (int i = 0; i < _encodedWords.Count; i++) { var encodedWord = _encodedWords[i]; if (NextTokenIsCompatible(encodedWord, i)) { EncodedWord nextEncodedWord = _encodedWords[i + 1]; encodedWord.Merge(nextEncodedWord); _encodedWords.RemoveAt(i + 1); doneSomeThing = true; break; } } } while (doneSomeThing); }
/// <summary> /// Merges together two encoded words and returns the correct encoded word string that will match the regular expression /// </summary> private string MergeEncodedValues(EncodedWord encodedWord) { string encodedData1 = EncodedData; string encodedData2 = encodedWord.EncodedData; string encodingType = EncodingType; string encodedData; if (encodingType == "B") { byte[] decodedData1 = Convert.FromBase64String(encodedData1); byte[] decodedData2 = Convert.FromBase64String(encodedData2); encodedData = Convert.ToBase64String(decodedData1.Concat(decodedData2).ToArray()); } else { encodedData = encodedData1 + encodedData2; } return string.Format("=?{0}?{1}?{2}?=", EncodingName, encodingType, encodedData); }
/// <summary> /// Merges the specified encoded word into this instance. /// /// This method assumes the encoded words are compatible /// </summary> public void Merge(EncodedWord encodedWord) { Value = MergeEncodedValues(encodedWord); Match = _singleEncodedWordsPattern.Match(Value); }
/// <summary> /// Determines if the current encoded word has the same encoding name and encoding type /// </summary> public bool IsCompatibleWith(EncodedWord other) { if (!IsEncoded || !other.IsEncoded) { return false; } return string.Equals(EncodingName, other.EncodingName, StringComparison.InvariantCultureIgnoreCase) && string.Equals(EncodingType, other.EncodingType, StringComparison.InvariantCultureIgnoreCase); }
/// <summary> /// Determines if the next token in the list (if any) match the encoded word regular expression and has the same encoding and charset values /// </summary> private bool NextTokenIsCompatible(EncodedWord encodedWord, int currentIndex) { if (currentIndex + 1 >= _encodedWords.Count) { return false; } var nextEncodedWord = _encodedWords[currentIndex + 1]; return encodedWord.IsCompatibleWith(nextEncodedWord); }