4 // Copyright (C) 2004 Novell, Inc.
7 // Fredrik Hedberg (fredrik.hedberg@avafan.com)
11 // Permission is hereby granted, free of charge, to any person obtaining a copy
12 // of this software and associated documentation files (the "Software"), to deal
13 // in the Software without restriction, including without limitation the rights
14 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 // copies of the Software, and to permit persons to whom the Software is
16 // furnished to do so, subject to the following conditions:
18 // The above copyright notice and this permission notice shall be included in all
19 // copies or substantial portions of the Software.
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33 using System
.Collections
;
34 using System
.Globalization
;
36 namespace Beagle
.Util
.Mozilla
39 /// Class representing a Mozilla profile, used to get a user's profiles and accounts
43 // FIXME: Move Beagle.Daemon.PathFinder to Beagle.Platform namespace dammit
45 static string datadir
= Environment
.GetEnvironmentVariable("HOME"); // Unix
47 static string datadir
= Environment
.GetEnvironmentVariable("APPDATA"); // Win32
50 // FIXME: Add more default locations
51 static string[] dirs
=
55 "Mozilla" + System
.IO
.Path
.DirectorySeparatorChar
+ "Firefox",
56 ".mozilla" + System
.IO
.Path
.DirectorySeparatorChar
+ "firefox"
59 Hashtable accounts
= new Hashtable ();
61 public ICollection Accounts
{
62 get { return accounts.Values; }
76 /// Creates and parses a profile from a prefs.js file
78 public Profile (string name
, string path
)
83 Preferences prefs
= new Preferences ( System
.IO
.Path
.Combine (path
, "prefs.js"));
85 string accountlist
= prefs
["mail.accountmanager.accounts"];
87 if (accountlist
!= null) {
89 string[] accounts
= accountlist
.Split (',');
91 foreach (string accountname
in accounts
) {
93 Account account
= new Account ();
94 string servername
= prefs
[String
.Format ("mail.account.{0}.server", accountname
)];
96 account
.Path
= prefs
[String
.Format ("mail.server.{0}.directory", servername
)];
97 account
.Name
= prefs
[String
.Format ("mail.server.{0}.name", servername
)];
98 account
.Type
= prefs
[String
.Format ("mail.server.{0}.type", servername
)];
100 this.accounts
.Add (accountname
, account
);
106 /// Fetch a users profiles from default locations
108 public static ICollection
ReadProfiles ()
110 ArrayList profiles
= new ArrayList ();
112 foreach (string subdir
in dirs
)
114 string dir
= System
.IO
.Path
.Combine (datadir
, subdir
);
116 if (!Directory
.Exists (dir
))
119 profiles
.AddRange (ReadProfiles (dir
));
126 /// Fetch a users profiles from a specific profiles.ini file
128 public static ICollection
ReadProfiles (string path
)
130 ArrayList profiles
= new ArrayList ();
132 StreamReader reader
= new StreamReader (new FileStream (System
.IO
.Path
.Combine (path
, "profiles.ini"), FileMode
.Open
, FileAccess
.Read
, FileShare
.Read
));
139 while ((data
= reader
.ReadLine ()) != null) {
141 if (data
.StartsWith ("[") && lname
!= null && lpath
!= null)
142 profiles
.Add (new Profile (lname
, System
.IO
.Path
.Combine(path
, lpath
)));
144 if (data
.IndexOf ("=") == -1)
147 string[] fields
= data
.Split ('=');
149 switch (fields
[0].ToLower ())
161 if (lname
!= null && lpath
!= null)
162 profiles
.Add (new Profile (lname
, System
.IO
.Path
.Combine (path
, lpath
)));
169 /// Class representing a Mozilla account
179 /// Class for parsing Mozilla preferences files - prefs.js
181 public class Preferences
183 Hashtable properties
= new Hashtable ();
185 public Preferences (string path
)
187 StreamReader reader
= new StreamReader (new FileStream (path
, FileMode
.Open
, FileAccess
.Read
, FileShare
.Read
));
191 while ((data
= reader
.ReadLine ()) != null) {
193 if (!data
.StartsWith ("user_pref"))
196 // FIXME: Use regexps
198 int index
= data
.IndexOf ('"',11);
200 string key
= data
.Substring (11, index
-11);
201 string value = data
.Substring (index
, data
.IndexOf (')')-index
).Substring (3).Trim ('"');
203 properties
[key
] = value;
209 public IDictionary Properties
{
210 get { return properties; }
213 public ICollection Keys
{
214 get { return properties.Keys; }
217 virtual public string this [string key
] {
218 get { return (string) properties [key]; }
220 if (value == null || value == "") {
221 if (properties
.Contains (key
))
222 properties
.Remove (key
);
225 properties
[key
] = value as string;
232 /// Message (mail, rss whatever) in Mozilla
238 public string Subject
;
244 StringBuilder body
= new StringBuilder ();
247 get { return body.ToString (); }
250 public void AppendBody (string str
)
255 public Hashtable Headers
= new Hashtable ();
263 public override string ToString ()
265 if (Name
!= null && Name
!= "")
266 return String
.Format ("{0} <{1}>", Name
, Email
);
271 public static ICollection
Parse (string str
)
278 /// FIXME: This is a hack and does not comply with any RFC, nor does it support attachments, encodings and other fancy shit
279 /// FIXME: Use a lib like gmime to parse messages, must be available on Linux, Win32 & MacOSX.
281 public class MessageReader
288 public MessageReader (string path
) : this (path
, -1)
290 Console
.WriteLine ("Doing: " + path
);
293 public MessageReader (string path
, int offset
)
300 stream
= new FileStream (path
,
306 stream
.Seek (offset
, SeekOrigin
.Begin
);
308 reader
= new StreamReader (stream
);
310 } catch (Exception e
) {
311 Console
.WriteLine ("Could not open '{0}' (offset={1})", path
, offset
);
312 Console
.WriteLine (e
);
320 public bool HasMoreMessages
322 get { return hasMore; }
325 public Message NextMessage
335 message
= new Message ();
342 while ((data
= reader
.ReadLine ()) != null) {
344 // Break for new message
346 if (data
.StartsWith ("From - ")) {
350 // Add body to message
353 message
.AppendBody (data
);
357 // Break for message content
359 if (data
.Length
== 0) {
366 int index
= data
.IndexOf (":");
368 if (index
!= -1 && !data
.StartsWith (" ")) {
370 if (data
.Length
< index
+2)
372 string key
= data
.Substring (0, index
);
373 string value = data
.Substring (index
+ 2);
375 message
.Headers
[key
] = value;
377 switch (key
.ToLower ()) {
379 message
.Subject
= value;
382 message
.From
= value;
388 message
.Date
= value;
391 char[] shit
= {'<', '>'}
;
392 message
.Id
= value.Trim (shit
);
399 } catch (Exception e
) {
400 Console
.WriteLine (e
);
409 public static void Main (string[] args
)
411 foreach (Profile profile
in Profile
.ReadProfiles ()) {
412 Console
.WriteLine("Profile: {0} - {1}", profile
.Name
, profile
.Path
);
413 foreach (Account account
in profile
.Accounts
) {
414 Console
.WriteLine ("\t{0} ({1}) - {2}", account
.Name
, account
.Type
, account
.Path
);