Ejemplo n.º 1
0
  LOCAL_FUNC
  TT_Error  TT_Open_Stream( const String*  filepathname, 
                            TT_Stream*     stream )
  {
    TT_Error     error;
    Int          file;
    PStream_Rec  stream_rec;
    TFileMap*    map;

    int          size, err = 0;
    short        vRefNum, res = -1;
    Str255       FontName;
    char         *cp, *p, *fname, *sep;
    Str63        myName;
    long         dirID;


    if ( ALLOC( *stream, sizeof ( TStream_Rec ) ) )
      return error;

    map = Allocate_Map();
    if ( !map )
    {
      error = TT_Err_Out_Of_Memory;
      goto Memory_Fail;
    }
    
    stream_rec = STREAM2REC( *stream );

    /* Find the dirID of the Fonts folder in the current System folder */
    if (FindFolder(kOnSystemDisk, kFontsFolderType, kDontCreateFolder, &vRefNum, &dirID)) 
        goto File_Fail;

    /* Break the name apart */
    fname = mystrdup(filepathname); /* Make a copy so we can muck with it */
    sep = ":/";     /* Things that can seperate file path componants */
    
    strtok(fname, sep);             /* Skip over "fonts:" */
    
    if ((p = strtok(NULL, sep)) == NULL)        /* Get filename */
        goto File_Fail;
    strcpy(myName + 1, p);                      /* Make this a Pascal string (Yuck!) */
    myName[0] = strlen(p);
     
    if ((p = strtok(NULL, sep)) == NULL)        /* Get res name */
        goto File_Fail;
    strcpy(FontName+1, p);                      /* Make this a Pascal string (Yuck!) */
    FontName[0] = strlen(p);
    
    FREE( fname );
    
    if ((cp = strchr(FontName, '.')) != NULL)   /* Strip off ".ttf" , if any */
        *cp = 0;
    
    /* Read the font into a buffer */
    if ((map->resid = HOpenResFile(vRefNum, dirID, myName, fsRdPerm)) == -1)
        goto File_Fail;
    
    if ((map->handle = Get1NamedResource('sfnt', FontName)) == NULL)
        goto Map_Fail;
    
    HLock(map->handle);
    map->base   = *map->handle;
    map->offset = 0;
    map->size   = GetResourceSizeOnDisk(map->handle);

    if ( map->base == NULL )
        goto Lock_Fail;

    stream_rec->map = map;
    stream_rec->pos = 0;

#ifndef TT_CONFIG_OPTION_THREAD_SAFE
    CUR_Stream = stream_rec;
#endif

    return TT_Err_Ok;

  Lock_Fail:
    ReleaseResource(map->handle);
    
  Map_Fail:
    CloseResFile(map->resid);

  File_Fail:
    error = TT_Err_Could_Not_Open_File;
    FREE( map );

  Memory_Fail:
    FREE( *stream );
    FREE( fname );
    return error;
  }
