# HG changeset patch # User teknolog # Date 1270392857 -3600 # Node ID 223f270fa7ff86cf3ab6fecec0aec97acb470132 # Parent 554d9980157fee87021a7a34f5cc9a26a3bcfc7f Significantly improved database robustness diff -r 554d9980157f -r 223f270fa7ff application/src/PodcastFeedView.cpp --- a/application/src/PodcastFeedView.cpp Sun Apr 04 00:21:57 2010 +0100 +++ b/application/src/PodcastFeedView.cpp Sun Apr 04 15:54:17 2010 +0100 @@ -204,17 +204,12 @@ switch(aEventType) { - case EEventPenDownOnItem: - DP("PEN DOWN"); - break; - #ifndef SYMBIAN1_UI case EEventItemClicked: #endif case EEventEnterKeyPressed: case EEventItemDoubleClicked: case EEventItemActioned: - DP("DOUBLE TAP"); { const RFeedInfoArray* sortedItems = NULL; TInt index = iListContainer->Listbox()->CurrentItemIndex(); @@ -334,7 +329,8 @@ } else { - iPodcastModel.FeedEngine().GetStatsByFeed(aFeedInfo.Uid(), showCount, unplayedCount); + // we will get a leave if there are no shows for this feed, for instance, which is fine + TRAP_IGNORE(iPodcastModel.FeedEngine().GetStatsByFeedL(aFeedInfo.Uid(), showCount, unplayedCount)); if (unplayedCount) { unplayedShows.Format(*iFeedsFormat, unplayedCount); @@ -370,7 +366,7 @@ } CArrayPtr* icons = iListContainer->Listbox()->ItemDrawer()->FormattedCellData()->IconArray(); iconIndex = iFeedIdForIconArray.Find(aFeedInfo.Uid()); - if(iconIndex == KErrNotFound && aFeedInfo.FeedIcon() != NULL && + if(iconIndex == KErrNotFound && aFeedInfo.FeedIcon() != NULL && aFeedInfo.ImageFileName().Length() > 0 && aFeedInfo.FeedIcon()->SizeInPixels().iHeight > 0 && aFeedInfo.FeedIcon()->SizeInPixels().iWidth > 0) { diff -r 554d9980157f -r 223f270fa7ff engine/inc/FeedEngine.h --- a/engine/inc/FeedEngine.h Sun Apr 04 00:21:57 2010 +0100 +++ b/engine/inc/FeedEngine.h Sun Apr 04 15:54:17 2010 +0100 @@ -70,8 +70,7 @@ IMPORT_C void CancelUpdateAllFeeds(); IMPORT_C const RFeedInfoArray& GetSortedFeeds(); IMPORT_C CFeedInfo* GetFeedInfoByUid(TUint aFeedUid); - IMPORT_C void GetStatsByFeed(TUint aFeedUid, TUint &aNumShows, TUint &aNumUnplayed); - IMPORT_C void GetDownloadedStats(TUint &aNumShows, TUint &aNumUnplayed); + IMPORT_C void GetStatsByFeedL(TUint aFeedUid, TUint &aNumShows, TUint &aNumUnplayed); IMPORT_C void AddObserver(MFeedEngineObserver *observer); IMPORT_C void RemoveObserver(MFeedEngineObserver *observer); @@ -123,12 +122,12 @@ private: void DBLoadFeedsL(); - TBool DBRemoveFeed(TUint aUid); - TBool DBAddFeedL(const CFeedInfo& aTtem); + void DBRemoveFeedL(TUint aUid); + void DBAddFeedL(const CFeedInfo& aTtem); CFeedInfo* DBGetFeedInfoByUidL(TUint aFeedUid); - TUint DBGetFeedCount(); - TBool DBUpdateFeedL(const CFeedInfo& aItem); - void DBGetStatsByFeed(TUint aFeedUid, TUint &aNumShows, TUint &aNumUnplayed); + TUint DBGetFeedCountL(); + void DBUpdateFeedL(const CFeedInfo& aItem); + void DBGetStatsByFeedL(TUint aFeedUid, TUint &aNumShows, TUint &aNumUnplayed); private: diff -r 554d9980157f -r 223f270fa7ff engine/inc/FeedInfo.h --- a/engine/inc/FeedInfo.h Sun Apr 04 00:21:57 2010 +0100 +++ b/engine/inc/FeedInfo.h Sun Apr 04 15:54:17 2010 +0100 @@ -71,8 +71,6 @@ IMPORT_C CFbsBitmap* FeedIcon() const; IMPORT_C void SetFeedIcon(CFbsBitmap* aBitmapToClone); - // IMPORT_C TInt FeedIconIndex() const; -// IMPORT_C void SetFeedIconIndex(TInt aIndex); private: CFeedInfo(); void ConstructL(); diff -r 554d9980157f -r 223f270fa7ff engine/inc/PodcastModel.h --- a/engine/inc/PodcastModel.h Sun Apr 04 00:21:57 2010 +0100 +++ b/engine/inc/PodcastModel.h Sun Apr 04 15:54:17 2010 +0100 @@ -85,6 +85,7 @@ TInt GetIapId(); sqlite3* DB(); + void ResetDB(); IMPORT_C void GetAllShowsL(); IMPORT_C void GetNewShowsL(); @@ -99,6 +100,8 @@ protected: CPodcastModel(); void ConstructL(); + + void OpenDBL(); // From ImageHandler void ImageOperationCompleteL(TInt aError, TUint aHandle, CPodcastModel& aPodcastModel); private: diff -r 554d9980157f -r 223f270fa7ff engine/inc/PodcastUtils.h --- a/engine/inc/PodcastUtils.h Sun Apr 04 00:21:57 2010 +0100 +++ b/engine/inc/PodcastUtils.h Sun Apr 04 15:54:17 2010 +0100 @@ -20,6 +20,14 @@ #define PODCASTUTILS_H_ #include +#include "sqlite3.h" +// Cleanup stack macro for SQLite3 +static void Cleanup_sqlite3_finalize_wrapper(TAny* handle) + { + sqlite3_finalize(static_cast(handle)); + } +#define Cleanup_sqlite3_finalize_PushL(__handle) CleanupStack::PushL(TCleanupItem(&Cleanup_sqlite3_finalize_wrapper, __handle)) + _LIT(KURLPrefix, "http://"); _LIT(KItpcPrefix, "itpc://"); diff -r 554d9980157f -r 223f270fa7ff engine/src/FeedEngine.cpp --- a/engine/src/FeedEngine.cpp Sun Apr 04 00:21:57 2010 +0100 +++ b/engine/src/FeedEngine.cpp Sun Apr 04 15:54:17 2010 +0100 @@ -28,14 +28,6 @@ #include _LIT(KFeedParseStorePath, "feeds\\"); -// Cleanup stack macro for SQLite3 -// TODO Move this to some common place. -static void Cleanup_sqlite3_finalize_wrapper(TAny* handle) - { - sqlite3_finalize(static_cast(handle)); - } -#define Cleanup_sqlite3_finalize_PushL(__handle) CleanupStack::PushL(TCleanupItem(&Cleanup_sqlite3_finalize_wrapper, __handle)) - CFeedEngine* CFeedEngine::NewL(CPodcastModel& aPodcastModel) { @@ -53,36 +45,41 @@ iFeedClient = CHttpClient::NewL(iPodcastModel, *this); iFeedTimer.ConstructL(); - RunFeedTimer(); + TInt err = KErrNone; + TInt feedCount = 0; - if (DBGetFeedCount() > 0) + TRAP(err, feedCount = DBGetFeedCountL()); + if (err == KErrNone && feedCount > 0) { DP("Loading feeds from DB"); - DBLoadFeedsL(); - } + TRAP(err, DBLoadFeedsL()); + } + - if (iPodcastModel.IsFirstStartup()) { + if (err != KErrNone || iPodcastModel.IsFirstStartup()) { TFileName defaultFile = iPodcastModel.SettingsEngine().DefaultFeedsFileName(); DP1("Loading default feeds from %S", &defaultFile); if (BaflUtils::FileExists(iPodcastModel.FsSession(), defaultFile)) { ImportFeedsL(defaultFile); } - } else { - // clean out feeds temp directory - TFileName feedTempPath; - feedTempPath.Copy (iPodcastModel.SettingsEngine().PrivatePath ()); - feedTempPath.Append(KFeedParseStorePath); - feedTempPath.Append(_L("*")); + } + + // clean out feeds temp directory + TFileName feedTempPath; + feedTempPath.Copy (iPodcastModel.SettingsEngine().PrivatePath ()); + feedTempPath.Append(KFeedParseStorePath); + feedTempPath.Append(_L("*")); - BaflUtils::EnsurePathExistsL(iPodcastModel.FsSession(), feedTempPath); - BaflUtils::DeleteFile(iPodcastModel.FsSession(),feedTempPath); - } + BaflUtils::EnsurePathExistsL(iPodcastModel.FsSession(), feedTempPath); + BaflUtils::DeleteFile(iPodcastModel.FsSession(),feedTempPath); TFileName importFile = iPodcastModel.SettingsEngine().ImportFeedsFileName(); if (BaflUtils::FileExists(iPodcastModel.FsSession(), importFile)) { DP("Importing feeds"); - ImportFeedsL(importFile); + TRAP_IGNORE(ImportFeedsL(importFile)); } + + RunFeedTimer(); } CFeedEngine::CFeedEngine(CPodcastModel& aPodcastModel) @@ -340,15 +337,17 @@ return ETrue; } -TBool CFeedEngine::DBAddFeedL(const CFeedInfo& aItem) +void CFeedEngine::DBAddFeedL(const CFeedInfo& aItem) { DP2("CFeedEngine::DBAddFeed, title=%S, URL=%S", &aItem.Title(), &aItem.Url()); - CFeedInfo *info = DBGetFeedInfoByUidL(aItem.Uid()); - if (info) { - DP("Feed already exists!"); + CFeedInfo *info; + + TRAPD(err, DBGetFeedInfoByUidL(aItem.Uid())); + + if (err == KErrNone && info) { delete info; - return EFalse; + User::Leave(KErrAlreadyExists); } HBufC* titleBuf = HBufC::NewLC(KMaxLineLength); @@ -372,24 +371,23 @@ sqlite3_stmt *st; - //DP1("SQL statement length=%d", iSqlBuffer.Length()); int rc = sqlite3_prepare16_v2(&iDB, (const void*)iSqlBuffer.PtrZ() , -1, &st, (const void**) NULL); if (rc==SQLITE_OK) { + Cleanup_sqlite3_finalize_PushL(st); rc = sqlite3_step(st); - if (rc == SQLITE_DONE) + if (rc != SQLITE_DONE) { - sqlite3_finalize(st); - return ETrue; + User::Leave(KErrCorrupt); } - else { - sqlite3_finalize(st); + CleanupStack::PopAndDestroy(); // st } - } - - return EFalse; + else + { + User::Leave(KErrCorrupt); + } } EXPORT_C void CFeedEngine::RemoveFeedL(TUint aUid) @@ -427,15 +425,13 @@ DP("Removed feed from array"); // now remove it from DB - DBRemoveFeed(aUid); - - return; + DBRemoveFeedL(aUid); } } } -TBool CFeedEngine::DBRemoveFeed(TUint aUid) +void CFeedEngine::DBRemoveFeedL(TUint aUid) { DP("CFeedEngine::DBRemoveFeed"); _LIT(KSqlStatement, "delete from feeds where uid=%u"); @@ -447,23 +443,23 @@ if (rc==SQLITE_OK) { + Cleanup_sqlite3_finalize_PushL(st); rc = sqlite3_step(st); - sqlite3_finalize(st); - if (rc == SQLITE_DONE) + if (rc != SQLITE_DONE) { - DP("Feed removed from DB"); - return ETrue; + User::Leave(KErrNotFound); } - else - { - DP("Error when removing feed from DB"); - } + + CleanupStack::PopAndDestroy(); //st } - return EFalse; + else + { + User::Leave(KErrCorrupt); + } } -TBool CFeedEngine::DBUpdateFeedL(const CFeedInfo &aItem) +void CFeedEngine::DBUpdateFeedL(const CFeedInfo &aItem) { DP2("CFeedEngine::DBUpdateFeed, title=%S, URL=%S", &aItem.Title(), &aItem.Url()); @@ -488,25 +484,23 @@ sqlite3_stmt *st; - //DP1("SQL statement length=%d", iSqlBuffer.Length()); int rc = sqlite3_prepare16_v2(&iDB, (const void*)iSqlBuffer.PtrZ() , -1, &st, (const void**) NULL); if (rc==SQLITE_OK) { + Cleanup_sqlite3_finalize_PushL(st); rc = sqlite3_step(st); - sqlite3_finalize(st); - if (rc == SQLITE_DONE) + if (rc != SQLITE_DONE) { - return ETrue; + User::Leave(KErrNotFound); } + CleanupStack::PopAndDestroy(); //st } else { - DP1("SQLite rc=%d", rc); + User::Leave(KErrCorrupt); } - - return EFalse; } void CFeedEngine::ParsingCompleteL(CFeedInfo *item) @@ -627,11 +621,9 @@ iClientState = EIdle; if(aError == KErrNone) { - if( BaflUtils::FileExists(CEikonEnv::Static()->FsSession(), iActiveFeed->ImageFileName() )) - { - // If this fails, no reason to worry - TRAP_IGNORE(iPodcastModel.ImageHandler().LoadFileAndScaleL(iActiveFeed->FeedIcon(), iActiveFeed->ImageFileName(), TSize(64,56), *iActiveFeed, iActiveFeed->Uid())); - } + // now the image has been downloaded, so we set it again in the FeedInfo to start + // converting it + TRAP_IGNORE(iActiveFeed->SetImageFileNameL(iActiveFeed->ImageFileName(), &iPodcastModel)); } DBUpdateFeedL(*iActiveFeed); NotifyFeedUpdateComplete(iActiveFeed->Uid(), aError); @@ -808,49 +800,13 @@ return a.Title().CompareF(b.Title()); } -EXPORT_C void CFeedEngine::GetDownloadedStats(TUint &aNumShows, TUint &aNumUnplayed) +EXPORT_C void CFeedEngine::GetStatsByFeedL(TUint aFeedUid, TUint &aNumShows, TUint &aNumUnplayed) { - DP("CFeedEngine::GetDownloadedStats"); - _LIT(KSqlStatement, "select count(*) from shows where downloadstate=%u"); - iSqlBuffer.Format(KSqlStatement, EDownloaded); - - sqlite3_stmt *st; - - int rc = sqlite3_prepare16_v2(&iDB, (const void*)iSqlBuffer.PtrZ() , -1, &st, (const void**) NULL); - - if( rc==SQLITE_OK ){ - rc = sqlite3_step(st); - - if (rc == SQLITE_ROW) { - aNumShows = sqlite3_column_int(st, 0); - } - } - - sqlite3_finalize(st); - - _LIT(KSqlStatement2, "select count(*) from shows where downloadstate=%u and playstate=%u"); - iSqlBuffer.Format(KSqlStatement2, EDownloaded, ENeverPlayed); - - rc = sqlite3_prepare16_v2(&iDB, (const void*)iSqlBuffer.PtrZ() , -1, &st, (const void**) NULL); - - if( rc==SQLITE_OK ){ - rc = sqlite3_step(st); - - if (rc == SQLITE_ROW) { - aNumUnplayed = sqlite3_column_int(st, 0); - } - } - - sqlite3_finalize(st); + //DP1("CFeedEngine::GetStatsByFeed, aFeedUid=%u", aFeedUid); + DBGetStatsByFeedL(aFeedUid, aNumShows, aNumUnplayed); } -EXPORT_C void CFeedEngine::GetStatsByFeed(TUint aFeedUid, TUint &aNumShows, TUint &aNumUnplayed) - { - //DP1("CFeedEngine::GetStatsByFeed, aFeedUid=%u", aFeedUid); - DBGetStatsByFeed(aFeedUid, aNumShows, aNumUnplayed); - } - -void CFeedEngine::DBGetStatsByFeed(TUint aFeedUid, TUint &aNumShows, TUint &aNumUnplayed) +void CFeedEngine::DBGetStatsByFeedL(TUint aFeedUid, TUint &aNumShows, TUint &aNumUnplayed) { //DP1("CFeedEngine::DBGetStatsByFeed, feedUid=%u", aFeedUid); _LIT(KSqlStatement, "select count(*) from shows where feeduid=%u"); @@ -860,50 +816,77 @@ int rc = sqlite3_prepare16_v2(&iDB, (const void*)iSqlBuffer.PtrZ() , -1, &st, (const void**) NULL); - if( rc==SQLITE_OK ){ + if( rc==SQLITE_OK) + { + Cleanup_sqlite3_finalize_PushL(st); rc = sqlite3_step(st); - if (rc == SQLITE_ROW) { + if (rc == SQLITE_ROW) + { aNumShows = sqlite3_column_int(st, 0); - } - } + } + else + { + User::Leave(KErrNotFound); + } + CleanupStack::PopAndDestroy(); // st + } + else + { + User::Leave(KErrCorrupt); + } - sqlite3_finalize(st); - _LIT(KSqlStatement2, "select count(*) from shows where feeduid=%u and playstate=0"); iSqlBuffer.Format(KSqlStatement2, aFeedUid); rc = sqlite3_prepare16_v2(&iDB, (const void*)iSqlBuffer.PtrZ() , -1, &st, (const void**) NULL); - if( rc==SQLITE_OK ){ + if(rc==SQLITE_OK) + { + Cleanup_sqlite3_finalize_PushL(st); rc = sqlite3_step(st); - if (rc == SQLITE_ROW) { + if (rc == SQLITE_ROW) + { aNumUnplayed = sqlite3_column_int(st, 0); - } + } + else + { + User::Leave(KErrNotFound); + } + CleanupStack::PopAndDestroy(); // st } - - sqlite3_finalize(st); } -TUint CFeedEngine::DBGetFeedCount() +TUint CFeedEngine::DBGetFeedCountL() { - DP("DBGetFeedCount BEGIN"); - sqlite3_stmt *st; - int rc = sqlite3_prepare_v2(&iDB,"select count(*) from feeds" , -1, &st, (const char**) NULL); - TUint size = 0; + DP("DBGetFeedCount BEGIN"); + sqlite3_stmt *st; + int rc = sqlite3_prepare_v2(&iDB,"select count(*) from feeds" , -1, &st, (const char**) NULL); + TUint size = 0; - if( rc==SQLITE_OK ){ - rc = sqlite3_step(st); - - if (rc == SQLITE_ROW) { + if( rc==SQLITE_OK ) + { + Cleanup_sqlite3_finalize_PushL(st); + rc = sqlite3_step(st); + + if (rc == SQLITE_ROW) + { size = sqlite3_column_int(st, 0); - } - } - - sqlite3_finalize(st); - DP1("DBGetFeedCount END=%d", size); - return size; + } + else + { + User::Leave(KErrCorrupt); + } + CleanupStack::PopAndDestroy(); // st + } + else + { + User::Leave(KErrCorrupt); + } + + DP1("DBGetFeedCount END=%d", size); + return size; } void CFeedEngine::DBLoadFeedsL() @@ -920,11 +903,13 @@ TLinearOrder sortOrder( CFeedEngine::CompareFeedsByTitle); int rc = sqlite3_prepare16_v2(&iDB, (const void*)iSqlBuffer.PtrZ() , -1, &st, (const void**) NULL); - Cleanup_sqlite3_finalize_PushL(st); - if (rc==SQLITE_OK) { + if (rc==SQLITE_OK) + { + Cleanup_sqlite3_finalize_PushL(st); rc = sqlite3_step(st); - while(rc == SQLITE_ROW) { + while(rc == SQLITE_ROW) + { feedInfo = CFeedInfo::NewLC(); const void *urlz = sqlite3_column_text16(st, 0); @@ -945,8 +930,11 @@ const void *imagefilez = sqlite3_column_text16(st, 4); TPtrC16 imagefile((const TUint16*)imagefilez); - feedInfo->SetImageFileNameL(imagefile, &iPodcastModel); - + if (imagefile.Length() > 0) + { + feedInfo->SetImageFileNameL(imagefile, &iPodcastModel); + } + const void *linkz = sqlite3_column_text16(st, 5); TPtrC16 link((const TUint16*)linkz); feedInfo->SetDescriptionL(link); @@ -960,9 +948,10 @@ feedInfo->SetLastUpdated(lastupdatedtime); sqlite3_int64 customtitle = sqlite3_column_int64(st, 10); - if (customtitle) { + if (customtitle) + { feedInfo->SetCustomTitle(); - } + } TInt lasterror = sqlite3_column_int(st, 11); feedInfo->SetLastError(lasterror); @@ -974,10 +963,13 @@ CleanupStack::Pop(feedInfo); rc = sqlite3_step(st); + } + CleanupStack::PopAndDestroy();//st } - } - - CleanupStack::PopAndDestroy();//st + else + { + User::Leave(KErrCorrupt); + } DP("DBLoadFeeds END"); } @@ -990,15 +982,15 @@ iSqlBuffer.Format(KSqlStatement, aFeedUid); sqlite3_stmt *st; - - //DP1("SQL statement length=%d", iSqlBuffer.Length()); - + int rc = sqlite3_prepare16_v2(&iDB, (const void*)iSqlBuffer.PtrZ() , -1, &st, (const void**) NULL); - if (rc==SQLITE_OK) { + if (rc==SQLITE_OK) + { Cleanup_sqlite3_finalize_PushL(st); rc = sqlite3_step(st); - if (rc == SQLITE_ROW) { + if (rc == SQLITE_ROW) + { feedInfo = CFeedInfo::NewLC(); const void *urlz = sqlite3_column_text16(st, 0); @@ -1042,9 +1034,17 @@ feedInfo->SetLastError(lasterror); CleanupStack::Pop(feedInfo); - } + } + else + { + User::Leave(KErrNotFound); + } CleanupStack::PopAndDestroy();//st - } + } + else + { + User::Leave(KErrNotFound); + } return feedInfo; } diff -r 554d9980157f -r 223f270fa7ff engine/src/FeedInfo.cpp --- a/engine/src/FeedInfo.cpp Sun Apr 04 00:21:57 2010 +0100 +++ b/engine/src/FeedInfo.cpp Sun Apr 04 15:54:17 2010 +0100 @@ -52,7 +52,9 @@ copy->SetLinkL(Link()); copy->SetBuildDate(BuildDate()); copy->SetLastUpdated(LastUpdated()); - copy->iFeedIcon->Duplicate(iFeedIcon->Handle()); + if (iFeedIcon) { + copy->SetFeedIcon(iFeedIcon); + } copy->SetImageFileNameL(ImageFileName(), NULL); if(CustomTitle()) { @@ -64,6 +66,7 @@ CleanupStack::Pop(copy); return copy; } + CFeedInfo::CFeedInfo() { iCustomTitle = EFalse; @@ -82,7 +85,7 @@ void CFeedInfo::ConstructL() { - iFeedIcon = new (ELeave) CFbsBitmap; + //iFeedIcon = new (ELeave) CFbsBitmap; } EXPORT_C const TDesC& CFeedInfo::Url() const @@ -195,6 +198,7 @@ EXPORT_C void CFeedInfo::SetImageFileNameL(const TDesC& aFileName, CPodcastModel* aPodcastModel) { + DP1("CFeedInfo::SetImageFileNameL BEGIN, aFileName=%S", &aFileName); TFileName cacheFileName; if (iImageFileName) @@ -209,15 +213,21 @@ cacheFileName.Append(parser.Name()); cacheFileName.Append(KMbmExtension()); - if( iFeedIcon->SizeInPixels() == TSize(0,0) && BaflUtils::FileExists(CEikonEnv::Static()->FsSession(), cacheFileName) ) + if (iFeedIcon) { + delete iFeedIcon; + } + + if( BaflUtils::FileExists(CEikonEnv::Static()->FsSession(), cacheFileName) ) { iFeedIcon = CEikonEnv::Static()->CreateBitmapL(cacheFileName, 0); } else if(aPodcastModel && BaflUtils::FileExists(CEikonEnv::Static()->FsSession(), ImageFileName() )) { // If this fails, no reason to worry + iFeedIcon = new CFbsBitmap(); TRAP_IGNORE(aPodcastModel->ImageHandler().LoadFileAndScaleL(FeedIcon(), ImageFileName(), TSize(64,56), *this, Uid())); - } + } + DP("CFeedInfo::SetImageFileNameL END"); } EXPORT_C TBool CFeedInfo::CustomTitle() const diff -r 554d9980157f -r 223f270fa7ff engine/src/OpmlParser.cpp --- a/engine/src/OpmlParser.cpp Sun Apr 04 00:21:57 2010 +0100 +++ b/engine/src/OpmlParser.cpp Sun Apr 04 15:54:17 2010 +0100 @@ -130,18 +130,17 @@ } else if (attr16.Compare(KTagHtmlUrl) == 0) { newFeed->SetLinkL(*val16); hasUrl = ETrue; - // text=... + // title=... } else if (attr16.Compare(KTagTitle) == 0) { newFeed->SetTitleL(*val16); - newFeed->SetCustomTitle(); hasTitle = ETrue; // description= } else if (attr16.Compare(KTagDescription) == 0) { newFeed->SetDescriptionL(*val16); + // text= } else if (attr16.Compare(KTagText) == 0) { if (!hasTitle) { newFeed->SetTitleL(*val16); - newFeed->SetCustomTitle(); hasTitle = ETrue; } } @@ -156,6 +155,14 @@ newFeed->SetTitleL(newFeed->Url()); } + // if the title is the same as the URL, it is hardly a custom + // title, so let's replace it on update + if (newFeed->Title().Length() && + newFeed->Url().Length() && + newFeed->Title().Compare(newFeed->Url()) != 0) { + newFeed->SetCustomTitle(); + } + if (iSearching) { iFeedEngine.AddSearchResultL(newFeed); CleanupStack::Pop(newFeed); diff -r 554d9980157f -r 223f270fa7ff engine/src/PodcastModel.cpp --- a/engine/src/PodcastModel.cpp Sun Apr 04 00:21:57 2010 +0100 +++ b/engine/src/PodcastModel.cpp Sun Apr 04 15:54:17 2010 +0100 @@ -22,6 +22,7 @@ #include "SettingsEngine.h" #include "ShowEngine.h" #include "connectionengine.h" +#include "podcastutils.h" #include #include @@ -84,6 +85,21 @@ iSettingsEngine = CSettingsEngine::NewL(*this); iConnectionEngine = CConnectionEngine::NewL(*this); + TRAPD(err, OpenDBL()); + + if (err != KErrNone) + { + ResetDB(); + + TRAP(err, OpenDBL()); + + if (err != KErrNone) + { + User::Panic(_L("Podcatcher"), 1); + } + + } + iFeedEngine = CFeedEngine::NewL(*this); iShowEngine = CShowEngine::NewL(*this); @@ -237,38 +253,90 @@ } } +void CPodcastModel::ResetDB() + { + DP("CPodcastModel::ResetDB BEGIN"); + + if (iDB != NULL) + { + sqlite3_close(iDB); + iDB = NULL; + } + + TFileName dbFileName; + dbFileName.Copy(iSettingsEngine->PrivatePath()); + dbFileName.Append(KDBFileName); + + // remove the old DB file + if (BaflUtils::FileExists(iFsSession, dbFileName)) + { + BaflUtils::DeleteFile(iFsSession, dbFileName); + } + + // copy template to new DB + TFileName dbTemplate; + dbTemplate.Copy(iSettingsEngine->PrivatePath()); + dbTemplate.Append(KDBTemplateFileName); + + BaflUtils::CopyFile(iFsSession, dbTemplate,dbFileName); + iIsFirstStartup = ETrue; + DP("CPodcastModel::ResetDB END"); + } + + +void CPodcastModel::OpenDBL() + { + DP("CPodcastModel::OpenDBL BEGIN"); + + if (iDB != NULL) + { + sqlite3_close(iDB); + iDB = NULL; + } + + TFileName dbFileName; + dbFileName.Copy(iSettingsEngine->PrivatePath()); + dbFileName.Append(KDBFileName); + + if (!BaflUtils::FileExists(iFsSession, dbFileName)) + { + User::Leave(KErrNotFound); + } + + if (iDB == NULL) { + // open DB + TBuf8 filename8; + filename8.Copy(dbFileName); + int rc = sqlite3_open((const char*) filename8.PtrZ(), &iDB); + if(rc != SQLITE_OK){ + User::Leave(KErrCorrupt); + } + + // do a test query + sqlite3_stmt *st; + rc = sqlite3_prepare_v2(iDB,"select count(*) from feeds" , -1, &st, (const char**) NULL); + if( rc==SQLITE_OK ) + { + Cleanup_sqlite3_finalize_PushL(st); + rc = sqlite3_step(st); + + if (rc != SQLITE_ROW) + { + User::Leave(KErrCorrupt); + } + CleanupStack::PopAndDestroy(); // st + } + else + { + User::Leave(KErrCorrupt); + } + } + + DP("CPodcastModel::OpenDBL END"); + } + sqlite3* CPodcastModel::DB() { - DP("CPodcastModel::DB BEGIN"); - if (iDB == NULL) { - TFileName dbFileName; - dbFileName.Copy(iSettingsEngine->PrivatePath()); - //iFsSession.PrivatePath(dbFileName); - dbFileName.Append(KDBFileName); - DP1("DB is at %S", &dbFileName); - - if (!BaflUtils::FileExists(iFsSession, dbFileName)) { - TFileName dbTemplate; - dbTemplate.Copy(iSettingsEngine->PrivatePath()); - //iFsSession.PrivatePath(dbTemplate); - dbTemplate.Append(KDBTemplateFileName); - DP1("No DB found, copying template from %S", &dbTemplate); - BaflUtils::CopyFile(iFsSession, dbTemplate,dbFileName); - iIsFirstStartup = ETrue; - } - - TBuf8 filename8; - filename8.Copy(dbFileName); - DP("Before sqlite3_open"); - int rc = sqlite3_open((const char*) filename8.PtrZ(), &iDB); - if( rc != SQLITE_OK){ - DP("Error loading DB"); - User::Panic(_L("Podcatcher"), 10); - } - - - } - DP("CPodcastModel::DB END"); return iDB; } diff -r 554d9980157f -r 223f270fa7ff engine/src/ShowEngine.cpp --- a/engine/src/ShowEngine.cpp Sun Apr 04 00:21:57 2010 +0100 +++ b/engine/src/ShowEngine.cpp Sun Apr 04 15:54:17 2010 +0100 @@ -34,15 +34,6 @@ const TUint KMaxDownloadErrors = 3; const TInt KMimeBufLength = 100; -// Cleanup stack macro for SQLite3 -// TODO Move this to some common place. -static void Cleanup_sqlite3_finalize_wrapper(TAny* handle) - { - sqlite3_finalize(static_cast(handle)); - } -#define Cleanup_sqlite3_finalize_PushL(__handle) CleanupStack::PushL(TCleanupItem(&Cleanup_sqlite3_finalize_wrapper, __handle)) - - CShowEngine::CShowEngine(CPodcastModel& aPodcastModel) : iPodcastModel(aPodcastModel), iDB(*aPodcastModel.DB()) diff -r 554d9980157f -r 223f270fa7ff engine/src/ShowInfo.cpp --- a/engine/src/ShowInfo.cpp Sun Apr 04 00:21:57 2010 +0100 +++ b/engine/src/ShowInfo.cpp Sun Apr 04 15:54:17 2010 +0100 @@ -217,10 +217,22 @@ EXPORT_C CShowInfo::CShowInfo(CShowInfo *aInfo) { + if (iTitle) + delete iTitle; iTitle = aInfo->Title().Alloc(); + + if(iUrl) + delete iUrl; iUrl = aInfo->Url().Alloc(); + + if (iDescription) + delete iDescription; iDescription = aInfo->Description().Alloc(); + + if (iFileName) + delete iFileName; iFileName = aInfo->FileName().Alloc(); + iPosition = aInfo->Position(); iPlayTime = aInfo->PlayTime(); iPlayState = aInfo->PlayState(); diff -r 554d9980157f -r 223f270fa7ff group/bld.inf --- a/group/bld.inf Sun Apr 04 00:21:57 2010 +0100 +++ b/group/bld.inf Sun Apr 04 15:54:17 2010 +0100 @@ -22,9 +22,9 @@ PRJ_MMPFILES -//#ifdef SQLITE_INCLUDED +#ifdef SQLITE_INCLUDED ..\engine\sqlite\group\sqlite.mmp -//#endif +#endif PRJ_MMPFILES ..\engine\group\engine.mmp @@ -33,6 +33,7 @@ ..\application\group\Podcast.mmp PRJ_EXPORTS +..\engine\config\podcatcher.sqlite \epoc32\winscw\c\private\A0009D00\podcatcher.sqlite.template ..\engine\config\defaultfeeds.xml \epoc32\winscw\c\private\A0009D00\defaultfeeds.xml ..\engine\config\testfeeds.xml \epoc32\winscw\c\data\testfeeds.xml ..\application\help\podcatcher.hlp \epoc32\winscw\c\resource\help\podcatcher.hlp