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