Bug 853159 - Merge hex decoding functions throughout mailnews. r=Neil, r=Standard8
This commit is contained in:
Родитель
bb56319f74
Коммит
0fe1f32fea
|
@ -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
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче