Back to index

lightning-sunbird  0.9+nobinonly
nsWSAUtils.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is the web scripts access security code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 2003
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s): Harish Dhurvasula <harishd@netscape.com>
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 
00039 #include "nsWSAUtils.h"
00040 #include "nsReadableUtils.h"
00041 #include "nsIStringBundle.h"
00042 #include "nsIConsoleService.h"
00043 #include "nsIServiceManager.h"
00044 #include "nsIDNSService.h"
00045 #include "nsIDNSRecord.h"
00046 #include "nsICancelable.h"
00047 #include "nsIRequest.h"
00048 #include "nsEventQueueUtils.h"
00049 #include "nsAutoPtr.h"
00050 #include "nsNetCID.h"
00051 
00052 static const char kSecurityProperties[] =
00053   "chrome://global/locale/webservices/security.properties";
00054 static NS_DEFINE_CID(kDNSServiceCID, NS_DNSSERVICE_CID);
00055 static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
00056 
00057 class nsDNSListener : public nsIDNSListener
00058 {
00059 public:
00060   nsDNSListener();
00061   virtual ~nsDNSListener();
00062   
00063   NS_DECL_ISUPPORTS
00064   NS_DECL_NSIDNSLISTENER
00065 
00066   nsCString mOfficialHostName;
00067   PRBool mLookupFinished;
00068 };
00069 
00070 #ifdef DEBUG
00071 
00072 struct TestStruct {
00073   const char* lhs; // string that contains the wild char(s).
00074   const char* rhs; // string that is compared against lhs.
00075   PRBool equal;    // set to true if lhs and rhs are expected 
00076                    // to be equal else set false;
00077 };
00078 
00079 static 
00080 const TestStruct kStrings[] = {
00081   { "f*o*bar", "foobar", PR_TRUE },
00082   { "foo*bar", "foofbar", PR_TRUE },
00083   { "*foo*bar", "ffoofoobbarbarbar", PR_TRUE },
00084   { "*foo*bar*barbar", "ffoofoobbarbarbar", PR_TRUE },
00085   { "http://*.*.*/*", "http://www.mozilla.org/", PR_TRUE},
00086   { "http://*/*", "http://www.mozilla.org/", PR_TRUE},
00087   { "http://*.mozilla.org/*/*", "http://www.mozilla.org/Projects/", PR_TRUE},
00088   { "http://www.m*zi*la.org/*", "http://www.mozilla.org/", PR_TRUE },
00089   { "http://www.mozilla.org/*.html", "http://www.mozilla.org/owners.html", PR_TRUE },
00090   { "http://www.mozilla.org/*.htm*", "http://www.mozilla.org/owners.html", PR_TRUE },
00091   { "http://www.mozilla.org/*rs.htm*", "http://www.mozilla.org/ownres.html", PR_FALSE },
00092   { "http://www.mozilla.org/a*c.html", "http://www.mozilla.org/abcd.html", PR_FALSE },
00093   { "https://www.mozilla.org/*", "http://www.mozilla.org/abcd.html", PR_FALSE },
00094 };
00095 
00096 void 
00097 nsWSAUtils::VerifyIsEqual()
00098 {
00099   static PRUint32 size = NS_ARRAY_LENGTH(kStrings);
00100   PRUint32 i;
00101   for (i = 0; i < size; ++i) {
00102     if (IsEqual(NS_ConvertUTF8toUCS2(kStrings[i].lhs), 
00103                 NS_ConvertUTF8toUCS2(kStrings[i].rhs)) 
00104                 != kStrings[i].equal) {
00105       const char* equal = 
00106         kStrings[i].equal ? "equivalent" : 
00107                             "not equivalent";
00108       printf("\nTest Failed: %s is %s to %s.\n", 
00109              kStrings[i].lhs, equal, kStrings[i].rhs);
00110     }
00111   }
00112 }
00113 
00114 #endif
00115 
00128 PRBool 
00129 nsWSAUtils::IsEqual(const nsAString& aLhs, const nsAString& aRhs) 
00130 {
00131   nsAString::const_iterator lhs_begin, lhs_end;
00132   nsAString::const_iterator rhs_begin, rhs_end;
00133  
00134   aLhs.BeginReading(lhs_begin);
00135   aLhs.EndReading(lhs_end);
00136   aRhs.BeginReading(rhs_begin);
00137   aRhs.EndReading(rhs_end);
00138 
00139   PRBool pattern_before_asterisk = PR_TRUE; 
00140   nsAString::const_iterator curr_posn = lhs_begin;
00141   while (curr_posn != lhs_end) {
00142     if (*lhs_begin == '*') {
00143       pattern_before_asterisk = PR_FALSE;
00144       ++lhs_begin; // Do this to not include '*' when pattern matching.
00145     }
00146     else if (pattern_before_asterisk) {
00147       // Match character by character to see if lhs and rhs are identical
00148       if (*curr_posn != *rhs_begin) {
00149         return PR_FALSE;
00150       }
00151       ++lhs_begin;
00152       ++curr_posn;
00153       ++rhs_begin;
00154       if (rhs_begin == rhs_end &&
00155           curr_posn == lhs_end) {
00156         return PR_TRUE; // lhs and rhs matched perfectly
00157       }
00158     }
00159     else if (++curr_posn == lhs_end) {
00160       if (curr_posn != lhs_begin) {
00161         // Here we're matching the last few characters to make sure
00162         // that lhs is actually equal to rhs. Ex. "a*c" != "abcd"
00163         // and "*xabcd" != "abcd".
00164         PRBool done = PR_FALSE;
00165         for (;;) {
00166           if (--curr_posn == lhs_begin)
00167             done = PR_TRUE;
00168           if (rhs_end == rhs_begin)
00169             return PR_FALSE;
00170           if (*(--rhs_end) != *curr_posn)
00171             return PR_FALSE;
00172           if (done)
00173             return PR_TRUE;
00174         }
00175       }
00176       // No discrepency between lhs and rhs
00177       return PR_TRUE;
00178     }
00179     else if (*curr_posn == '*') {
00180       // Matching pattern between asterisks. That is, in "h*ll*" we
00181       // check to see if "ll" exists in the rhs string.
00182       const nsAString& pattern = Substring(lhs_begin, curr_posn);
00183 
00184       nsAString::const_iterator tmp_end = rhs_end;
00185       if (!FindInReadable(pattern, rhs_begin, rhs_end)) {
00186          return PR_FALSE;
00187       }
00188       rhs_begin = rhs_end;
00189       rhs_end   = tmp_end;
00190       lhs_begin = curr_posn;
00191     }
00192   }
00193 
00194   return PR_FALSE;
00195 }
00196 
00197 nsresult
00198 nsWSAUtils::ReportError(const PRUnichar* aMessageID, 
00199                         const PRUnichar** aInputs, 
00200                         const PRInt32 aLength)
00201 {
00202   nsCOMPtr<nsIStringBundleService> bundleService
00203     = do_GetService(NS_STRINGBUNDLE_CONTRACTID);
00204   NS_ENSURE_TRUE(bundleService, NS_OK); // intentionally returning NS_OK;
00205 
00206   nsCOMPtr<nsIStringBundle> bundle;
00207   bundleService->CreateBundle(kSecurityProperties, getter_AddRefs(bundle));
00208   NS_ENSURE_TRUE(bundle, NS_OK);
00209 
00210   nsXPIDLString message;
00211   bundle->FormatStringFromName(aMessageID, aInputs, aLength,
00212                                getter_Copies(message));
00213 
00214   nsCOMPtr<nsIConsoleService> consoleService = 
00215     do_GetService(NS_CONSOLESERVICE_CONTRACTID);
00216   NS_ENSURE_TRUE(consoleService, NS_OK); // intentionally returning NS_OK;
00217   
00218   return consoleService->LogStringMessage(message.get());
00219 }
00220 
00221 nsresult
00222 nsWSAUtils::GetOfficialHostName(nsIURI* aServiceURI,
00223                                 nsACString& aResult)
00224 {
00225   NS_ASSERTION(aServiceURI, "Cannot get FQDN for a null URI!");
00226  
00227   if (!aServiceURI)
00228     return NS_ERROR_NULL_POINTER;
00229 
00230   nsresult rv;
00231   nsCOMPtr<nsIDNSService> dns(do_GetService(kDNSServiceCID, &rv));
00232   
00233   if (NS_FAILED(rv)) 
00234     return rv;
00235   
00236   nsCAutoString host;
00237   aServiceURI->GetHost(host);
00238 
00239   nsRefPtr<nsDNSListener> listener = new nsDNSListener();
00240   NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY);
00241     
00242   nsCOMPtr<nsIEventQueueService> eventQService = 
00243     do_GetService(kEventQueueServiceCID, &rv);
00244   
00245   if (NS_FAILED(rv))
00246     return rv;
00247 
00248   nsCOMPtr<nsIEventQueue> eventQ;
00249   rv = eventQService->PushThreadEventQueue(getter_AddRefs(eventQ));
00250   
00251   if (NS_FAILED(rv))
00252     return rv;
00253 
00254   nsCOMPtr<nsICancelable> dummy;
00255   rv = dns->AsyncResolve(host, nsIDNSService::RESOLVE_CANONICAL_NAME,
00256                          listener, eventQ, getter_AddRefs(dummy));
00257   
00258   PLEvent *ev;
00259   while (NS_SUCCEEDED(rv) && !listener->mLookupFinished) {
00260     rv = eventQ->WaitForEvent(&ev);
00261     NS_ASSERTION(NS_SUCCEEDED(rv), "WaitForEvent failed");
00262     if (NS_SUCCEEDED(rv)) {
00263       rv = eventQ->HandleEvent(ev);
00264       NS_ASSERTION(NS_SUCCEEDED(rv), "HandleEvent failed");
00265     }
00266   }
00267 
00268   aResult.Assign(listener->mOfficialHostName);
00269 
00270   eventQService->PopThreadEventQueue(eventQ);
00271    
00272   return rv;
00273 }
00274 
00275 NS_IMPL_THREADSAFE_ISUPPORTS1(nsDNSListener,
00276                               nsIDNSListener)
00277 
00278 nsDNSListener::nsDNSListener()
00279   : mLookupFinished(PR_FALSE)
00280 {
00281 }
00282 
00283 nsDNSListener::~nsDNSListener()
00284 {
00285 }
00286 
00287 NS_IMETHODIMP
00288 nsDNSListener::OnLookupComplete(nsICancelable* aRequest, 
00289                                 nsIDNSRecord* aRecord,
00290                                 nsresult aStatus)
00291 {
00292   if (aRecord)
00293     aRecord->GetCanonicalName(mOfficialHostName);
00294 
00295   mLookupFinished = PR_TRUE;
00296   return NS_OK;
00297 }
00298