Developer Area

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

Revision 577, 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
172            string privateTelname = Publishers.Instance.GetPrivateTelname(telname);
173            this.PerformLookup(privateTelname, telname);
174        }
175
176        // internal lookup call
177        /// <summary>
178        /// Performs a lookup on the given telname under the guise of the lookup being on the public telname
179        /// </summary>
180        /// <param name="telname">The telname to perform the lookup on</param>
181        /// <param name="publicTelname">The telname to display to the user</param>
182        private void PerformLookup(string telname , string publicTelname)
183        {
184            Logger.Log(Logger.Section.Lookups, "Looking up " + telname);
185            try
186            {
187                if (TelnameChecker.IsEnum(telname))
188                {
189                    Logger.Log(Logger.Section.Lookups, telname + " identified as an Enum");
190                    // TODO: we will need to use the system DNS, not the one in preferences!
191                }
192                LookupTelname lt = new LookupTelname(IPAddress.Parse(Preferences.GetPreference("dns")), 
193                                                                        int.Parse(Preferences.GetPreference("dnsport")));
194                lt.Listener = this;
195                lt.performLookup(telname, publicTelname);
196            }
197            catch (Exception ex)
198            {
199                Logger.Log(Logger.Section.Lookups, "Exception caught during lookup: " + ex);
200                throw new Exception(String.Format(DotTelSystem.Properties.Resources.Lookup_ErrorDuringLookup, ex.Message));
201            }
202        }
203
204        /// <summary>
205        /// Decrypt any encrypted NAPTRs and cache the result
206        /// </summary>
207        /// <param name="lr"></param>
208        private void DecryptAndCache(LookupResult lr)
209        {
210            if (lr == null || lr.NaptrRecords == null) return;
211
212            // set to true if we do any decryption
213            bool modified = false;
214
215            ArrayList modifiedNaptrs = new ArrayList();
216            foreach (DNSTelnameNaptrResourceRecord record in lr.NaptrRecords)
217            {
218                DNSTelnameNaptrResourceRecord r = record;
219
220                if (r.ServiceType != null && r.ServiceType.StartsWith(X_Crypto_ServiceType))
221                {
222                    modified = true;
223
224                    try
225                    {
226                        string decrypted = Friending.Instance.Crypto.DecryptNaptr(r.Uri);
227                        byte[] data = new System.Text.UTF8Encoding().GetBytes(decrypted);
228
229                        DNSInputStream dnsInputStream = new DNSInputStream(data, 0, data.Length);
230                        string flags;
231                        string service;
232                        string regexpstr;
233                        string replacestr;
234                        dnsInputStream.ReadNaptrBody(out flags, out service, out regexpstr, out replacestr);
235
236                        // create a telname naptr
237                        DNSNaptrResourceRecord tempNaptr = new DNSNaptrResourceRecord(r.TTL, r.Order, r.Preference, flags, service, regexpstr, replacestr, true);
238                        string applicationUniqueString = r.Query;
239                        if (TelnameChecker.IsEnum(r.Query))
240                        {
241                            applicationUniqueString = UriHandler.getInstance().EnumToNumber(r.Query);
242                        }
243                        DNSTelnameNaptrResourceRecord[] records = DNSTelnameNaptrResourceRecord.parseTelnameNaptr(tempNaptr, r.Query, applicationUniqueString);
244                        /* not sure what purpose this code serves
245                        if (records.Length > 1)
246                        {
247                            int length = records.Length;
248                        }*/
249                        r = records[0];
250
251                        // we've successfully modified a NAPTR - we will need to update NaptrRecords
252
253                    }
254                    catch (Exception e)
255                    {
256                        // problem with decryption - exclude result
257                        Logger.Log(Logger.Section.Lookups, "Could not decrypt NAPTR: " + r.ToString());
258                        Logger.Log(Logger.Section.Lookups, "Reason was: " + e.Message);
259                        continue;
260                    }
261                }
262                modifiedNaptrs.Add(r);
263            }
264
265            // if we've made any changes to the NAPTRs then update the cache
266            if (modified)
267            {
268                lr.NaptrRecords = modifiedNaptrs;
269                LookupCache.SetResult(lr.Telname, lr);
270            }
271        }
272
273        /// <summary>
274        /// If Naptr is not laucnhable, makes it an unlinked Naptr
275        /// </summary>
276        /// <param name="lr"></param>
277        private void ExtractUnlinkedNaptr(LookupResult lr)
278        {
279            if (lr == null || lr.NaptrRecords == null) return;
280
281            // set to true if we do any decryption
282            bool modified = false;
283
284            ArrayList modifiedNaptrs = new ArrayList();
285            foreach (DNSTelnameNaptrResourceRecord record in lr.NaptrRecords)
286            {
287                DNSTelnameNaptrResourceRecord r = record;
288                if (r.ServiceType != null && 
289                    //(r.ServiceType.StartsWith(X_User_ServiceType) || r.ServiceType.StartsWith(X_Note_ServiceType) || r.ServiceType.StartsWith(Unknown_ServiceType)))
290                    !UriHandler.getInstance().Launchable(r.ServiceType))
291                {
292                    modified = true;
293                    DNSUnlinkedTelnameNaptrResourceRecord unlinkedNaptr = new DNSUnlinkedTelnameNaptrResourceRecord(r);
294                    modifiedNaptrs.Add(unlinkedNaptr);
295                }
296                else
297                {
298                    modifiedNaptrs.Add(r);
299                }
300            }
301
302            // if we've made any changes to the NAPTRs then update the cache
303            if (modified)
304            {
305                lr.NaptrRecords = modifiedNaptrs;
306                LookupCache.SetResult(lr.Telname, lr);
307            }
308        }
309
310    }
311}
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