Developer Area

root/apps/outlook/branches/1.5/DotTelSystem/Lookup/Lookup.cs @ 588

Revision 588, 12.8 kB (checked in by jonmaycock, 10 months ago)
Line 
1///<summary>
2/// Author: Ben Dowling & Nick Brunwin
3///------------------------
4///Copyright (c) 2008, Telnic Ltd.
5///
6///All rights reserved.
7///
8///Redistribution and use in source and binary forms, with or
9///without modification, are permitted provided that the following
10///conditions are met:
11///
12///*    Redistributions of source code must retain the above
13///     copyright notice, this list of conditions and the
14///     following disclaimer.
15///*    Redistributions in binary form must reproduce the above
16///     copyright notice, this list of conditions and the following
17///     disclaimer in the documentation and/or other materials
18///     provided with the distribution.
19///*    Neither the name of the Telnic Ltd. nor the names of its
20///     contributors may be used to endorse or promote products
21///     derived from this software without specific prior written
22///     permission.
23///
24///THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
25///CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
26///INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
27///MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28///DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
29///CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30///SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31///LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
32///USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
33///AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34///LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
35///IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
36///THE POSSIBILITY OF SUCH DAMAGE.
37///--------------------------
38///</summary>
39using System;
40using System.Collections.Generic;
41using System.Text;
42using System.Net;
43using org.telnic.outlook.lookup;
44using org.telnic.outlook.dns;
45using org.telnic.outlook.util;
46using System.Collections;
47using System.Threading;
48using org.telnic.outlook.prefs;
49using org.telnic.outlook.friending;
50using org.telnic.outlook.dns.records;
51using org.telnic.outlook.friending.messaging;
52using org.telnic.outlook.prefs.publishers;
53using org.telnic.outlook.uri;
54
55namespace org.telnic.outlook.lookup
56{
57    public class Lookup : LookupTelnameCompleteListener
58    {
59        private static IMissingPublishersDialog missingPublishersDialog;
60        public static IMissingPublishersDialog MissingPublishersDialog
61        {
62            set
63            {
64                missingPublishersDialog = value;
65            }
66        }
67
68        private static string X_Crypto_ServiceType = "x-crypto";
69
70        private static string X_Note_ServiceType = "x-note";
71
72        private static string X_User_ServiceType = "x-user";
73
74        private static string Unknown_ServiceType = "unknown";
75
76        private LookupTelnameCompleteListener completeListener;
77
78        /// <summary>
79        /// Remove the given publisher from the publishers list
80        /// </summary>
81        /// <param name="telname">The publisher to remove</param>
82        private void RemovePublisher(string telname)
83        {
84            Thread t = new Thread(delegate() {
85                Messaging.Instance.RemoveFriend(telname);
86            });
87            t.Start();
88        }
89
90        /// <summary>
91        /// Decrypt encrypted NAPTRs and then call the passed completion listener
92        /// </summary>
93        /// <param name="lr">The result of the lookup</param>
94        public void LookupTelnameComplete(LookupResult lr)
95        {
96            if (completeListener == null)
97            {
98                Logger.Log(Logger.Section.Lookups, "Lookup completed, but listener is null");
99                return;
100            }
101            // if the domain doesn't exist make sure we didn't lookup something
102            // from the publishers list
103            if (lr != null && lr.NaptrStatus == LookupWorker.LookupStatus.Nxdomain)
104            {
105                // have we looked up a publishers subdomain?
106                string privateTelname = lr.Telname;
107
108                Logger.Log(Logger.Section.Lookups, "Telname is: " + privateTelname);
109
110                string publicTelname = lr.PublicTelname;
111                //string subDomain = telname.Substring(0, endOfSubdomain - 1);
112                Logger.Log(Logger.Section.Lookups, "Private telname is is: " + privateTelname + " Public telname is: " + publicTelname);
113                if (Publishers.Instance.GetPrivateTelname(publicTelname) != publicTelname
114                        && Publishers.Instance.GetPrivateTelname(publicTelname) == privateTelname)
115                {
116                    // we have looked up a sumdomain from the publishers list, and it doesn't exist!
117
118                    string pref = Preferences.GetPreference("publisher.missing");
119                    if (pref == "prompt")
120                    {
121                        if (missingPublishersDialog.Ask() == RemovePublisherChoice.Yes)
122                        {
123                            // remove the publisher
124                            RemovePublisher(publicTelname);
125                        }
126
127                    }
128                    else if (pref == "remove")
129                    {
130                        // remove the publisher
131                        RemovePublisher(publicTelname);
132                    }
133
134                    PerformLookup(publicTelname, publicTelname);
135                    return;
136                }
137            }
138
139            if (lr == null)
140            {
141                Logger.Log(Logger.Section.Lookups, "Lookup completed - null result returned");
142            }
143            else
144            {
145                Logger.Log(Logger.Section.Lookups, "Lookup completed for " + lr.Telname);
146            }
147
148            DecryptAndCache(lr);
149            ExtractUnlinkedNaptr(lr);
150
151            completeListener.LookupTelnameComplete(lr);
152        }
153
154        public Lookup() { }
155
156        /// <summary>
157        /// perform a lookup on telname - add a subdomain to telname if it is in
158        /// the publishers list, and decrypt results once they are back, then call lc
159        /// </summary>
160        /// <param name="telname">The telname to perform the lookup on</param>
161        /// <param name="lc">The listener to call on completion of the lookup</param>
162        public virtual void PerformLookup(string telname, LookupTelnameCompleteListener lc)
163        {
164            Logger.Log(Logger.Section.Lookups, "Lookup called with " + telname);
165            if (lc == null)
166            {
167                Logger.Log(Logger.Section.Lookups, "Perform lookup called without a listener.");
168                return;
169            }
170            completeListener = lc;
171            string privateTelname = Publishers.Instance.GetPrivateTelname(telname);
172            this.PerformLookup(privateTelname, telname);
173        }
174
175        // internal lookup call
176        /// <summary>
177        /// Performs a lookup on the given telname under the guise of the lookup being on the public telname
178        /// </summary>
179        /// <param name="telname">The telname to perform the lookup on</param>
180        /// <param name="publicTelname">The telname to display to the user</param>
181        private void PerformLookup(string telname , string publicTelname)
182        {
183            Logger.Log(Logger.Section.Lookups, "Looking up " + telname);
184            try
185            {
186                if (TelnameChecker.IsEnum(telname))
187                {
188                    Logger.Log(Logger.Section.Lookups, telname + " identified as an Enum");
189                    // TODO: we will need to use the system DNS, not the one in preferences!
190                }
191                LookupTelname lt = new LookupTelname(IPAddress.Parse(Preferences.GetPreference("dns")), 
192                                                                        int.Parse(Preferences.GetPreference("dnsport")));
193                lt.Listener = this;
194                lt.performLookup(telname, publicTelname);
195            }
196            catch (Exception ex)
197            {
198                Logger.Log(Logger.Section.Lookups, "Exception caught during lookup: " + ex);
199                throw new Exception(String.Format(DotTelSystem.Properties.Resources.Lookup_ErrorDuringLookup, ex.Message));
200            }
201        }
202
203        /// <summary>
204        /// Decrypt any encrypted NAPTRs and cache the result
205        /// </summary>
206        /// <param name="lr"></param>
207        private void DecryptAndCache(LookupResult lr)
208        {
209            if (lr == null || lr.NaptrRecords == null) return;
210
211            // set to true if we do any decryption
212            bool modified = false;
213
214            ArrayList modifiedNaptrs = new ArrayList();
215            foreach (DNSTelnameNaptrResourceRecord record in lr.NaptrRecords)
216            {
217                DNSTelnameNaptrResourceRecord r = record;
218
219                if (r.ServiceType != null && r.ServiceType.StartsWith(X_Crypto_ServiceType))
220                {
221                    modified = true;
222
223                    try
224                    {
225                        string decrypted = Friending.Instance.Crypto.DecryptNaptr(r.Uri);
226                        byte[] data = new System.Text.UTF8Encoding().GetBytes(decrypted);
227
228                        DNSInputStream dnsInputStream = new DNSInputStream(data, 0, data.Length);
229                        string flags;
230                        string service;
231                        string regexpstr;
232                        string replacestr;
233                        dnsInputStream.ReadNaptrBody(out flags, out service, out regexpstr, out replacestr);
234
235                        // create a telname naptr
236                        DNSNaptrResourceRecord tempNaptr = new DNSNaptrResourceRecord(r.TTL, r.Order, r.Preference, flags, service, regexpstr, replacestr, true);
237                        string applicationUniqueString = r.Query;
238                        if (TelnameChecker.IsEnum(r.Query))
239                        {
240                            applicationUniqueString = UriHandler.getInstance().EnumToNumber(r.Query);
241                        }
242                        DNSTelnameNaptrResourceRecord[] records = DNSTelnameNaptrResourceRecord.parseTelnameNaptr(tempNaptr, r.Query, applicationUniqueString);
243                        /* not sure what purpose this code serves
244                        if (records.Length > 1)
245                        {
246                            int length = records.Length;
247                        }*/
248                        r = records[0];
249
250                        // we've successfully modified a NAPTR - we will need to update NaptrRecords
251
252                    }
253                    catch (Exception e)
254                    {
255                        // problem with decryption - exclude result
256                        Logger.Log(Logger.Section.Lookups, "Could not decrypt NAPTR: " + r.ToString());
257                        Logger.Log(Logger.Section.Lookups, "Reason was: " + e.Message);
258                        continue;
259                    }
260                }
261                modifiedNaptrs.Add(r);
262            }
263
264            // if we've made any changes to the NAPTRs then update the cache
265            if (modified)
266            {
267                lr.NaptrRecords = modifiedNaptrs;
268                LookupCache.SetResult(lr.Telname, lr);
269            }
270        }
271
272        /// <summary>
273        /// If Naptr is not laucnhable, makes it an unlinked Naptr
274        /// </summary>
275        /// <param name="lr"></param>
276        private void ExtractUnlinkedNaptr(LookupResult lr)
277        {
278            if (lr == null || lr.NaptrRecords == null) return;
279
280            // set to true if we do any decryption
281            bool modified = false;
282
283            ArrayList modifiedNaptrs = new ArrayList();
284            foreach (DNSTelnameNaptrResourceRecord record in lr.NaptrRecords)
285            {
286                DNSTelnameNaptrResourceRecord r = record;
287                if (r.ServiceType != null && 
288                    //(r.ServiceType.StartsWith(X_User_ServiceType) || r.ServiceType.StartsWith(X_Note_ServiceType) || r.ServiceType.StartsWith(Unknown_ServiceType)))
289                    !UriHandler.getInstance().Launchable(r.ServiceType))
290                {
291                    modified = true;
292                    DNSUnlinkedTelnameNaptrResourceRecord unlinkedNaptr = new DNSUnlinkedTelnameNaptrResourceRecord(r);
293                    modifiedNaptrs.Add(unlinkedNaptr);
294                }
295                else
296                {
297                    modifiedNaptrs.Add(r);
298                }
299            }
300
301            // if we've made any changes to the NAPTRs then update the cache
302            if (modified)
303            {
304                lr.NaptrRecords = modifiedNaptrs;
305                LookupCache.SetResult(lr.Telname, lr);
306            }
307        }
308
309    }
310}
Note: See TracBrowser for help on using the browser.
Telnic
Search This Site
Partners
Neustar
ICANN
Main site | WHOIS | Sell .tel | FAQ | Archived Site | About Telnic | Contact Us