// This is the function that looks for the first folder to purge. It also
// applies retention settings to any folder that hasn't had retention settings
// applied in mMinDelayBetweenPurges minutes (default, 8 hours).
// However, if we've spent more than .5 seconds in this loop, don't
// apply any more retention settings because it might lock up the UI.
// This might starve folders later on in the hierarchy, since we always
// start at the top, but since we also apply retention settings when you
// open a folder, or when you compact all folders, I think this will do
// for now, until we have a cleanup on shutdown architecture.
nsresult nsMsgPurgeService::PerformPurge()
{
  MOZ_LOG(MsgPurgeLogModule, mozilla::LogLevel::Info, ("performing purge"));

  nsresult rv;

  nsCOMPtr <nsIMsgAccountManager> accountManager = do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
  NS_ENSURE_SUCCESS(rv,rv);
  bool keepApplyingRetentionSettings = true;

  nsCOMPtr<nsIArray> allServers;
  rv = accountManager->GetAllServers(getter_AddRefs(allServers));
  if (NS_SUCCEEDED(rv) && allServers)
  {
    uint32_t numServers;
    rv = allServers->GetLength(&numServers);
    MOZ_LOG(MsgPurgeLogModule, mozilla::LogLevel::Info, ("%d servers", numServers));
    nsCOMPtr<nsIMsgFolder> folderToPurge;
    PRIntervalTime startTime = PR_IntervalNow();
    int32_t purgeIntervalToUse = 0;
    PRTime oldestPurgeTime = 0; // we're going to pick the least-recently purged folder

    // apply retention settings to folders that haven't had retention settings
    // applied in mMinDelayBetweenPurges minutes (default 8 hours)
    // Because we get last purge time from the folder cache,
    // this code won't open db's for folders until it decides it needs
    // to apply retention settings, and since nsIMsgFolder::ApplyRetentionSettings
    // will close any db's it opens, this code won't leave db's open.
    for (uint32_t serverIndex=0; serverIndex < numServers; serverIndex++)
    {
      nsCOMPtr <nsIMsgIncomingServer> server =
        do_QueryElementAt(allServers, serverIndex, &rv);
      if (NS_SUCCEEDED(rv) && server)
      {
        if (keepApplyingRetentionSettings)
        {
          nsCOMPtr <nsIMsgFolder> rootFolder;
          rv = server->GetRootFolder(getter_AddRefs(rootFolder));
          NS_ENSURE_SUCCESS(rv, rv);

          nsCOMPtr<nsIArray> childFolders;
          rv = rootFolder->GetDescendants(getter_AddRefs(childFolders));
          NS_ENSURE_SUCCESS(rv, rv);

          uint32_t cnt = 0;
          childFolders->GetLength(&cnt);

          nsCOMPtr<nsISupports> supports;
          nsCOMPtr<nsIUrlListener> urlListener;
          nsCOMPtr<nsIMsgFolder> childFolder;

          for (uint32_t index = 0; index < cnt; index++)
          {
            childFolder = do_QueryElementAt(childFolders, index);
            if (childFolder)
            {
              uint32_t folderFlags;
              (void) childFolder->GetFlags(&folderFlags);
              if (folderFlags & nsMsgFolderFlags::Virtual)
                continue;
              PRTime curFolderLastPurgeTime = 0;
              nsCString curFolderLastPurgeTimeString, curFolderUri;
              rv = childFolder->GetStringProperty("LastPurgeTime", curFolderLastPurgeTimeString);
              if (NS_FAILED(rv))
                continue; // it is ok to fail, go on to next folder

              if (!curFolderLastPurgeTimeString.IsEmpty())
              {
                PRTime theTime;
                PR_ParseTimeString(curFolderLastPurgeTimeString.get(), false, &theTime);
                curFolderLastPurgeTime = theTime;
              }

              childFolder->GetURI(curFolderUri);
              MOZ_LOG(MsgPurgeLogModule, mozilla::LogLevel::Info, ("%s curFolderLastPurgeTime=%s (if blank, then never)", curFolderUri.get(), curFolderLastPurgeTimeString.get()));

              // check if this folder is due to purge
              // has to have been purged at least mMinDelayBetweenPurges minutes ago
              // we don't want to purge the folders all the time - once a day is good enough
              int64_t minDelayBetweenPurges(mMinDelayBetweenPurges);
              int64_t microSecondsPerMinute(60000000);
              PRTime nextPurgeTime = curFolderLastPurgeTime + (minDelayBetweenPurges * microSecondsPerMinute);
              if (nextPurgeTime < PR_Now())
              {
                MOZ_LOG(MsgPurgeLogModule, mozilla::LogLevel::Info, ("purging %s", curFolderUri.get()));
                childFolder->ApplyRetentionSettings();
              }
              PRIntervalTime elapsedTime = PR_IntervalNow() - startTime;
              // check if more than 500 milliseconds have elapsed in this purge process
              if (PR_IntervalToMilliseconds(elapsedTime) > 500)
              {
                keepApplyingRetentionSettings = false;
                break;
              }
            }
          }
        }
        nsCString type;
        nsresult rv = server->GetType(type);
        NS_ENSURE_SUCCESS(rv, rv);

        nsCString realHostName;
        server->GetRealHostName(realHostName);
        MOZ_LOG(MsgPurgeLogModule, mozilla::LogLevel::Info, ("[%d] %s (%s)", serverIndex, realHostName.get(), type.get()));

        nsCOMPtr <nsISpamSettings> spamSettings;
        rv = server->GetSpamSettings(getter_AddRefs(spamSettings));
        NS_ENSURE_SUCCESS(rv, rv);

        int32_t spamLevel;
        spamSettings->GetLevel(&spamLevel);
        MOZ_LOG(MsgPurgeLogModule, mozilla::LogLevel::Info, ("[%d] spamLevel=%d (if 0, don't purge)", serverIndex, spamLevel));
        if (!spamLevel)
          continue;

        // check if we are set up to purge for this server
        // if not, skip it.
        bool purgeSpam;
        spamSettings->GetPurge(&purgeSpam);

        MOZ_LOG(MsgPurgeLogModule, mozilla::LogLevel::Info, ("[%d] purgeSpam=%s (if false, don't purge)", serverIndex, purgeSpam ? "true" : "false"));
        if (!purgeSpam)
          continue;

        // check if the spam folder uri is set for this server
        // if not skip it.
        nsCString junkFolderURI;
        rv = spamSettings->GetSpamFolderURI(getter_Copies(junkFolderURI));
        NS_ENSURE_SUCCESS(rv,rv);

        MOZ_LOG(MsgPurgeLogModule, mozilla::LogLevel::Info, ("[%d] junkFolderURI=%s (if empty, don't purge)", serverIndex, junkFolderURI.get()));
        if (junkFolderURI.IsEmpty())
          continue;

        // if the junk folder doesn't exist
        // because the folder pane isn't built yet, for example
        // skip this account
        nsCOMPtr<nsIMsgFolder> junkFolder;
        rv = FindFolder(junkFolderURI, getter_AddRefs(junkFolder));
        NS_ENSURE_SUCCESS(rv, rv);

        MOZ_LOG(MsgPurgeLogModule, mozilla::LogLevel::Info, ("[%d] %s exists? %s (if doesn't exist, don't purge)", serverIndex, junkFolderURI.get(), junkFolder ? "true" : "false"));
        if (!junkFolder)
          continue;

        PRTime curJunkFolderLastPurgeTime = 0;
        nsCString curJunkFolderLastPurgeTimeString;
        rv = junkFolder->GetStringProperty("curJunkFolderLastPurgeTime", curJunkFolderLastPurgeTimeString);
        if (NS_FAILED(rv))
          continue; // it is ok to fail, junk folder may not exist

        if (!curJunkFolderLastPurgeTimeString.IsEmpty())
        {
          PRTime theTime;
          PR_ParseTimeString(curJunkFolderLastPurgeTimeString.get(), false, &theTime);
          curJunkFolderLastPurgeTime = theTime;
        }

        MOZ_LOG(MsgPurgeLogModule, mozilla::LogLevel::Info, ("[%d] %s curJunkFolderLastPurgeTime=%s (if blank, then never)", serverIndex, junkFolderURI.get(), curJunkFolderLastPurgeTimeString.get()));

        // check if this account is due to purge
        // has to have been purged at least mMinDelayBetweenPurges minutes ago
        // we don't want to purge the folders all the time
        PRTime nextPurgeTime = curJunkFolderLastPurgeTime + mMinDelayBetweenPurges * 60000000 /* convert mMinDelayBetweenPurges to into microseconds */;
        if (nextPurgeTime < PR_Now())
        {
          MOZ_LOG(MsgPurgeLogModule, mozilla::LogLevel::Info, ("[%d] last purge greater than min delay", serverIndex));

          nsCOMPtr <nsIMsgIncomingServer> junkFolderServer;
          rv = junkFolder->GetServer(getter_AddRefs(junkFolderServer));
          NS_ENSURE_SUCCESS(rv,rv);

          bool serverBusy = false;
          bool serverRequiresPassword = true;
          bool passwordPromptRequired;
          bool canSearchMessages = false;
          junkFolderServer->GetPasswordPromptRequired(&passwordPromptRequired);
          junkFolderServer->GetServerBusy(&serverBusy);
          junkFolderServer->GetServerRequiresPasswordForBiff(&serverRequiresPassword);
          junkFolderServer->GetCanSearchMessages(&canSearchMessages);
          // Make sure we're logged on before doing the search (assuming we need to be)
          // and make sure the server isn't already in the middle of downloading new messages
          // and make sure a search isn't already going on
          MOZ_LOG(MsgPurgeLogModule, mozilla::LogLevel::Info, ("[%d] (search in progress? %s)", serverIndex, mSearchSession ? "true" : "false"));
          MOZ_LOG(MsgPurgeLogModule, mozilla::LogLevel::Info, ("[%d] (server busy? %s)", serverIndex, serverBusy ? "true" : "false"));
          MOZ_LOG(MsgPurgeLogModule, mozilla::LogLevel::Info, ("[%d] (serverRequiresPassword? %s)", serverIndex, serverRequiresPassword ? "true" : "false"));
          MOZ_LOG(MsgPurgeLogModule, mozilla::LogLevel::Info, ("[%d] (passwordPromptRequired? %s)", serverIndex, passwordPromptRequired ? "true" : "false"));
          if (canSearchMessages && !mSearchSession && !serverBusy && (!serverRequiresPassword || !passwordPromptRequired))
          {
            int32_t purgeInterval;
            spamSettings->GetPurgeInterval(&purgeInterval);

            if ((oldestPurgeTime == 0) || (curJunkFolderLastPurgeTime < oldestPurgeTime))
            {
              MOZ_LOG(MsgPurgeLogModule, mozilla::LogLevel::Info, ("[%d] purging! searching for messages older than %d days", serverIndex, purgeInterval));
              oldestPurgeTime = curJunkFolderLastPurgeTime;
              purgeIntervalToUse = purgeInterval;
              folderToPurge = junkFolder;
              // if we've never purged this folder, do it...
              if (curJunkFolderLastPurgeTime == 0)
                break;
            }
          }
          else {
            NS_ASSERTION(canSearchMessages, "unexpected, you should be able to search");
            MOZ_LOG(MsgPurgeLogModule, mozilla::LogLevel::Info, ("[%d] not a good time for this server, try again later", serverIndex));
          }
        }
        else {
          MOZ_LOG(MsgPurgeLogModule, mozilla::LogLevel::Info, ("[%d] last purge too recent", serverIndex));
        }
      }
    }
    if (folderToPurge && purgeIntervalToUse != 0)
      rv = SearchFolderToPurge(folderToPurge, purgeIntervalToUse);
  }

  // set up timer to check accounts again
  SetupNextPurge();
  return rv;
}