xref: /haiku/src/apps/expander/ExpanderRules.cpp (revision b028e77473189065f2baefc6f5e10d451cf591e2)
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 
17 ExpanderRule::ExpanderRule(BString mimetype, BString filenameExtension,
18 	BString listingCmd, BString expandCmd)
19 	:
20 	fMimeType(mimetype.String()),
21 	fFilenameExtension(filenameExtension),
22 	fListingCmd(listingCmd),
23 	fExpandCmd(expandCmd)
24 {
25 }
26 
27 
28 ExpanderRule::ExpanderRule(const char* mimetype, const char* filenameExtension,
29 	const char* listingCmd, const char* expandCmd)
30 	:
31 	fMimeType(mimetype),
32 	fFilenameExtension(filenameExtension),
33 	fListingCmd(listingCmd),
34 	fExpandCmd(expandCmd)
35 {
36 }
37 
38 
39 ExpanderRules::ExpanderRules()
40 {
41 	fList.AddItem(new ExpanderRule("", 								".tar.gz", 	"zcat %s | tar -tvf -", 		"zcat %s | tar -xf -"));
42 	fList.AddItem(new ExpanderRule("", 								".tar.bz2", "bzcat %s | tar -tvf -", 		"bzcat %s | tar -xf -"));
43 	fList.AddItem(new ExpanderRule("", 								".tar.Z", 	"zcat %s | tar -tvf -", 		"zcat %s | tar -xf -"));
44 	fList.AddItem(new ExpanderRule("", 								".tgz", 	"zcat %s | tar -tvf -", 		"zcat %s | tar -xf -"));
45 	fList.AddItem(new ExpanderRule("application/x-tar", 			".tar", 	"tar -tvf %s", 					"tar -xf %s"));
46 	fList.AddItem(new ExpanderRule("application/x-gzip",			".gz", 		"echo %s | sed 's/.gz$//g'", 	"gunzip %s"));
47 	fList.AddItem(new ExpanderRule("application/x-bzip2",			".bz2", 	"echo %s | sed 's/.bz2$//g'", 	"bunzip2 %s"));
48 	fList.AddItem(new ExpanderRule("application/zip", 				".zip", 	"unzip -l %s", 					"unzip -o %s"));
49 	fList.AddItem(new ExpanderRule("application/x-zip-compressed", 	".zip", 	"unzip -l %s", 					"unzip -o %s"));
50 	fList.AddItem(new ExpanderRule("application/x-rar",				".rar", 	"unrar v %s", 					"unrar x -y %s"));
51 
52 	BFile file;
53 	if (Open(&file) != B_OK)
54 		return;
55 
56 	int fd = file.Dup();
57 	FILE * f = fdopen(fd, "r");
58 
59 	char buffer[1024];
60 	BString strings[4];
61 	while (fgets(buffer, 1024 - 1, f) != NULL) {
62 		int32 i = 0, j = 0;
63 		int32 firstQuote = -1;
64 		while (buffer[i] != '#' && buffer[i] != '\n' && j < 4) {
65 			if ((j == 0 || j > 1) && buffer[i] == '"') {
66 				if (firstQuote >= 0) {
67 					strings[j++].SetTo(&buffer[firstQuote+1], i - firstQuote - 1);
68 					firstQuote = -1;
69 				} else
70 					firstQuote = i;
71 			} else if (j == 1 && (buffer[i] == ' ' || buffer[i] == '\t')) {
72 				if (firstQuote >= 0) {
73 					if (firstQuote + 1 != i) {
74 						strings[j++].SetTo(&buffer[firstQuote+1], i - firstQuote - 1);
75 						firstQuote = -1;
76 					} else
77 						firstQuote = i;
78 				} else
79 					firstQuote = i;
80 			}
81 			i++;
82 		}
83 		if (j == 4) {
84 			fList.AddItem(new ExpanderRule(strings[0], strings[1], strings[2], strings[3]));
85 		}
86 	}
87 	fclose(f);
88 	close(fd);
89 }
90 
91 
92 ExpanderRules::~ExpanderRules()
93 {
94 	void *item;
95 	while ((item = fList.RemoveItem((int32)0)))
96 		delete (ExpanderRule*)item;
97 }
98 
99 
100 status_t
101 ExpanderRules::Open(BFile *file)
102 {
103 	BPath path;
104 	if (find_directory(B_USER_CONFIG_DIRECTORY, &path) != B_OK)
105 		return B_ERROR;
106 
107 	path.Append("etc/expander.rules");
108 	if (file->SetTo(path.Path(), B_READ_ONLY) == B_OK)
109 		return B_OK;
110 
111 	if (find_directory(B_COMMON_ETC_DIRECTORY, &path) != B_OK)
112 		return B_ERROR;
113 
114 	path.Append("expander.rules");
115 
116 	return file->SetTo(path.Path(), B_READ_ONLY);
117 }
118 
119 
120 ExpanderRule *
121 ExpanderRules::MatchingRule(BString &fileName, const char *filetype)
122 {
123 	int32 count = fList.CountItems();
124 	int32 length = fileName.Length();
125 	for (int32 i = 0; i < count; i++) {
126 		ExpanderRule *rule = (ExpanderRule *)fList.ItemAt(i);
127 		if ((rule->MimeType().IsValid() && rule->MimeType() == filetype)
128 			|| (fileName.FindLast(rule->FilenameExtension()) == (length - rule->FilenameExtension().Length())))
129 			return rule;
130 	}
131 	return NULL;
132 }
133 
134 
135 ExpanderRule *
136 ExpanderRules::MatchingRule(const entry_ref *ref)
137 {
138 	BEntry entry(ref, true);
139 	BNode node(&entry);
140 	BNodeInfo nodeInfo(&node);
141 	char type[B_MIME_TYPE_LENGTH];
142 	nodeInfo.GetType(type);
143 	BString fileName(ref->name);
144 	return MatchingRule(fileName, type);
145 }
146 
147 
148 RuleRefFilter::RuleRefFilter(ExpanderRules &rules)
149 	: BRefFilter(),
150 	fRules(rules)
151 {
152 }
153 
154 
155 bool
156 RuleRefFilter::Filter(const entry_ref *ref, BNode* node, struct stat *st,
157 	const char *filetype)
158 {
159 	if (node->IsDirectory() || node->IsSymLink())
160 		return true;
161 
162 	BString fileName(ref->name);
163 	return fRules.MatchingRule(fileName, filetype) != NULL;
164 }
165