4 // Copyright (C) 2004 Matthew Jones <mattharrison sbcglobal net>
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to deal
10 // in the Software without restriction, including without limitation the rights
11 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 // copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
15 // The above copyright notice and this permission notice shall be included in all
16 // 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 FROM,
23 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 using System
.Collections
;
32 namespace Beagle
.Util
{
34 public class ImBuddy
{
35 public string Protocol
= "";
36 public string OwnerAccountName
= "";
37 public string BuddyAccountName
= "";
38 public string Alias
= "";
39 public string BuddyIconLocation
= "";
40 public string BuddyIconChecksum
= "";
42 public ImBuddy (string protocol
, string owneraccount
, string buddyaccount
, string alias, string iconlocation
, string iconchecksum
) {
44 OwnerAccountName
= owneraccount
;
45 BuddyAccountName
= buddyaccount
;
47 BuddyIconLocation
= iconlocation
;
48 BuddyIconChecksum
= iconchecksum
;
52 ///////////////////////////////////////////////////////////////////////////////
54 public abstract class ImBuddyListReader
{
56 public bool verbose
= false;
58 public Hashtable buddyList
= new Hashtable ();
60 abstract public void Read ();
62 public void DebugPrint (string str
) {
65 Logger
.Log
.Debug ("{0}", str
);
68 public class ImBuddyComparer
: IComparer
{
70 int IComparer
.Compare (Object x
, Object y
) {
71 string accountx
, accounty
;
74 accountx
= ((ImBuddy
) x
).BuddyAccountName
;
80 accounty
= ((ImBuddy
) y
).BuddyAccountName
;
85 return System
.String
.Compare (accountx
, accounty
);
89 public class ImBuddyAliasComparer
: IComparer
{
91 int IComparer
.Compare (Object x
, Object y
) {
93 return System
.String
.Compare ((string)x
, ((ImBuddy
) y
).BuddyAccountName
);
95 return System
.String
.Compare (((ImBuddy
) x
).BuddyAccountName
, (string)y
);
101 public class GaimBuddyListReader
: ImBuddyListReader
{
103 string buddyListPath
;
105 DateTime buddyListLastWriteTime
;
108 public GaimBuddyListReader ()
110 string home
= Environment
.GetEnvironmentVariable ("HOME");
111 buddyListDir
= Path
.Combine (home
, ".gaim");
112 buddyListPath
= Path
.Combine (buddyListDir
, "blist.xml");
114 if (File
.Exists (buddyListPath
))
117 // Poll the file once every minute
118 timeoutId
= GLib
.Timeout
.Add (60000, new GLib
.TimeoutHandler (ReadTimeoutHandler
));
121 ~
GaimBuddyListReader ()
124 GLib
.Source
.Remove (timeoutId
);
127 private bool ReadTimeoutHandler ()
129 if (File
.Exists (buddyListPath
))
135 private string Format (string name
) {
136 return name
.ToLower ().Replace (" ", "");
139 override public void Read ()
141 // If the file hasn't changed, don't do anything.
142 DateTime last_write
= File
.GetLastWriteTime (buddyListPath
);
143 if (last_write
== buddyListLastWriteTime
)
146 buddyListLastWriteTime
= last_write
;
148 buddyList
= new Hashtable ();
151 XmlDocument accounts
= new XmlDocument ();
152 accounts
.Load (buddyListPath
);
154 XmlNodeList contacts
= accounts
.SelectNodes ("//contact");
156 foreach (XmlNode contact
in contacts
) {
157 string groupalias
= "";
159 foreach (XmlAttribute attr
in contact
.Attributes
) {
160 if (attr
.Name
== "alias") {
161 groupalias
= attr
.Value
;
165 if (groupalias
!= "") {
166 foreach (XmlNode buddy
in contact
.ChildNodes
) {
167 AddBuddy (buddy
, groupalias
);
172 foreach (XmlNode buddy
in accounts
.SelectNodes ("//contact[not(@name)]/buddy")) {
175 } catch (Exception ex
) {
176 Logger
.Log
.Error ("Caught exception while trying to parse Gaim contact list: {0}", ex
.Message
);
180 private void AddBuddy (XmlNode buddy
, string groupalias
)
182 string protocol
, owner
, other
, alias, iconlocation
, iconchecksum
;
191 foreach (XmlAttribute attr
in buddy
.Attributes
) {
195 DebugPrint ("owner: " + owner
);
198 protocol
= attr
.Value
;
199 DebugPrint ("protocol: " + protocol
);
204 foreach (XmlNode attr
in buddy
.ChildNodes
) {
205 switch (attr
.LocalName
) {
207 other
= attr
.InnerText
;
208 DebugPrint ("other: " + other
);
211 alias = attr
.InnerText
;
212 DebugPrint ("alias: " + alias);
215 foreach (XmlAttribute subattr
in attr
.Attributes
) {
216 if (subattr
.Name
== "name" && subattr
.Value
== "buddy_icon")
218 iconlocation
= attr
.InnerText
;
219 DebugPrint ("iconlocation: " + iconlocation
);
221 else if ( subattr
.Name
== "name" && subattr
.Value
== "icon_checksum")
223 iconchecksum
= attr
.InnerText
;
224 DebugPrint ("iconchecksum: " + iconchecksum
);
235 if (buddyList
.ContainsKey (Format(other
))) {
236 old
= (ImBuddy
)buddyList
[Format(other
)];
237 if (old
.Alias
== "" && alias != "")
239 if (old
.BuddyIconLocation
== "" && iconlocation
== "") {
240 old
.BuddyIconLocation
= iconlocation
;
241 old
.BuddyIconChecksum
= iconchecksum
;
243 buddyList
.Remove (Format(other
));
244 buddyList
.Add (Format(other
), old
);
247 buddyList
.Add (Format(other
), new ImBuddy (protocol
, owner
, Format(other
), alias, iconlocation
, iconchecksum
));
250 private void AddBuddy (XmlNode buddy
)
252 string protocol
, owner
, other
, alias, iconlocation
, iconchecksum
;
261 foreach (XmlAttribute attr
in buddy
.Attributes
) {
265 DebugPrint ("owner: " + owner
);
268 protocol
= attr
.Value
;
269 DebugPrint ("protocol: " + protocol
);
274 foreach (XmlNode attr
in buddy
.ChildNodes
) {
275 switch (attr
.LocalName
) {
277 other
= attr
.InnerText
;
278 DebugPrint ("other: " + other
);
281 alias = attr
.InnerText
;
282 DebugPrint ("alias: " + alias);
285 foreach (XmlAttribute subattr
in attr
.Attributes
) {
286 if (subattr
.Name
== "name" && subattr
.Value
== "buddy_icon")
288 iconlocation
= attr
.InnerText
;
289 DebugPrint ("iconlocation: " + iconlocation
);
291 else if ( subattr
.Name
== "name" && subattr
.Value
== "icon_checksum")
293 iconchecksum
= attr
.InnerText
;
294 DebugPrint ("iconchecksum: " + iconchecksum
);
303 if (buddyList
.ContainsKey (Format(other
))) {
304 old
= (ImBuddy
)buddyList
[Format(other
)];
305 if (old
.Alias
== "" && alias != "")
307 if (old
.BuddyIconLocation
== "" && iconlocation
== "") {
308 old
.BuddyIconLocation
= iconlocation
;
309 old
.BuddyIconChecksum
= iconchecksum
;
311 buddyList
.Remove (Format(other
));
312 buddyList
.Add (Format(other
), old
);
315 buddyList
.Add (Format(other
), new ImBuddy (protocol
, owner
, Format(other
), alias, iconlocation
, iconchecksum
));
319 public ImBuddy
Search (string buddy
) {
320 return (ImBuddy
)buddyList
[Format(buddy
)];
325 /////////////////////////////////////////////////////////////
327 public class KopeteBuddyListReader
: ImBuddyListReader
{
329 string buddyListPath
;
331 DateTime buddyListLastWriteTime
;
334 public KopeteBuddyListReader ()
336 buddyListDir
= Path
.Combine (PathFinder
.HomeDir
, ".kde/share/apps/kopete");
337 buddyListPath
= Path
.Combine (buddyListDir
, "contactlist.xml");
339 if (File
.Exists (buddyListPath
))
342 // Poll the file once every minute
343 timeoutId
= GLib
.Timeout
.Add (60000, new GLib
.TimeoutHandler (ReadTimeoutHandler
));
346 ~
KopeteBuddyListReader ()
349 GLib
.Source
.Remove (timeoutId
);
352 private bool ReadTimeoutHandler ()
354 if (File
.Exists (buddyListPath
))
360 private string Format (string name
) {
361 return name
.ToLower ().Replace (" ", "");
364 override public void Read ()
366 // If the file hasn't changed, don't do anything.
367 DateTime last_write
= File
.GetLastWriteTime (buddyListPath
);
368 if (last_write
== buddyListLastWriteTime
)
371 buddyListLastWriteTime
= last_write
;
373 buddyList
= new Hashtable ();
376 XmlDocument accounts
= new XmlDocument ();
377 accounts
.Load (buddyListPath
);
379 // Find all xml contact nodes in the contact list
380 foreach (XmlNode contact
in accounts
.SelectNodes ("//meta-contact"))
381 AddContact (contact
);
382 } catch (Exception ex
) {
383 Logger
.Log
.Error ("Caught exception while trying to parse Kopete contact list: {0}", ex
.Message
);
387 private void AddContact (XmlNode contact
)
389 string protocol
, owner
, other
, alias, iconlocation
, iconchecksum
;
398 // For each and every meta-contact, there can be multiple
399 // buddy information entries if we have a contact added on
400 // multiple protocols. Loop through them.
402 foreach (XmlNode plugin_node
in contact
.SelectNodes ("plugin-data")) {
403 // Determin the protocol
404 XmlAttribute plugin_id_attr
= plugin_node
.Attributes
["plugin-id"];
405 protocol
= plugin_id_attr
.Value
.Substring (0, plugin_id_attr
.Value
.Length
-8).ToLower ();
406 DebugPrint ("Protocol=" + protocol
);
408 // Fetch all the buddy properties
409 foreach (XmlNode plugin_data_node
in plugin_node
.SelectNodes ("plugin-data-field")) {
410 switch (plugin_data_node
.Attributes
["key"].Value
) {
412 other
= plugin_data_node
.InnerText
;
413 DebugPrint ("Screen=" + other
);
416 owner
= plugin_data_node
.InnerText
;
417 DebugPrint ("Account=" + owner
);
420 alias = plugin_data_node
.InnerText
;
421 DebugPrint ("Alias=" + alias);
426 // Replace any earlier buddies with the same screenname
427 // FIXME: Not safe since we can have the same screenname on different accounts.
428 if (buddyList
.ContainsKey (Format(other
)))
429 buddyList
.Remove (Format(other
));
431 buddyList
.Add (Format(other
), new ImBuddy (protocol
, owner
, Format(other
), alias, iconlocation
, iconchecksum
));
436 public ImBuddy
Search (string buddy
) {
437 return (ImBuddy
)buddyList
[Format(buddy
)];