diff --git a/TODO.txt b/TODO.txt index faf84ee..08c8383 100644 --- a/TODO.txt +++ b/TODO.txt @@ -12,9 +12,6 @@ Important improvements: so. * _Huge_ problem, but I haven't had luck figuring it out yet… * Move from BLists to BObjectLists where possible -* General input sanitization -* File error-handling - * e.g., Utils.cpp's userFileError * Fix background of Feeds List error status icon (it's black, not transparent) * Check if arg is a file or not (treat appropriately) * Make UI friendly to whatever font-size you throw at it diff --git a/src/EntriesView.cpp b/src/EntriesView.cpp index 2bca8c5..788c50f 100644 --- a/src/EntriesView.cpp +++ b/src/EntriesView.cpp @@ -7,6 +7,7 @@ #include +#include #include #include #include @@ -51,7 +52,32 @@ EntriesView::MessageReceived(BMessage* msg) status_t result = ((App*)be_app)->fPreferences->SetEntryDir( fEntryFolderText->Text()); if (result != B_OK) - userFileError(result, fEntryFolderText->Text()); + _FileError(result); + + fEntryFolderText->SetText(((App*)be_app)->fPreferences->EntryDir()); + break; + } + case kEntryFolderBrowse: + { + entry_ref appsRef; + fEntryFolderPanel = new BFilePanel(B_OPEN_PANEL, NULL, NULL, + B_DIRECTORY_NODE, false, new BMessage(kEntryFolderPath)); + fEntryFolderPanel->Show(); + fEntryFolderPanel->SetTarget(this); + break; + } + case kEntryFolderPath: + { + entry_ref ref; + if (msg->HasRef("refs") && msg->FindRef("refs", &ref) == B_OK) { + status_t result = ((App*)be_app)->fPreferences->SetEntryDir( + BPath(&ref).Path()); + if (result != B_OK) + _FileError(result); + } + + fEntryFolderText->SetText(((App*)be_app)->fPreferences->EntryDir()); + delete fEntryFolderPanel; break; } case kOpenHtmlRadio: @@ -70,6 +96,16 @@ EntriesView::MessageReceived(BMessage* msg) fOpenWithMenuField->MenuItem()->Label()); break; } + case kOpenWithBrowse: + { + entry_ref appsRef; + BEntry("/boot/system/apps/").GetRef(&appsRef); + + fOpenWithPanel = new BFilePanel(B_OPEN_PANEL, NULL, &appsRef, + B_FILE_NODE, false, new BMessage(kOpenWithPath)); + fOpenWithPanel->Show(); + fOpenWithPanel->SetTarget(this); + } case kOpenWithPath: { entry_ref ref; @@ -81,16 +117,6 @@ EntriesView::MessageReceived(BMessage* msg) delete fOpenWithPanel; break; } - case kOpenWithBrowse: - { - entry_ref appsRef; - BEntry("/boot/system/apps/").GetRef(&appsRef); - - fOpenWithPanel = new BFilePanel(B_OPEN_PANEL, NULL, &appsRef, - B_FILE_NODE, false, new BMessage(kOpenWithPath)); - fOpenWithPanel->Show(); - fOpenWithPanel->SetTarget(this); - } default: { BGroupView::MessageReceived(msg); @@ -213,3 +239,29 @@ EntriesView::_PopulateOpenWithMenu() } +void +EntriesView::_FileError(status_t result) +{ + BPath cfgPath; + find_directory(B_USER_SETTINGS_DIRECTORY, &cfgPath); + + if (result == B_NOT_A_DIRECTORY) { + BAlert* alert = new BAlert("Entries Directory", "The path you " + "selected isn't a folder― please choose another path.", "OK", + NULL, NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT); + alert->Go(); + return; + } + + userFileError(result, "Entries Directory", + "Couldn't open this folder because no path was specified.\n" + "Please select a new folder.", + "Couldn't open this folder because permission was denied.\n" + "This usually means that you don't have read permissions.\nPlease make " + "sure that your user has read-access to this folder.\nCheck your OS " + "documentation for more information.", + "There is not enough memory available on your system to access the " + "given path.\nPlease try closing a few applications and restarting Pogger."); +} + + diff --git a/src/EntriesView.h b/src/EntriesView.h index 34a8e91..8f78065 100644 --- a/src/EntriesView.h +++ b/src/EntriesView.h @@ -23,6 +23,7 @@ enum { kEntryFolderText = 'txef', kEntryFolderBrowse = 'tbef', + kEntryFolderPath = 'txep', kOpenHtmlRadio = 'rdow', kOpenUrlRadio = 'roow', kOpenWithSelect = 'mnow', @@ -42,11 +43,14 @@ private: void _InitInterface(); void _PopulateOpenWithMenu(); + void _FileError(status_t result); + BBox* fSavingBox; BStringView* fEntryFolderLabel; BTextControl* fEntryFolderText; BButton* fEntryFolderBrowseButton; + BFilePanel* fEntryFolderPanel; BBox* fOpeningBox; BStringView* fOpenAsLabel; diff --git a/src/FeedEditWindow.cpp b/src/FeedEditWindow.cpp index 34e554b..2470fd9 100644 --- a/src/FeedEditWindow.cpp +++ b/src/FeedEditWindow.cpp @@ -5,6 +5,7 @@ #include "FeedEditWindow.h" +#include #include #include #include @@ -121,7 +122,7 @@ FeedEditWindow::_InitInterface() .End(); } -#include + void FeedEditWindow::_SaveFeed() { @@ -132,6 +133,24 @@ FeedEditWindow::_SaveFeed() BString title(fFeedNameText->Text()); const char* urlString = fFeedUrlText->Text(); + BUrl url = BUrl(urlString); + + if (BString(urlString).IsEmpty() == true) { + BAlert* emptyAlert = new BAlert("Invalid Feed", + "Please enter a URL.", "OK", NULL, NULL, + B_WIDTH_AS_USUAL, B_OFFSET_SPACING, B_WARNING_ALERT); + emptyAlert->Go(); + return; + } + + if (url.IsValid() == false) { + BAlert* invAlert = new BAlert("Invalid Feed", + "The given URL is invalid. Please make sure you typed it in correctly.", + "OK", NULL, NULL, B_WIDTH_AS_USUAL, B_OFFSET_SPACING, B_WARNING_ALERT); + invAlert->Go(); + return; + } + BString filename; if (title.IsEmpty()) filename = BString(urlString); diff --git a/src/Preferences.cpp b/src/Preferences.cpp index 818a8eb..51e31e3 100644 --- a/src/Preferences.cpp +++ b/src/Preferences.cpp @@ -5,10 +5,10 @@ #include "Preferences.h" -#include - #include +#include "Util.h" + Preferences::Preferences() { } @@ -27,9 +27,12 @@ Preferences::Load() cfgPath.Append("Pogger"); BString filename = BString(cfgPath.Path()).Append("/Settings"); - BFile file(filename.String(), B_READ_ONLY); + BFile file = BFile(filename.String(), B_READ_ONLY); status_t result = file.InitCheck(); + if (result == B_PERMISSION_DENIED || result == B_NO_MEMORY) + _FileError(result); + BMessage storage; storage.Unflatten(&file); @@ -68,8 +71,12 @@ Preferences::Save() BMessage storage; BString filename = BString(cfgPath.Path()).Append("/Settings"); - BFile file(filename.String(), B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE); + BFile file = BFile(filename.String(), B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE); status_t result = file.InitCheck(); + if (result != B_OK) { + _FileError(result); + return; + } storage.AddString("entryDir", fEntryDir.String()); storage.AddString("openWith", fOpenWith.String()); @@ -128,7 +135,10 @@ Preferences::EntryDir() status_t Preferences::SetEntryDir(const char* path) { - status_t testStatus = BEntry(path).InitCheck(); + status_t testStatus = BDirectory(path).InitCheck(); + if (BDirectory(path).IsDirectory() == false) + return B_NOT_A_DIRECTORY; + if (testStatus == B_OK) fEntryDir = BString(path); return testStatus; @@ -171,3 +181,28 @@ Preferences::SetEntryOpenAsHtml(bool asHtml) } +void +Preferences::_FileError(status_t result) +{ + BPath cfgPath; + find_directory(B_USER_SETTINGS_DIRECTORY, &cfgPath); + + BString permLabel("Couldn't open the preferences file because permission " + "was denied.\nThis usually means that you don't have read permissions to " + "your settings directory.\nPlease make sure that your user has " + "read-access to your settings directory― likely %path%.\nCheck your OS " + "documentation for more information."); + permLabel.ReplaceAll("%path%", cfgPath.Path()); + + userFileError(result, "Preferences file", + "Couldn't open the preferences file because the path is not " + "specified.\nThis usually means that the programmer made a mistake.\n" + "Please submit a bug report to the Pogger repository on GitHub.\n" + "Your personal settings will not be loaded.", + permLabel.String(), + "There is not enough memory available on your system to load the " + "preferences file.\nPlease try closing a few applications and restarting " + "Pogger."); +} + + diff --git a/src/Preferences.h b/src/Preferences.h index 081079c..ed3b13b 100644 --- a/src/Preferences.h +++ b/src/Preferences.h @@ -49,6 +49,8 @@ public: int32 fTabSelection; private: + void _FileError(status_t result); + int8 fUpdateInterval; BString fEntryDir; diff --git a/src/Util.cpp b/src/Util.cpp index b812ee4..51faa8d 100644 --- a/src/Util.cpp +++ b/src/Util.cpp @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -165,8 +166,35 @@ fetch(BUrl url, BDataIO* reply, BString* hash, int timeout) void -userFileError(status_t status, const char* path) +userFileError(status_t status, const char* title, const char* bad_value, + const char* perm_denied, const char* no_memory) { + BString label; + + switch (status) { + case B_BAD_VALUE: + { + label = bad_value; + break; + } + case B_READ_ONLY_DEVICE: + case B_PERMISSION_DENIED: + { + label = perm_denied; + break; + } + case B_NO_MEMORY: + { + label = no_memory; + break; + } + default: + return; + } + + BAlert* alert = new BAlert(title, label.String(), "OK", NULL, NULL, + B_WIDTH_AS_USUAL, B_WARNING_ALERT); + alert->Go(); } diff --git a/src/Util.h b/src/Util.h index 474cf49..173699b 100644 --- a/src/Util.h +++ b/src/Util.h @@ -31,15 +31,19 @@ const char* tempFileName(const char* dir, const char* name, const char* suffix); int32 fetch(BUrl url, BDataIO* reply, BString* hash, int timeout); -void userFileError(status_t status, const char* path); +// The strings passed to this function are adapted from those in +// Calendar (utils/Preferences.cpp). +void userFileError(status_t status, const char* title, const char* bad_value, + const char* perm_denied, const char* no_memory); // Takes a (probably invalid) bit of HTML and adds necessary elements in a // temporary copy. Returns an entry_ref to said temporary copy. entry_ref tempHtmlFile(entry_ref* ref, const char* title); -// Ripped from Calendar (utils/ResourceLoader.cpp) +// Also ripped from Calendar (utils/ResourceLoader.cpp) BBitmap* loadVectorIcon(const char* name, int32 iconSize = 32, int32 cropSize = 22); + #endif // UTIL_H