1/*
2 * Copyright 2004-2006, J��r��me Duval. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include "ExpanderRules.h"
8
9#include <FindDirectory.h>
10#include <stdlib.h>
11#include <Path.h>
12#include <NodeInfo.h>
13#include <stdio.h>
14#include <unistd.h>
15
16#include <compat/sys/stat.h>
17
18
19ExpanderRule::ExpanderRule(BString mimetype, BString filenameExtension,
20	BString listingCmd, BString expandCmd)
21	:
22	fMimeType(mimetype.String()),
23	fFilenameExtension(filenameExtension),
24	fListingCmd(listingCmd),
25	fExpandCmd(expandCmd)
26{
27}
28
29
30ExpanderRule::ExpanderRule(const char* mimetype, const char* filenameExtension,
31	const char* listingCmd, const char* expandCmd)
32	:
33	fMimeType(mimetype),
34	fFilenameExtension(filenameExtension),
35	fListingCmd(listingCmd),
36	fExpandCmd(expandCmd)
37{
38}
39
40
41ExpanderRules::ExpanderRules()
42{
43	fList.AddItem(new ExpanderRule("", 								".tar.gz", 	"tar -ztvf %s", 				"tar -zxf %s"));
44	fList.AddItem(new ExpanderRule("", 								".tar.bz2", "tar -jtvf %s",					"tar -jxf %s"));
45	fList.AddItem(new ExpanderRule("", 								".tar.Z", 	"tar -Ztvf %s", 				"tar -Zxf %s"));
46	fList.AddItem(new ExpanderRule("", 								".tgz", 	"tar -ztvf %s", 				"tar -zxf %s"));
47	fList.AddItem(new ExpanderRule("application/x-tar", 			".tar", 	"tar -tvf %s", 					"tar -xf %s"));
48	fList.AddItem(new ExpanderRule("application/x-gzip",			".gz", 		"echo %s | sed 's/.gz$//g'", 	"gunzip -c %s > `echo %s | sed 's/.gz$//g'`"));
49	fList.AddItem(new ExpanderRule("application/x-bzip2",			".bz2", 	"echo %s | sed 's/.bz2$//g'", 	"bunzip2 -k %s"));
50	fList.AddItem(new ExpanderRule("application/zip", 				".zip", 	"unzip -l %s", 					"unzip -o %s"));
51	fList.AddItem(new ExpanderRule("application/x-zip-compressed", 	".zip", 	"unzip -l %s", 					"unzip -o %s"));
52	fList.AddItem(new ExpanderRule("application/x-rar",				".rar", 	"unrar v %s", 					"unrar x -y %s"));
53
54	BFile file;
55	if (Open(&file) != B_OK)
56		return;
57
58	int fd = file.Dup();
59	FILE * f = fdopen(fd, "r");
60
61	char buffer[1024];
62	BString strings[4];
63	while (fgets(buffer, 1024 - 1, f) != NULL) {
64		int32 i = 0, j = 0;
65		int32 firstQuote = -1;
66		while (buffer[i] != '#' && buffer[i] != '\n' && j < 4) {
67			if ((j == 0 || j > 1) && buffer[i] == '"') {
68				if (firstQuote >= 0) {
69					strings[j++].SetTo(&buffer[firstQuote+1], i - firstQuote - 1);
70					firstQuote = -1;
71				} else
72					firstQuote = i;
73			} else if (j == 1 && (buffer[i] == ' ' || buffer[i] == '\t')) {
74				if (firstQuote >= 0) {
75					if (firstQuote + 1 != i) {
76						strings[j++].SetTo(&buffer[firstQuote+1], i - firstQuote - 1);
77						firstQuote = -1;
78					} else
79						firstQuote = i;
80				} else
81					firstQuote = i;
82			}
83			i++;
84		}
85		if (j == 4) {
86			fList.AddItem(new ExpanderRule(strings[0], strings[1], strings[2], strings[3]));
87		}
88	}
89	fclose(f);
90	close(fd);
91}
92
93
94ExpanderRules::~ExpanderRules()
95{
96	void *item;
97	while ((item = fList.RemoveItem((int32)0)))
98		delete (ExpanderRule*)item;
99}
100
101
102status_t
103ExpanderRules::Open(BFile *file)
104{
105	directory_which which[] = {
106		B_USER_DATA_DIRECTORY,
107		B_COMMON_DATA_DIRECTORY
108	};
109
110	for (size_t i = 0; i < sizeof(which) / sizeof(which[0]); i++) {
111		BPath path;
112		if (find_directory(which[i], &path) != B_OK)
113			continue;
114
115		path.Append("expander.rules");
116		if (file->SetTo(path.Path(), B_READ_ONLY) == B_OK)
117			return B_OK;
118	}
119
120	return B_ENTRY_NOT_FOUND;
121}
122
123
124ExpanderRule *
125ExpanderRules::MatchingRule(BString &fileName, const char *filetype)
126{
127	int32 count = fList.CountItems();
128	int32 length = fileName.Length();
129	for (int32 i = 0; i < count; i++) {
130		ExpanderRule *rule = (ExpanderRule *)fList.ItemAt(i);
131		if (rule->MimeType().IsValid() && rule->MimeType() == filetype)
132			return rule;
133		int32 extPosition = fileName.FindLast(rule->FilenameExtension());
134		if (extPosition != -1
135			&& extPosition == (length - rule->FilenameExtension().Length()))
136			return rule;
137	}
138	return NULL;
139}
140
141
142ExpanderRule *
143ExpanderRules::MatchingRule(const entry_ref *ref)
144{
145	BEntry entry(ref, true);
146	BNode node(&entry);
147	BNodeInfo nodeInfo(&node);
148	char type[B_MIME_TYPE_LENGTH];
149	nodeInfo.GetType(type);
150	BString fileName(ref->name);
151	return MatchingRule(fileName, type);
152}
153
154
155RuleRefFilter::RuleRefFilter(ExpanderRules &rules)
156	: BRefFilter(),
157	fRules(rules)
158{
159}
160
161
162bool
163RuleRefFilter::Filter(const entry_ref *ref, BNode* node, struct stat_beos *st,
164	const char *filetype)
165{
166	if (node->IsDirectory() || node->IsSymLink())
167		return true;
168
169	BString fileName(ref->name);
170	return fRules.MatchingRule(fileName, filetype) != NULL;
171}
172