229 lines
5.3 KiB
C++
229 lines
5.3 KiB
C++
/*
|
|
* Copyright 2004-2006, Jérôme Duval. All rights reserved.
|
|
* Distributed under the terms of the MIT License.
|
|
*/
|
|
|
|
|
|
#include "ExpanderRules.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
|
|
#include <FindDirectory.h>
|
|
#include <NodeInfo.h>
|
|
#include <Path.h>
|
|
|
|
#include <compat/sys/stat.h>
|
|
|
|
#include "ExpanderSettings.h"
|
|
|
|
|
|
static const char* const kRulesDirectoryPath = "expander/rules";
|
|
static const char* const kUserRulesFileName = "rules";
|
|
|
|
|
|
// #pragma mark - ExpanderRule
|
|
|
|
|
|
ExpanderRule::ExpanderRule(const char* mimeType,
|
|
const BString& filenameExtension, const BString& listingCommand,
|
|
const BString& expandCommand)
|
|
:
|
|
fMimeType(mimeType),
|
|
fFilenameExtension(filenameExtension),
|
|
fListingCmd(listingCommand),
|
|
fExpandCmd(expandCommand)
|
|
{
|
|
}
|
|
|
|
|
|
// #pragma mark - ExpanderRules
|
|
|
|
|
|
ExpanderRules::ExpanderRules()
|
|
{
|
|
// 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();
|
|
|
|
_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");
|
|
_AddRule("application/x-vnd.haiku-package", ".hpkg", "package list %s",
|
|
"package extract %s");
|
|
}
|
|
|
|
|
|
ExpanderRules::~ExpanderRules()
|
|
{
|
|
void* item;
|
|
while ((item = fList.RemoveItem((int32)0)))
|
|
delete (ExpanderRule*)item;
|
|
}
|
|
|
|
|
|
ExpanderRule*
|
|
ExpanderRules::MatchingRule(BString& fileName, const char* filetype)
|
|
{
|
|
int32 count = fList.CountItems();
|
|
int32 length = fileName.Length();
|
|
for (int32 i = 0; i < count; i++) {
|
|
ExpanderRule* rule = (ExpanderRule*)fList.ItemAt(i);
|
|
if (rule->MimeType().IsValid() && rule->MimeType() == filetype)
|
|
return rule;
|
|
|
|
int32 extensionPosition = fileName.FindLast(rule->FilenameExtension());
|
|
if (extensionPosition != -1 && extensionPosition
|
|
== (length - rule->FilenameExtension().Length())) {
|
|
return rule;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
ExpanderRule*
|
|
ExpanderRules::MatchingRule(const entry_ref* ref)
|
|
{
|
|
BEntry entry(ref, true);
|
|
BNode node(&entry);
|
|
BNodeInfo nodeInfo(&node);
|
|
char type[B_MIME_TYPE_LENGTH];
|
|
nodeInfo.GetType(type);
|
|
BString fileName(ref->name);
|
|
|
|
return MatchingRule(fileName, type);
|
|
}
|
|
|
|
|
|
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_SYSTEM_NONPACKAGED_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& listingCommand, const BString& expandCommand)
|
|
{
|
|
ExpanderRule* rule = new(std::nothrow) ExpanderRule(mimeType,
|
|
filenameExtension, listingCommand, expandCommand);
|
|
if (rule == NULL)
|
|
return false;
|
|
|
|
if (!fList.AddItem(rule)) {
|
|
delete rule;
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
// #pragma mark - RuleRefFilter
|
|
|
|
|
|
RuleRefFilter::RuleRefFilter(ExpanderRules& rules)
|
|
:
|
|
BRefFilter(),
|
|
fRules(rules)
|
|
{
|
|
}
|
|
|
|
|
|
bool
|
|
RuleRefFilter::Filter(const entry_ref* ref, BNode* node, struct stat_beos* stat,
|
|
const char* filetype)
|
|
{
|
|
if (node->IsDirectory() || node->IsSymLink())
|
|
return true;
|
|
|
|
BString fileName(ref->name);
|
|
return fRules.MatchingRule(fileName, filetype) != NULL;
|
|
}
|