示例#1
0
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;
}