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