Bug 853159 - Merge hex decoding functions throughout mailnews. r=Neil, r=Standard8

This commit is contained in:
aceman 2014-05-19 12:03:00 -04:00
Родитель bb56319f74
Коммит 0fe1f32fea
9 изменённых файлов: 88 добавлений и 143 удалений

Просмотреть файл

@ -31,6 +31,7 @@
#include "nsIPrefBranch.h"
#include "nsIAbManager.h"
#include "mozilla/Services.h"
#include <algorithm>
#define ID_PAB_TABLE 1
#define ID_DELETEDCARDS_TABLE 2
@ -2248,25 +2249,8 @@ nsresult nsAddrDatabase::GetStringColumn(nsIMdbRow *cardRow, mdb_token outToken,
void nsAddrDatabase::YarnToUInt32(struct mdbYarn *yarn, uint32_t *pResult)
{
uint32_t i, result, numChars;
char *p = (char *) yarn->mYarn_Buf;
if (yarn->mYarn_Fill > 8)
numChars = 8;
else
numChars = yarn->mYarn_Fill;
for (i=0, result = 0; i < numChars; i++, p++)
{
char C = *p;
int8_t unhex = ((C >= '0' && C <= '9') ? C - '0' :
((C >= 'A' && C <= 'F') ? C - 'A' + 10 :
((C >= 'a' && C <= 'f') ? C - 'a' + 10 : -1)));
if (unhex < 0)
break;
result = (result << 4) | unhex;
}
*pResult = result;
uint8_t numChars = std::min<mdb_fill>(8, yarn->mYarn_Fill);
*pResult = MsgUnhex((char *) yarn->mYarn_Buf, numChars);
}
nsresult nsAddrDatabase::GetIntColumn

Просмотреть файл

@ -7,6 +7,7 @@
#include "nsMsgFolderCacheElement.h"
#include "prmem.h"
#include "nsISupportsObsolete.h"
#include "nsMsgUtils.h"
nsMsgFolderCacheElement::nsMsgFolderCacheElement()
{
@ -66,18 +67,15 @@ NS_IMETHODIMP nsMsgFolderCacheElement::GetInt32Property(const char *propertyName
if (resultStr.IsEmpty())
return NS_ERROR_FAILURE;
int32_t result = 0;
for (uint32_t index = 0; index < resultStr.Length(); index++)
// This must be an inverse function to nsCString.AppentInt(),
// which uses snprintf("%x") internally, so that the wrapped negative numbers
// are decoded properly.
if (PR_sscanf(resultStr.get(), "%x", aResult) != 1)
{
char C = resultStr.CharAt(index);
int8_t unhex = ((C >= '0' && C <= '9') ? C - '0' :
((C >= 'A' && C <= 'F') ? C - 'A' + 10 :
((C >= 'a' && C <= 'f') ? C - 'a' + 10 : -1)));
if (unhex < 0)
break;
result = (result << 4) | unhex;
NS_WARNING("Unexpected failure to decode hex string.");
return NS_ERROR_FAILURE;
}
*aResult = result;
return NS_OK;
}
@ -115,6 +113,9 @@ NS_IMETHODIMP nsMsgFolderCacheElement::SetInt32Property(const char *propertyName
{
NS_ENSURE_ARG_POINTER(propertyName);
NS_ENSURE_TRUE(m_mdbRow, NS_ERROR_FAILURE);
// This also supports encoding negative numbers into hex
// by integer wrapping them (e.g. -1 -> "ffffffff").
nsAutoCString propertyStr;
propertyStr.AppendInt(propertyValue, 16);
return SetStringProperty(propertyName, propertyStr);

Просмотреть файл

@ -1647,21 +1647,18 @@ NS_MSG_BASE void MsgStripQuotedPrintable (unsigned char *src)
while (src[srcIdx] != 0)
{
// Decode sequence of '=XY' into a character with code XY.
if (src[srcIdx] == '=')
{
unsigned char *token = &src[srcIdx];
unsigned char c = 0;
// decode the first quoted char
if (token[1] >= '0' && token[1] <= '9')
c = token[1] - '0';
else if (token[1] >= 'A' && token[1] <= 'F')
c = token[1] - ('A' - 10);
else if (token[1] >= 'a' && token[1] <= 'f')
c = token[1] - ('a' - 10);
if (MsgIsHex((const char*)src + srcIdx + 1, 2)) {
// If we got here, we successfully decoded a quoted printable sequence,
// so bump each pointer past it and move on to the next char.
dest[destIdx++] = MsgUnhex((const char*)src + srcIdx + 1, 2);
srcIdx += 3;
}
else
{
// first char after '=' isn't hex. check if it's a normal char
// If first char after '=' isn't hex check if it's a normal char
// or a soft line break. If it's a soft line break, eat the
// CR/LF/CRLF.
if (src[srcIdx + 1] == '\r' || src[srcIdx + 1] == '\n')
@ -1674,33 +1671,12 @@ NS_MSG_BASE void MsgStripQuotedPrintable (unsigned char *src)
srcIdx++;
}
}
else // normal char, copy it.
else // The first or second char after '=' isn't hex, just copy the '='.
{
dest[destIdx++] = src[srcIdx++]; // aka token[0]
dest[destIdx++] = src[srcIdx++];
}
continue;
}
// decode the second quoted char
c = (c << 4);
if (token[2] >= '0' && token[2] <= '9')
c += token[2] - '0';
else if (token[2] >= 'A' && token[2] <= 'F')
c += token[2] - ('A' - 10);
else if (token[2] >= 'a' && token[2] <= 'f')
c += token[2] - ('a' - 10);
else
{
// second char after '=' isn't hex. copy the '=' as a normal char and keep going
dest[destIdx++] = src[srcIdx++]; // aka token[0]
continue;
}
// if we got here, we successfully decoded a quoted printable sequence,
// so bump each pointer past it and move on to the next char;
dest[destIdx++] = c;
srcIdx += 3;
}
else
dest[destIdx++] = src[srcIdx++];
@ -1903,6 +1879,7 @@ NS_MSG_BASE void MsgCompressWhitespace(nsCString& aString)
aString.SetLength(end - start);
}
NS_MSG_BASE void MsgReplaceChar(nsString& str, const char *set, const char16_t replacement)
{
char16_t *c_str = str.BeginWriting();
@ -2235,6 +2212,42 @@ NS_MSG_BASE uint64_t ParseUint64Str(const char *str)
#endif
}
NS_MSG_BASE uint64_t MsgUnhex(const char *aHexString, size_t aNumChars)
{
// Large numbers will not fit into uint64_t.
NS_ASSERTION(aNumChars <= 16, "Hex literal too long to convert!");
uint64_t result = 0;
for (size_t i = 0; i < aNumChars; i++)
{
unsigned char c = aHexString[i];
uint8_t digit;
if ((c >= '0') && (c <= '9'))
digit = (c - '0');
else if ((c >= 'a') && (c <= 'f'))
digit = ((c - 'a') + 10);
else if ((c >= 'A') && (c <= 'F'))
digit = ((c - 'A') + 10);
else
break;
result = (result << 4) | digit;
}
return result;
}
NS_MSG_BASE bool MsgIsHex(const char *aHexString, size_t aNumChars)
{
for (size_t i = 0; i < aNumChars; i++)
{
if (!isxdigit(aHexString[i]))
return false;
}
return true;
}
NS_MSG_BASE nsresult
MsgStreamMsgHeaders(nsIInputStream *aInputStream, nsIStreamListener *aConsumer)
{

Просмотреть файл

@ -533,4 +533,16 @@ uint32_t MsgCountChar(nsAString &aString, char16_t aChar) {
#endif
/**
* Converts a hex string into an integer.
* Processes up to aNumChars characters or the first non-hex char.
* It is not an error if less than aNumChars valid hex digits are found.
*/
NS_MSG_BASE uint64_t MsgUnhex(const char *aHexString, size_t aNumChars);
/**
* Checks if a string is a valid hex literal containing at least aNumChars digits.
*/
NS_MSG_BASE bool MsgIsHex(const char *aHexString, size_t aNumChars);
#endif

Просмотреть файл

@ -935,10 +935,6 @@ nsMsgSendLater::DeleteCurrentMessage()
// representation. Arguably, we could allow Lines to escape, but it's not
// required by NNTP.)
//
#define UNHEX(C) \
((C >= '0' && C <= '9') ? C - '0' : \
((C >= 'A' && C <= 'F') ? C - 'A' + 10 : \
((C >= 'a' && C <= 'f') ? C - 'a' + 10 : 0)))
nsresult
nsMsgSendLater::BuildHeaders()
{
@ -1095,14 +1091,10 @@ SEARCH_NEWLINE:
}
else if (do_flags_p)
{
int i;
char *s = value;
PR_ASSERT(*s != ' ' && *s != '\t');
m_flags = 0;
for (i=0 ; i<4 ; i++) {
m_flags = (m_flags << 4) | UNHEX(*s);
s++;
}
NS_ASSERTION(MsgIsHex(s, 4), "Expected 4 hex digits for flags.");
m_flags = MsgUnhex(s, 4);
}
if (*buf == '\r' || *buf == '\n')

Просмотреть файл

@ -3878,56 +3878,26 @@ nsresult nsMsgDatabase::RowCellColumnToCharPtr(nsIMdbRow *row, mdb_token columnT
// this is so we can leave default values as they were.
/* static */void nsMsgDatabase::YarnToUInt32(struct mdbYarn *yarn, uint32_t *pResult)
{
uint32_t result;
char *p = (char *) yarn->mYarn_Buf;
int32_t numChars = std::min((mdb_fill)8, yarn->mYarn_Fill);
int32_t i;
uint8_t numChars = std::min<mdb_fill>(8, yarn->mYarn_Fill);
if (numChars > 0)
{
for (i=0, result = 0; i<numChars; i++, p++)
{
char C = *p;
if (numChars == 0)
return;
int8_t unhex = ((C >= '0' && C <= '9') ? C - '0' :
((C >= 'A' && C <= 'F') ? C - 'A' + 10 :
((C >= 'a' && C <= 'f') ? C - 'a' + 10 : -1)));
if (unhex < 0)
break;
result = (result << 4) | unhex;
}
*pResult = result;
}
*pResult = MsgUnhex((char *) yarn->mYarn_Buf, numChars);
}
// WARNING - if yarn is empty, *pResult will not be changed!!!!
// this is so we can leave default values as they were.
/* static */void nsMsgDatabase::YarnToUInt64(struct mdbYarn *yarn, uint64_t *pResult)
{
uint64_t result;
char *p = (char *) yarn->mYarn_Buf;
int32_t numChars = std::min((mdb_fill)16, yarn->mYarn_Fill);
int32_t i;
uint8_t numChars = std::min<mdb_fill>(16, yarn->mYarn_Fill);
if (numChars > 0)
{
for (i = 0, result = 0; i < numChars; i++, p++)
{
char C = *p;
if (numChars == 0)
return;
int8_t unhex = ((C >= '0' && C <= '9') ? C - '0' :
((C >= 'A' && C <= 'F') ? C - 'A' + 10 :
((C >= 'a' && C <= 'f') ? C - 'a' + 10 : -1)));
if (unhex < 0)
break;
result = (result << 4) | unhex;
}
*pResult = result;
}
*pResult = MsgUnhex((char *) yarn->mYarn_Buf, numChars);
}
nsresult nsMsgDatabase::GetProperty(nsIMdbRow *row, const char *propertyName, char **result)
{
nsresult err = NS_OK;

Просмотреть файл

@ -918,8 +918,6 @@ nsresult nsEudoraMac::GetAttachmentInfo(const char *pFileName, nsIFile *pFile, n
OSType type = '?\??\?';
OSType creator = '?\??\?';
uint32_t fNum = 0;
int i;
char16_t c;
nsCString str(pFileName);
if (str.Length() > 22)
@ -931,21 +929,9 @@ nsresult nsEudoraMac::GetAttachmentInfo(const char *pFileName, nsIFile *pFile, n
str.Right(fileNum, 10);
if ((fileNum.CharAt(0) == '(') && (fileNum.CharAt(9) == ')'))
{
for (i = 1; i < 9; i++)
{
fNum *= 16;
c = fileNum.CharAt(i);
if ((c >= '0') && (c <= '9'))
fNum += (c - '0');
else if ((c >= 'a') && (c <= 'f'))
fNum += (c - 'a' + 10);
else if ((c >= 'A') && (c <= 'F'))
fNum += (c - 'A' + 10);
else
break;
}
if (i == 9)
if (MsgIsHex(fileNum.get() + 1, 8))
{
fNum = MsgUnhex(fileNum.get() + 1, 8);
str.Left(fileNum, str.Length() - 10);
str = fileNum;
str.Trim(kWhitespace);

Просмотреть файл

@ -1295,7 +1295,6 @@ nsresult nsParseMailMessageState::FinalizeHeaders()
struct message_header *content_type;
char md5_data [50];
const char *s;
uint32_t flags = 0;
uint32_t delta = 0;
nsMsgPriorityValue priorityFlags = nsMsgPriority::notSet;
@ -1343,11 +1342,8 @@ nsresult nsParseMailMessageState::FinalizeHeaders()
{
if (mozstatus->length == 4)
{
int i;
for (i=0,s=mozstatus->value ; i<4 ; i++,s++)
{
flags = (flags << 4) | msg_UnHex(*s);
}
NS_ASSERTION(MsgIsHex(mozstatus->value, 4), "Expected 4 hex digits for flags.");
flags = MsgUnhex(mozstatus->value, 4);
// strip off and remember priority bits.
flags &= ~nsMsgMessageFlags::RuntimeOnly;
priorityFlags = (nsMsgPriorityValue) ((flags & nsMsgMessageFlags::Priorities) >> 13);
@ -1511,7 +1507,7 @@ nsresult nsParseMailMessageState::FinalizeHeaders()
if (!mozstatus && statush)
{
/* Parse a little bit of the Berkeley Mail status header. */
for (s = statush->value; *s; s++) {
for (const char *s = statush->value; *s; s++) {
uint32_t msgFlags = 0;
(void)m_newMsgHdr->GetFlags(&msgFlags);
switch (*s)

Просмотреть файл

@ -65,7 +65,6 @@ public:
nsresult InternSubject (struct message_header *header);
static bool IsEnvelopeLine(const char *buf, int32_t buf_size);
static int msg_UnHex(char C);
nsCOMPtr<nsIMsgDBHdr> m_newMsgHdr; /* current message header we're building */
nsCOMPtr<nsIMsgDatabase> m_mailDB;
@ -127,14 +126,6 @@ public:
protected:
};
// this should go in some utility class.
inline int nsParseMailMessageState::msg_UnHex(char C)
{
return ((C >= '0' && C <= '9') ? C - '0' :
((C >= 'A' && C <= 'F') ? C - 'A' + 10 :
((C >= 'a' && C <= 'f') ? C - 'a' + 10 : 0)));
}
// This class is part of the mailbox parsing state machine
class nsMsgMailboxParser : public nsIStreamListener, public nsParseMailMessageState, public nsMsgLineBuffer
{