vfs: check userland buffers before reading them.
[haiku.git] / src / apps / expander / ExpanderRules.cpp
blob91eeada6fff493fcadc80c85f9c80e0276e89d65
1 /*
2 * Copyright 2004-2006, Jérôme Duval. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 */
7 #include "ExpanderRules.h"
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <unistd.h>
13 #include <FindDirectory.h>
14 #include <NodeInfo.h>
15 #include <Path.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)
33 fMimeType(mimeType),
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.
48 _LoadRulesFiles();
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'",
58 "bunzip2 -k %s");
59 _AddRule("application/zip", ".zip", "unzip -l %s", "unzip -o %s");
60 _AddRule("application/x-zip-compressed", ".zip", "unzip -l %s",
61 "unzip -o %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()
70 void* item;
71 while ((item = fList.RemoveItem((int32)0)))
72 delete (ExpanderRule*)item;
76 ExpanderRule*
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)
84 return rule;
86 int32 extensionPosition = fileName.FindLast(rule->FilenameExtension());
87 if (extensionPosition != -1 && extensionPosition
88 == (length - rule->FilenameExtension().Length())) {
89 return rule;
93 return NULL;
97 ExpanderRule*
98 ExpanderRules::MatchingRule(const entry_ref* ref)
100 BEntry entry(ref, true);
101 BNode node(&entry);
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);
111 void
112 ExpanderRules::_LoadRulesFiles()
114 // load the user editable rules first
115 BPath path;
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]);
130 i++) {
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) {
135 continue;
138 entry_ref entry;
139 while (directory.GetNextRef(&entry) == B_OK) {
140 BPath filePath;
141 if (filePath.SetTo(path.Path(), entry.name) == B_OK)
142 _LoadRulesFile(filePath.Path());
148 void
149 ExpanderRules::_LoadRulesFile(const char* path)
151 FILE* file = fopen(path, "r");
152 if (file == NULL)
153 return;
155 char buffer[1024];
156 BString strings[4];
157 while (fgets(buffer, 1024 - 1, file) != NULL) {
158 int32 i = 0, j = 0;
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],
164 i - firstQuote - 1);
165 firstQuote = -1;
166 } else
167 firstQuote = i;
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],
172 i - firstQuote - 1);
173 firstQuote = -1;
174 } else
175 firstQuote = i;
176 } else
177 firstQuote = i;
179 i++;
182 if (j == 4)
183 _AddRule(strings[0], strings[1], strings[2], strings[3]);
186 fclose(file);
190 bool
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);
196 if (rule == NULL)
197 return false;
199 if (!fList.AddItem(rule)) {
200 delete rule;
201 return false;
204 return true;
208 // #pragma mark - RuleRefFilter
211 RuleRefFilter::RuleRefFilter(ExpanderRules& rules)
213 BRefFilter(),
214 fRules(rules)
219 bool
220 RuleRefFilter::Filter(const entry_ref* ref, BNode* node, struct stat_beos* stat,
221 const char* filetype)
223 if (node->IsDirectory() || node->IsSymLink())
224 return true;
226 BString fileName(ref->name);
227 return fRules.MatchingRule(fileName, filetype) != NULL;