2 * Copyright 2004-2006, Jérôme Duval. All rights reserved.
3 * Distributed under the terms of the MIT License.
7 #include "ExpanderRules.h"
13 #include <FindDirectory.h>
17 #include <compat/sys/stat.h>
19 #include "ExpanderSettings.h"
22 static const char* const kRulesDirectoryPath
= "expander/rules";
23 static const char* const kUserRulesFileName
= "rules";
26 // #pragma mark - ExpanderRule
29 ExpanderRule::ExpanderRule(const char* mimeType
,
30 const BString
& filenameExtension
, const BString
& listingCommand
,
31 const BString
& expandCommand
)
34 fFilenameExtension(filenameExtension
),
35 fListingCmd(listingCommand
),
36 fExpandCmd(expandCommand
)
41 // #pragma mark - ExpanderRules
44 ExpanderRules::ExpanderRules()
46 // Load the rules files first, then add the built-in rules. This way the
47 // built-ins can be overridden, if the files contain matching rules.
50 _AddRule("", ".tar.gz", "tar -ztvf %s", "tar -zxf %s");
51 _AddRule("", ".tar.bz2", "tar -jtvf %s", "tar -jxf %s");
52 _AddRule("", ".tar.Z", "tar -Ztvf %s", "tar -Zxf %s");
53 _AddRule("", ".tgz", "tar -ztvf %s", "tar -zxf %s");
54 _AddRule("application/x-tar", ".tar", "tar -tvf %s", "tar -xf %s");
55 _AddRule("application/x-gzip", ".gz", "echo %s | sed 's/.gz$//g'",
56 "gunzip -c %s > `echo %s | sed 's/.gz$//g'`");
57 _AddRule("application/x-bzip2", ".bz2", "echo %s | sed 's/.bz2$//g'",
59 _AddRule("application/zip", ".zip", "unzip -l %s", "unzip -o %s");
60 _AddRule("application/x-zip-compressed", ".zip", "unzip -l %s",
62 _AddRule("application/x-rar", ".rar", "unrar v %s", "unrar x -y %s");
63 _AddRule("application/x-vnd.haiku-package", ".hpkg", "package list %s",
64 "package extract %s");
68 ExpanderRules::~ExpanderRules()
71 while ((item
= fList
.RemoveItem((int32
)0)))
72 delete (ExpanderRule
*)item
;
77 ExpanderRules::MatchingRule(BString
& fileName
, const char* filetype
)
79 int32 count
= fList
.CountItems();
80 int32 length
= fileName
.Length();
81 for (int32 i
= 0; i
< count
; i
++) {
82 ExpanderRule
* rule
= (ExpanderRule
*)fList
.ItemAt(i
);
83 if (rule
->MimeType().IsValid() && rule
->MimeType() == filetype
)
86 int32 extensionPosition
= fileName
.FindLast(rule
->FilenameExtension());
87 if (extensionPosition
!= -1 && extensionPosition
88 == (length
- rule
->FilenameExtension().Length())) {
98 ExpanderRules::MatchingRule(const entry_ref
* ref
)
100 BEntry
entry(ref
, true);
102 BNodeInfo
nodeInfo(&node
);
103 char type
[B_MIME_TYPE_LENGTH
];
104 nodeInfo
.GetType(type
);
105 BString
fileName(ref
->name
);
107 return MatchingRule(fileName
, type
);
112 ExpanderRules::_LoadRulesFiles()
114 // load the user editable rules first
116 if (ExpanderSettings::GetSettingsDirectoryPath(path
) == B_OK
117 && path
.Append(kUserRulesFileName
) == B_OK
) {
118 _LoadRulesFile(path
.Path());
121 // load the rules files from the data directories
122 const directory_which kDirectories
[] = {
123 B_USER_NONPACKAGED_DATA_DIRECTORY
,
124 B_USER_DATA_DIRECTORY
,
125 B_SYSTEM_NONPACKAGED_DATA_DIRECTORY
,
126 B_SYSTEM_DATA_DIRECTORY
129 for (size_t i
= 0; i
< sizeof(kDirectories
) / sizeof(kDirectories
[0]);
131 BDirectory directory
;
132 if (find_directory(kDirectories
[i
], &path
) != B_OK
133 || path
.Append(kRulesDirectoryPath
) != B_OK
134 || directory
.SetTo(path
.Path()) != B_OK
) {
139 while (directory
.GetNextRef(&entry
) == B_OK
) {
141 if (filePath
.SetTo(path
.Path(), entry
.name
) == B_OK
)
142 _LoadRulesFile(filePath
.Path());
149 ExpanderRules::_LoadRulesFile(const char* path
)
151 FILE* file
= fopen(path
, "r");
157 while (fgets(buffer
, 1024 - 1, file
) != NULL
) {
159 int32 firstQuote
= -1;
160 while (buffer
[i
] != '#' && buffer
[i
] != '\n' && j
< 4) {
161 if ((j
== 0 || j
> 1) && buffer
[i
] == '"') {
162 if (firstQuote
>= 0) {
163 strings
[j
++].SetTo(&buffer
[firstQuote
+1],
168 } else if (j
== 1 && (buffer
[i
] == ' ' || buffer
[i
] == '\t')) {
169 if (firstQuote
>= 0) {
170 if (firstQuote
+ 1 != i
) {
171 strings
[j
++].SetTo(&buffer
[firstQuote
+1],
183 _AddRule(strings
[0], strings
[1], strings
[2], strings
[3]);
191 ExpanderRules::_AddRule(const char* mimeType
, const BString
& filenameExtension
,
192 const BString
& listingCommand
, const BString
& expandCommand
)
194 ExpanderRule
* rule
= new(std::nothrow
) ExpanderRule(mimeType
,
195 filenameExtension
, listingCommand
, expandCommand
);
199 if (!fList
.AddItem(rule
)) {
208 // #pragma mark - RuleRefFilter
211 RuleRefFilter::RuleRefFilter(ExpanderRules
& rules
)
220 RuleRefFilter::Filter(const entry_ref
* ref
, BNode
* node
, struct stat_beos
* stat
,
221 const char* filetype
)
223 if (node
->IsDirectory() || node
->IsSymLink())
226 BString
fileName(ref
->name
);
227 return fRules
.MatchingRule(fileName
, filetype
) != NULL
;