xref: /haiku/src/apps/expander/ExpanderRules.cpp (revision 820dca4df6c7bf955c46e8f6521b9408f50b2900)
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 -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 
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 	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 
124 ExpanderRule *
125 ExpanderRules::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 
142 ExpanderRule *
143 ExpanderRules::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 
155 RuleRefFilter::RuleRefFilter(ExpanderRules &rules)
156 	: BRefFilter(),
157 	fRules(rules)
158 {
159 }
160 
161 
162 bool
163 RuleRefFilter::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