PRIVATE void intl_FillTryIMAP4SearchIterator(INTL_CSIDIteratorPriv* p, int16 csid) { int idx = 0; cscvt_t *cscvtp = cscvt_tbl; p->csidlist[idx++] = INTL_DefaultMailCharSetID(csid); /* add mailcsid first */ p->csidlist[idx++] = INTL_DefaultNewsCharSetID(csid); /* If the news csid is different add it */ if(p->csidlist[0] == p->csidlist[1]) idx--; /* Add all the csid that we know how to convert to (Without CS_AUTO bit on */ while (cscvtp->from_csid) { if ( (cscvtp->from_csid & ~CS_AUTO) == (csid & ~CS_AUTO)) { int16 foundcsid = cscvtp->to_csid & ~CS_AUTO; XP_Bool notInTheList = TRUE; int i; for(i = 0; i < idx ;i++) { if(foundcsid == p->csidlist[i]) notInTheList = FALSE; } if(notInTheList) { p->csidlist[idx++] = foundcsid; XP_ASSERT(NUMOFCSIDINITERATOR == idx); if(NUMOFCSIDINITERATOR == idx) break; } } cscvtp++; } p->csidlist[idx] = 0; /* terminate the list by 0 */ }
nsresult nsMsgSearchAdapter::EncodeImapTerm (nsIMsgSearchTerm *term, bool reallyDredd, const PRUnichar *srcCharset, const PRUnichar *destCharset, char **ppOutTerm) { NS_ENSURE_ARG_POINTER(term); NS_ENSURE_ARG_POINTER(ppOutTerm); nsresult err = NS_OK; bool useNot = false; bool useQuotes = false; bool ignoreValue = false; nsCAutoString arbitraryHeader; const char *whichMnemonic = nsnull; const char *orHeaderMnemonic = nsnull; *ppOutTerm = nsnull; nsCOMPtr <nsIMsgSearchValue> searchValue; nsresult rv = term->GetValue(getter_AddRefs(searchValue)); NS_ENSURE_SUCCESS(rv,rv); nsMsgSearchOpValue op; term->GetOp(&op); if (op == nsMsgSearchOp::DoesntContain || op == nsMsgSearchOp::Isnt) useNot = true; nsMsgSearchAttribValue attrib; term->GetAttrib(&attrib); switch (attrib) { case nsMsgSearchAttrib::ToOrCC: orHeaderMnemonic = m_kImapCC; // fall through to case nsMsgSearchAttrib::To: case nsMsgSearchAttrib::To: whichMnemonic = m_kImapTo; break; case nsMsgSearchAttrib::CC: whichMnemonic = m_kImapCC; break; case nsMsgSearchAttrib::Sender: whichMnemonic = m_kImapFrom; break; case nsMsgSearchAttrib::Subject: whichMnemonic = m_kImapSubject; break; case nsMsgSearchAttrib::Body: whichMnemonic = m_kImapBody; break; case nsMsgSearchAttrib::AgeInDays: // added for searching online for age in days... // for AgeInDays, we are actually going to perform a search by date, so convert the operations for age // to the IMAP mnemonics that we would use for date! { // If we have a future date, the > and < are reversed. // e.g. ageInDays > 2 means more than 2 days old ("date before X") whereas // ageInDays > -2 should be more than 2 days in the future ("date after X") PRInt32 ageInDays; searchValue->GetAge(&ageInDays); bool dateInFuture = (ageInDays < 0); switch (op) { case nsMsgSearchOp::IsGreaterThan: whichMnemonic = (!dateInFuture) ? m_kImapBefore : m_kImapSince; break; case nsMsgSearchOp::IsLessThan: whichMnemonic = (!dateInFuture) ? m_kImapSince : m_kImapBefore; break; case nsMsgSearchOp::Is: whichMnemonic = m_kImapSentOn; break; default: NS_ASSERTION(false, "invalid search operator"); return NS_ERROR_INVALID_ARG; } } break; case nsMsgSearchAttrib::Size: switch (op) { case nsMsgSearchOp::IsGreaterThan: whichMnemonic = m_kImapSizeLarger; break; case nsMsgSearchOp::IsLessThan: whichMnemonic = m_kImapSizeSmaller; break; default: NS_ASSERTION(false, "invalid search operator"); return NS_ERROR_INVALID_ARG; } break; case nsMsgSearchAttrib::Date: switch (op) { case nsMsgSearchOp::IsBefore: whichMnemonic = m_kImapBefore; break; case nsMsgSearchOp::IsAfter: whichMnemonic = m_kImapSince; break; case nsMsgSearchOp::Isnt: /* we've already added the "Not" so just process it like it was a date is search */ case nsMsgSearchOp::Is: whichMnemonic = m_kImapSentOn; break; default: NS_ASSERTION(false, "invalid search operator"); return NS_ERROR_INVALID_ARG; } break; case nsMsgSearchAttrib::AnyText: whichMnemonic = m_kImapAnyText; break; case nsMsgSearchAttrib::Keywords: whichMnemonic = m_kImapKeyword; break; case nsMsgSearchAttrib::MsgStatus: useNot = false; // bizarrely, NOT SEEN is wrong, but UNSEEN is right. ignoreValue = true; // the mnemonic is all we need PRUint32 status; searchValue->GetStatus(&status); switch (status) { case nsMsgMessageFlags::Read: whichMnemonic = op == nsMsgSearchOp::Is ? m_kImapSeen : m_kImapNotSeen; break; case nsMsgMessageFlags::Replied: whichMnemonic = op == nsMsgSearchOp::Is ? m_kImapAnswered : m_kImapNotAnswered; break; case nsMsgMessageFlags::New: whichMnemonic = op == nsMsgSearchOp::Is ? m_kImapNew : m_kImapNotNew; break; case nsMsgMessageFlags::Marked: whichMnemonic = op == nsMsgSearchOp::Is ? m_kImapFlagged : m_kImapNotFlagged; break; default: NS_ASSERTION(false, "invalid search operator"); return NS_ERROR_INVALID_ARG; } break; default: if ( attrib > nsMsgSearchAttrib::OtherHeader && attrib < nsMsgSearchAttrib::kNumMsgSearchAttributes) { nsCString arbitraryHeaderTerm; term->GetArbitraryHeader(arbitraryHeaderTerm); if (!arbitraryHeaderTerm.IsEmpty()) { arbitraryHeader.AssignLiteral(" \""); arbitraryHeader.Append(arbitraryHeaderTerm); arbitraryHeader.AppendLiteral("\" "); whichMnemonic = arbitraryHeader.get(); } else return NS_ERROR_FAILURE; } else { NS_ASSERTION(false, "invalid search operator"); return NS_ERROR_INVALID_ARG; } } char *value = nsnull; char dateBuf[100]; dateBuf[0] = '\0'; bool valueWasAllocated = false; if (attrib == nsMsgSearchAttrib::Date) { // note that there used to be code here that encoded an RFC822 date for imap searches. // The IMAP RFC 2060 is misleading to the point that it looks like it requires an RFC822 // date but really it expects dd-mmm-yyyy, like dredd, and refers to the RFC822 date only in that the // dd-mmm-yyyy date will match the RFC822 date within the message. PRTime adjustedDate; searchValue->GetDate(&adjustedDate); if (whichMnemonic == m_kImapSince) { // it looks like the IMAP server searches on Since includes the date in question... // our UI presents Is, IsGreater and IsLessThan. For the IsGreater case (m_kImapSince) // we need to adjust the date so we get greater than and not greater than or equal to which // is what the IMAP server wants to search on // won't work on Mac. // ack, is this right? is PRTime seconds or microseconds? PRInt64 microSecondsPerSecond, secondsInDay, microSecondsInDay; LL_I2L(microSecondsPerSecond, PR_USEC_PER_SEC); LL_UI2L(secondsInDay, 60 * 60 * 24); LL_MUL(microSecondsInDay, secondsInDay, microSecondsPerSecond); LL_ADD(adjustedDate, adjustedDate, microSecondsInDay); // bump up to the day after this one... } PRExplodedTime exploded; PR_ExplodeTime(adjustedDate, PR_LocalTimeParameters, &exploded); PR_FormatTimeUSEnglish(dateBuf, sizeof(dateBuf), "%d-%b-%Y", &exploded); // strftime (dateBuf, sizeof(dateBuf), "%d-%b-%Y", localtime (/* &term->m_value.u.date */ &adjustedDate)); value = dateBuf; } else { if (attrib == nsMsgSearchAttrib::AgeInDays) { // okay, take the current date, subtract off the age in days, then do an appropriate Date search on // the resulting day. PRInt32 ageInDays; searchValue->GetAge(&ageInDays); PRTime now = PR_Now(); PRTime matchDay; PRInt64 microSecondsPerSecond, secondsInDays, microSecondsInDay; LL_I2L(microSecondsPerSecond, PR_USEC_PER_SEC); LL_I2L(secondsInDays, 60 * 60 * 24 * ageInDays); LL_MUL(microSecondsInDay, secondsInDays, microSecondsPerSecond); LL_SUB(matchDay, now, microSecondsInDay); // = now - term->m_value.u.age * 60 * 60 * 24; PRExplodedTime exploded; PR_ExplodeTime(matchDay, PR_LocalTimeParameters, &exploded); PR_FormatTimeUSEnglish(dateBuf, sizeof(dateBuf), "%d-%b-%Y", &exploded); // strftime (dateBuf, sizeof(dateBuf), "%d-%b-%Y", localtime (&matchDay)); value = dateBuf; } else if (attrib == nsMsgSearchAttrib::Size) { PRUint32 sizeValue; nsCAutoString searchTermValue; searchValue->GetSize(&sizeValue); // Multiply by 1024 to get into kb resolution sizeValue *= 1024; // Ensure that greater than is really greater than // in kb resolution. if (op == nsMsgSearchOp::IsGreaterThan) sizeValue += 1024; searchTermValue.AppendInt(sizeValue); value = ToNewCString(searchTermValue); valueWasAllocated = true; } else if (IS_STRING_ATTRIBUTE(attrib)) { PRUnichar *convertedValue; // = reallyDredd ? MSG_EscapeSearchUrl (term->m_value.u.string) : msg_EscapeImapSearchProtocol(term->m_value.u.string); nsString searchTermValue; searchValue->GetStr(searchTermValue); // Ugly switch for Korean mail/news charsets. // We want to do this here because here is where // we know what charset we want to use. #ifdef DOING_CHARSET if (reallyDredd) dest_csid = INTL_DefaultNewsCharSetID(dest_csid); else dest_csid = INTL_DefaultMailCharSetID(dest_csid); #endif // do all sorts of crazy escaping convertedValue = reallyDredd ? EscapeSearchUrl (searchTermValue.get()) : EscapeImapSearchProtocol(searchTermValue.get()); useQuotes = ((!reallyDredd || (nsDependentString(convertedValue).FindChar(PRUnichar(' ')) != -1)) && (attrib != nsMsgSearchAttrib::Keywords)); // now convert to char* and escape quoted_specials nsCAutoString valueStr; nsresult rv = ConvertFromUnicode(NS_LossyConvertUTF16toASCII(destCharset).get(), nsDependentString(convertedValue), valueStr); if (NS_SUCCEEDED(rv)) { const char *vptr = valueStr.get(); // max escaped length is one extra character for every character in the cmd. nsAutoArrayPtr<char> newValue(new char[2*strlen(vptr) + 1]); if (newValue) { char *p = newValue; while (1) { char ch = *vptr++; if (!ch) break; if ((useQuotes ? ch == '"' : 0) || ch == '\\') *p++ = '\\'; *p++ = ch; } *p = '\0'; value = strdup(newValue); // realloc down to smaller size } } else value = strdup(""); NS_Free(convertedValue); valueWasAllocated = true; } } // this should be rewritten to use nsCString int subLen = (value ? strlen(value) : 0) + (useNot ? strlen(m_kImapNot) : 0) + strlen(m_kImapHeader); int len = strlen(whichMnemonic) + subLen + (useQuotes ? 2 : 0) + (orHeaderMnemonic ? (subLen + strlen(m_kImapOr) + strlen(orHeaderMnemonic) + 2 /*""*/) : 0) + 10; // add slough for imap string literals char *encoding = new char[len]; if (encoding) { encoding[0] = '\0'; // Remember: if ToOrCC and useNot then the expression becomes NOT To AND Not CC as opposed to (NOT TO) || (NOT CC) if (orHeaderMnemonic && !useNot) PL_strcat(encoding, m_kImapOr); if (useNot) PL_strcat (encoding, m_kImapNot); if (!arbitraryHeader.IsEmpty()) PL_strcat (encoding, m_kImapHeader); PL_strcat (encoding, whichMnemonic); if (!ignoreValue) err = EncodeImapValue(encoding, value, useQuotes, reallyDredd); if (orHeaderMnemonic) { if (useNot) PL_strcat(encoding, m_kImapNot); PL_strcat (encoding, m_kImapHeader); PL_strcat (encoding, orHeaderMnemonic); if (!ignoreValue) err = EncodeImapValue(encoding, value, useQuotes, reallyDredd); } // kmcentee, don't let the encoding end with whitespace, // this throws off later url STRCMP if (*encoding && *(encoding + strlen(encoding) - 1) == ' ') *(encoding + strlen(encoding) - 1) = '\0'; } if (value && valueWasAllocated) NS_Free (value); *ppOutTerm = encoding; return err; }