diff --git a/build/jam/ImageRules b/build/jam/ImageRules index 8b5f7cfbcc..e73b731a1b 100644 --- a/build/jam/ImageRules +++ b/build/jam/ImageRules @@ -1098,43 +1098,6 @@ rule AddGroupToHaikuImage group : gid : members AddEntryToHaikuImageUserGroupFile group : $(entry) ; } -rule AddEntryToHaikuImageExpanderRuleFile file : entry -{ - local allEntries - = [ on $(file) return $(HAIKU_IMAGE_EXPANDER_RULES_ENTRIES) ] ; - - if $(allEntries) { - allEntries = $(allEntries)!$(entry) ; - } else { - allEntries = $(entry) ; - - Always $(file) ; - MakeLocate $(file) : $(HAIKU_COMMON_PLATFORM_OBJECT_DIR) ; - BuildHaikuImageExpanderRules $(file) ; - AddFilesToHaikuImage common data : $(file) ; - } - - HAIKU_IMAGE_EXPANDER_RULES_ENTRIES on $(file) = $(allEntries) ; -} - -actions BuildHaikuImageExpanderRules -{ - echo -e "$(HAIKU_IMAGE_EXPANDER_RULES_ENTRIES)" | tr '!' '\n' > $(1) -} - -rule AddExpanderRuleToHaikuImage mimetype : extension : list : extract -{ - #AddExpanderRuleToHaikuImage : : : - - if ! $(mimetype) || ! $(extension) || ! $(list) || ! $(extract) { - Exit "Invalid expander rule specification passed to AddExpanderRule." ; - } - - local entry - = "\\\"$(mimetype)\\\"\\\t$(extension)\\\t\\\"$(list)\\\"\\\t\\\"$(extract)\\\"" ; - AddEntryToHaikuImageExpanderRuleFile expander.rules - : $(entry) ; -} rule AddOptionalPackageDescriptionToHaikuImage file : searchPath { diff --git a/build/jam/OptionalPackages b/build/jam/OptionalPackages index a3375fbe36..d829184cf0 100644 --- a/build/jam/OptionalPackages +++ b/build/jam/OptionalPackages @@ -1597,11 +1597,6 @@ if [ IsOptionalHaikuImagePackageAdded P7zip ] { InstallOptionalHaikuImagePackage $(baseURL)/p7zip-9.20.1-x86_64-2012-12-08.zip ; } - - AddExpanderRuleToHaikuImage "application/x-7z-compressed" : .7z - : "7za l \\0045s" - : "7za x -y \\0045s" - ; } else { Echo "No optional package P7zip available for $(TARGET_ARCH)" ; } @@ -2160,20 +2155,6 @@ if [ IsOptionalHaikuImagePackageAdded XZ-Utils ] { Echo "No optional package XZ-Utils available for gcc" $(HAIKU_GCC_VERSION[1]) ; } - -# TODO: Move rules into package! -# AddExpanderRuleToHaikuImage "application/x-xz" : .tar.xz -# : "tar -Jtvf \\0045s" -# : "tar -Jxvf \\0045s" -# ; -# AddExpanderRuleToHaikuImage "application/x-xz" : .txz -# : "tar -Jtvf \\0045s" -# : "tar -Jxvf \\0045s" -# ; -# AddExpanderRuleToHaikuImage "application/x-xz" : .xz -# : "echo \\0045s | sed 's/.xz\\\$//g'" -# : "xz -df \\0045s" -# ; } else { Echo "No optional package XZ-Utils available for $(TARGET_ARCH)" ; } diff --git a/src/apps/expander/ExpanderRules.cpp b/src/apps/expander/ExpanderRules.cpp index 9a42eae2f6..eeb4672218 100644 --- a/src/apps/expander/ExpanderRules.cpp +++ b/src/apps/expander/ExpanderRules.cpp @@ -16,23 +16,19 @@ #include +#include "ExpanderSettings.h" + + +static const char* const kRulesDirectoryPath = "expander/rules"; +static const char* const kUserRulesFileName = "rules"; + // #pragma mark - ExpanderRule -ExpanderRule::ExpanderRule(BString mimetype, BString filenameExtension, - BString listingCmd, BString expandCmd) - : - fMimeType(mimetype.String()), - fFilenameExtension(filenameExtension), - fListingCmd(listingCmd), - fExpandCmd(expandCmd) -{ -} - - -ExpanderRule::ExpanderRule(const char* mimetype, const char* filenameExtension, - const char* listingCmd, const char* expandCmd) +ExpanderRule::ExpanderRule(const char* mimetype, + const BString& filenameExtension, const BString& listingCmd, + const BString& expandCmd) : fMimeType(mimetype), fFilenameExtension(filenameExtension), @@ -47,68 +43,23 @@ ExpanderRule::ExpanderRule(const char* mimetype, const char* filenameExtension, ExpanderRules::ExpanderRules() { - fList.AddItem(new ExpanderRule("", ".tar.gz", - "tar -ztvf %s", "tar -zxf %s")); - fList.AddItem(new ExpanderRule("", ".tar.bz2", - "tar -jtvf %s", "tar -jxf %s")); - fList.AddItem(new ExpanderRule("", ".tar.Z", - "tar -Ztvf %s", "tar -Zxf %s")); - fList.AddItem(new ExpanderRule("", ".tgz", - "tar -ztvf %s", "tar -zxf %s")); - fList.AddItem(new ExpanderRule("application/x-tar", ".tar", - "tar -tvf %s", "tar -xf %s")); - fList.AddItem(new ExpanderRule("application/x-gzip", ".gz", - "echo %s | sed 's/.gz$//g'", - "gunzip -c %s > `echo %s | sed 's/.gz$//g'`")); - fList.AddItem(new ExpanderRule("application/x-bzip2", ".bz2", - "echo %s | sed 's/.bz2$//g'", "bunzip2 -k %s")); - fList.AddItem(new ExpanderRule("application/zip", ".zip", - "unzip -l %s", "unzip -o %s")); - fList.AddItem(new ExpanderRule("application/x-zip-compressed", ".zip", - "unzip -l %s", "unzip -o %s")); - fList.AddItem(new ExpanderRule("application/x-rar", ".rar", - "unrar v %s", "unrar x -y %s")); + // Load the rules files first, then add the built-in rules. This way the + // built-ins can be overridden, if the files contain matching rules. + _LoadRulesFiles(); - BFile file; - if (_Open(&file) != B_OK) - return; - - int fd = file.Dup(); - FILE* f = fdopen(fd, "r"); - - char buffer[1024]; - BString strings[4]; - while (fgets(buffer, 1024 - 1, f) != NULL) { - int32 i = 0, j = 0; - int32 firstQuote = -1; - while (buffer[i] != '#' && buffer[i] != '\n' && j < 4) { - if ((j == 0 || j > 1) && buffer[i] == '"') { - if (firstQuote >= 0) { - strings[j++].SetTo(&buffer[firstQuote+1], - i - firstQuote - 1); - firstQuote = -1; - } else - firstQuote = i; - } else if (j == 1 && (buffer[i] == ' ' || buffer[i] == '\t')) { - if (firstQuote >= 0) { - if (firstQuote + 1 != i) { - strings[j++].SetTo(&buffer[firstQuote+1], - i - firstQuote - 1); - firstQuote = -1; - } else - firstQuote = i; - } else - firstQuote = i; - } - i++; - } - if (j == 4) { - fList.AddItem(new ExpanderRule(strings[0], strings[1], strings[2], - strings[3])); - } - } - fclose(f); - close(fd); + _AddRule("", ".tar.gz", "tar -ztvf %s", "tar -zxf %s"); + _AddRule("", ".tar.bz2", "tar -jtvf %s", "tar -jxf %s"); + _AddRule("", ".tar.Z", "tar -Ztvf %s", "tar -Zxf %s"); + _AddRule("", ".tgz", "tar -ztvf %s", "tar -zxf %s"); + _AddRule("application/x-tar", ".tar", "tar -tvf %s", "tar -xf %s"); + _AddRule("application/x-gzip", ".gz", "echo %s | sed 's/.gz$//g'", + "gunzip -c %s > `echo %s | sed 's/.gz$//g'`"); + _AddRule("application/x-bzip2", ".bz2", "echo %s | sed 's/.bz2$//g'", + "bunzip2 -k %s"); + _AddRule("application/zip", ".zip", "unzip -l %s", "unzip -o %s"); + _AddRule("application/x-zip-compressed", ".zip", "unzip -l %s", + "unzip -o %s"); + _AddRule("application/x-rar", ".rar", "unrar v %s", "unrar x -y %s"); } @@ -120,28 +71,6 @@ ExpanderRules::~ExpanderRules() } -status_t -ExpanderRules::_Open(BFile* file) -{ - directory_which which[] = { - B_USER_DATA_DIRECTORY, - B_COMMON_DATA_DIRECTORY - }; - - for (size_t i = 0; i < sizeof(which) / sizeof(which[0]); i++) { - BPath path; - if (find_directory(which[i], &path) != B_OK) - continue; - - path.Append("expander.rules"); - if (file->SetTo(path.Path(), B_READ_ONLY) == B_OK) - return B_OK; - } - - return B_ENTRY_NOT_FOUND; -} - - ExpanderRule* ExpanderRules::MatchingRule(BString& fileName, const char* filetype) { @@ -173,6 +102,100 @@ ExpanderRules::MatchingRule(const entry_ref* ref) } +void +ExpanderRules::_LoadRulesFiles() +{ + // load the user editable rules first + BPath path; + if (ExpanderSettings::GetSettingsDirectoryPath(path) == B_OK + && path.Append(kUserRulesFileName) == B_OK) { + _LoadRulesFile(path.Path()); + } + + // load the rules files from the data directories + const directory_which kDirectories[] = { + B_USER_NONPACKAGED_DATA_DIRECTORY, + B_USER_DATA_DIRECTORY, + B_COMMON_NONPACKAGED_DATA_DIRECTORY, + B_COMMON_DATA_DIRECTORY, + B_SYSTEM_DATA_DIRECTORY + }; + + for (size_t i = 0; i < sizeof(kDirectories) / sizeof(kDirectories[0]); + i++) { + BDirectory directory; + if (find_directory(kDirectories[i], &path) != B_OK + || path.Append(kRulesDirectoryPath) != B_OK + || directory.SetTo(path.Path()) != B_OK) { + continue; + } + + entry_ref entry; + while (directory.GetNextRef(&entry) == B_OK) { + BPath filePath; + if (filePath.SetTo(path.Path(), entry.name) == B_OK) + _LoadRulesFile(filePath.Path()); + } + } +} + + +void +ExpanderRules::_LoadRulesFile(const char* path) +{ + FILE* file = fopen(path, "r"); + if (file == NULL) + return; + + char buffer[1024]; + BString strings[4]; + while (fgets(buffer, 1024 - 1, file) != NULL) { + int32 i = 0, j = 0; + int32 firstQuote = -1; + while (buffer[i] != '#' && buffer[i] != '\n' && j < 4) { + if ((j == 0 || j > 1) && buffer[i] == '"') { + if (firstQuote >= 0) { + strings[j++].SetTo(&buffer[firstQuote+1], + i - firstQuote - 1); + firstQuote = -1; + } else + firstQuote = i; + } else if (j == 1 && (buffer[i] == ' ' || buffer[i] == '\t')) { + if (firstQuote >= 0) { + if (firstQuote + 1 != i) { + strings[j++].SetTo(&buffer[firstQuote+1], + i - firstQuote - 1); + firstQuote = -1; + } else + firstQuote = i; + } else + firstQuote = i; + } + i++; + } + if (j == 4) + _AddRule(strings[0], strings[1], strings[2], strings[3]); + } + + fclose(file); +} + + +bool +ExpanderRules::_AddRule(const char* mimetype, const BString& filenameExtension, + const BString& listingCmd, const BString& expandCmd) +{ + ExpanderRule* rule = new(std::nothrow) ExpanderRule(mimetype, + filenameExtension, listingCmd, expandCmd); + if (rule == NULL || !fList.AddItem(rule)) { + delete rule; + return false; + } + + return true; +} + + // #pragma mark - RuleRefFilter diff --git a/src/apps/expander/ExpanderRules.h b/src/apps/expander/ExpanderRules.h index 8918f9292e..c1011b607d 100644 --- a/src/apps/expander/ExpanderRules.h +++ b/src/apps/expander/ExpanderRules.h @@ -16,13 +16,10 @@ class ExpanderRule { public: - ExpanderRule(BString mimetype, - BString filenameExtension, - BString listingCmd, BString expandCmd); ExpanderRule(const char* mimetype, - const char* filenameExtension, - const char* listingCmd, - const char* expandCmd); + const BString& filenameExtension, + const BString& listingCmd, + const BString& expandCmd); const BMimeType& MimeType() const { return fMimeType; } @@ -51,7 +48,13 @@ public: ExpanderRule* MatchingRule(const entry_ref* ref); private: - status_t _Open(BFile* file); + void _LoadRulesFiles(); + void _LoadRulesFile(const char* path); + + bool _AddRule(const char* mimetype, + const BString& filenameExtension, + const BString& listingCmd, + const BString& expandCmd); private: BList fList; diff --git a/src/apps/expander/ExpanderSettings.cpp b/src/apps/expander/ExpanderSettings.cpp index 43acb7f5bb..04bf05f10a 100644 --- a/src/apps/expander/ExpanderSettings.cpp +++ b/src/apps/expander/ExpanderSettings.cpp @@ -181,14 +181,25 @@ ExpanderSettings::~ExpanderSettings() } +/*static*/ status_t +ExpanderSettings::GetSettingsDirectoryPath(BPath& _path) +{ + status_t error = find_directory(B_USER_SETTINGS_DIRECTORY, &_path); + return error == B_OK ? _path.Append("expander") : error; +} + + status_t ExpanderSettings::Open(BFile *file, int32 mode) { BPath path; - if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK) - return B_ERROR; + status_t error = GetSettingsDirectoryPath(path); + if (error != B_OK) + return error; - path.Append("Expander_Settings"); + error = path.Append("settings"); + if (error != B_OK) + return error; return file->SetTo(path.Path(), mode); } diff --git a/src/apps/expander/ExpanderSettings.h b/src/apps/expander/ExpanderSettings.h index 5d475a93b8..dff7ebdcff 100644 --- a/src/apps/expander/ExpanderSettings.h +++ b/src/apps/expander/ExpanderSettings.h @@ -32,6 +32,10 @@ #include #include + +class BPath; + + static const uint32 kMsgExpanderSettings = 'Exst'; class ExpanderSettings { @@ -42,6 +46,8 @@ class ExpanderSettings { const BMessage &Message() const { return fMessage; } void UpdateFrom(BMessage *message); + static status_t GetSettingsDirectoryPath(BPath& _path); + private: status_t Open(BFile *file, int32 mode);