xref: /haiku/src/apps/expander/ExpanderRules.cpp (revision a1163de83ea633463a79de234b8742ee106531b2)
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 
19 ExpanderRule::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 
30 ExpanderRule::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 
41 ExpanderRules::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 %s"));
49 	fList.AddItem(new ExpanderRule("application/x-bzip2",			".bz2", 	"echo %s | sed 's/.bz2$//g'", 	"bunzip2 %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 
94 ExpanderRules::~ExpanderRules()
95 {
96 	void *item;
97 	while ((item = fList.RemoveItem((int32)0)))
98 		delete (ExpanderRule*)item;
99 }
100 
101 
102 status_t
103 ExpanderRules::Open(BFile *file)
104 {
105 	BPath path;
106 	if (find_directory(B_USER_CONFIG_DIRECTORY, &path) != B_OK)
107 		return B_ERROR;
108 
109 	path.Append("etc/expander.rules");
110 	if (file->SetTo(path.Path(), B_READ_ONLY) == B_OK)
111 		return B_OK;
112 
113 	if (find_directory(B_COMMON_ETC_DIRECTORY, &path) != B_OK)
114 		return B_ERROR;
115 
116 	path.Append("expander.rules");
117 
118 	return file->SetTo(path.Path(), B_READ_ONLY);
119 }
120 
121 
122 ExpanderRule *
123 ExpanderRules::MatchingRule(BString &fileName, const char *filetype)
124 {
125 	int32 count = fList.CountItems();
126 	int32 length = fileName.Length();
127 	for (int32 i = 0; i < count; i++) {
128 		ExpanderRule *rule = (ExpanderRule *)fList.ItemAt(i);
129 		if (rule->MimeType().IsValid() && rule->MimeType() == filetype)
130 			return rule;
131 		int32 extPosition = fileName.FindLast(rule->FilenameExtension());
132 		if (extPosition != -1
133 			&& extPosition == (length - rule->FilenameExtension().Length()))
134 			return rule;
135 	}
136 	return NULL;
137 }
138 
139 
140 ExpanderRule *
141 ExpanderRules::MatchingRule(const entry_ref *ref)
142 {
143 	BEntry entry(ref, true);
144 	BNode node(&entry);
145 	BNodeInfo nodeInfo(&node);
146 	char type[B_MIME_TYPE_LENGTH];
147 	nodeInfo.GetType(type);
148 	BString fileName(ref->name);
149 	return MatchingRule(fileName, type);
150 }
151 
152 
153 RuleRefFilter::RuleRefFilter(ExpanderRules &rules)
154 	: BRefFilter(),
155 	fRules(rules)
156 {
157 }
158 
159 
160 bool
161 RuleRefFilter::Filter(const entry_ref *ref, BNode* node, struct stat_beos *st,
162 	const char *filetype)
163 {
164 	if (node->IsDirectory() || node->IsSymLink())
165 		return true;
166 
167 	BString fileName(ref->name);
168 	return fRules.MatchingRule(fileName, filetype) != NULL;
169 }
170