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