(Back)port some changes from beagle-lucene-1-9-lockfile-branch: allow ext: queries...
[beagle.git] / Filters / FilterExternal.cs
blob4d2eefd699090b722f27b7535656849fcab2150c
1 //
2 // FilterExternal.cs
3 //
4 // Copyright (C) 2006 Novell, Inc.
5 //
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining a
9 // copy of this software and associated documentation files (the "Software"),
10 // to deal in the Software without restriction, including without limitation
11 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 // and/or sell copies of the Software, and to permit persons to whom the
13 // Software is furnished to do so, subject to the following conditions:
15 // The above copyright notice and this permission notice shall be included in
16 // all copies or substantial portions of the Software.
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 // DEALINGS IN THE SOFTWARE.
27 // The purpose of this filter is to allow users to easily extract text
28 // content from structured files using an external program. See
29 // external-filters.txt for more information.
31 using System;
32 using System.Collections;
33 using System.IO;
34 using System.Diagnostics;
35 using System.Xml;
36 using System.Xml.Serialization;
38 using Beagle.Daemon;
39 using Beagle.Util;
41 namespace Beagle.Filters {
43 public class ExternalFilterInfo {
45 [XmlElement ("mimetype")]
46 public string [] MimeTypes;
48 [XmlElement ("extension")]
49 public string [] Extensions;
51 [XmlElement ("command")]
52 public string Command;
54 [XmlElement ("arguments")]
55 public string Arguments;
58 [XmlRoot ("external-filters")]
59 public class ExternalFilterInfoContainer {
60 [XmlElement ("filter")]
61 public ExternalFilterInfo [] Items;
64 public class FilterExternal : Beagle.Daemon.Filter {
66 private ExternalFilterInfo [] filters = null;
68 public FilterExternal ()
70 string path = Path.Combine (Path.Combine (ExternalStringsHack.SysConfDir, "beagle"), "external-filters.xml");
72 try {
73 FileStream fs = File.Open (path, FileMode.Open, FileAccess.Read, FileShare.Read);
74 XmlSerializer serializer = new XmlSerializer (typeof (ExternalFilterInfoContainer));
75 ExternalFilterInfoContainer container = (ExternalFilterInfoContainer) serializer.Deserialize (fs);
76 fs.Close ();
77 this.filters = container.Items;
78 } catch (FileNotFoundException) {
79 // Probably not an error if the file isn't there.
81 } catch (DirectoryNotFoundException) {
82 // The directory isn't there either, not an error.
84 } catch (InvalidOperationException ex) {
85 // Something wrong with the XML
86 Logger.Log.Error (ex, "Unable to parse {0}", path);
88 } catch (XmlException ex) {
89 // Something else wrong with the XML
90 Logger.Log.Error (ex, "Unable to parse {0}", path);
93 if (this.filters == null)
94 return;
96 foreach (ExternalFilterInfo efi in this.filters) {
97 if (efi.MimeTypes != null) {
98 foreach (string s in efi.MimeTypes) {
99 FilterFlavor flavor = FilterFlavor.NewFromMimeType (s);
100 // External filters have higher priority than default ones
101 // This allows users to override default filters by something they want
102 flavor.Priority = 1;
103 AddSupportedFlavor (flavor);
107 if (efi.Extensions != null) {
108 foreach (string s in efi.Extensions) {
109 FilterFlavor flavor = FilterFlavor.NewFromExtension (s);
110 flavor.Priority = 1;
111 AddSupportedFlavor (flavor);
117 private ExternalFilterInfo GetFilterInfo (string extension, string mime_type)
119 if (this.filters == null || this.filters.Length == 0)
120 return null;
122 if (extension != null) {
123 foreach (ExternalFilterInfo efi in this.filters) {
124 if (efi.Extensions == null)
125 continue;
127 if (ArrayFu.IndexOfString (efi.Extensions, extension) != -1)
128 return efi;
132 if (mime_type != null) {
133 foreach (ExternalFilterInfo efi in this.filters) {
134 if (efi.MimeTypes == null)
135 continue;
137 if (ArrayFu.IndexOfString (efi.MimeTypes, mime_type) != -1)
138 return efi;
142 return null;
145 protected override void DoPull ()
147 ExternalFilterInfo efi = GetFilterInfo (this.Extension, this.MimeType);
149 if (efi == null) {
150 Logger.Log.Warn ("Unable to find a match for extension {0}, mime type {1} when one should have matched", this.Extension, this.MimeType);
151 Error ();
154 // FIXME: Need to deal with quotation marks in the XML file, probably.
155 string[] tmp_argv = efi.Arguments.Split (' ');
156 string[] argv = new string [tmp_argv.Length + 1];
158 argv [0] = efi.Command;
160 int j = 1;
161 for (int i = 0; i < tmp_argv.Length; i++) {
162 if (tmp_argv [i] == String.Empty)
163 continue;
165 if (tmp_argv [i] == "%s")
166 argv [j] = FileInfo.FullName;
167 else
168 argv [j] = tmp_argv [i];
169 j++;
172 SafeProcess pc = new SafeProcess ();
173 pc.Arguments = argv;
174 pc.RedirectStandardOutput = true;
176 try {
177 pc.Start ();
178 } catch (SafeProcessException e) {
179 Log.Warn (e.Message);
180 Error ();
181 return;
184 StreamReader pout = new StreamReader (pc.StandardOutput);
186 string str;
187 while ((str = pout.ReadLine ()) != null) {
188 AppendText (str);
189 AppendStructuralBreak ();
192 pout.Close ();
193 pc.Close ();
194 Finished ();