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; }