sbURIChecker.cpp
Go to the documentation of this file.
1 /*
2 //
3 // BEGIN SONGBIRD GPL
4 //
5 // This file is part of the Songbird web player.
6 //
7 // Copyright(c) 2005-2008 POTI, Inc.
8 // http://songbirdnest.com
9 //
10 // This file may be licensed under the terms of of the
11 // GNU General Public License Version 2 (the "GPL").
12 //
13 // Software distributed under the License is distributed
14 // on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
15 // express or implied. See the GPL for the specific language
16 // governing rights and limitations.
17 //
18 // You should have received a copy of the GPL along with this
19 // program. If not, go to http://www.gnu.org/licenses/gpl.html
20 // or write to the Free Software Foundation, Inc.,
21 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 //
23 // END SONGBIRD GPL
24 //
25  */
26 
27 #include "sbURIChecker.h"
28 
29 #include <prio.h>
30 #include <prnetdb.h>
31 #include <nsCOMPtr.h>
32 #include <nsIURL.h>
33 #include <nsNetUtil.h>
34 
35 /*
36  * To log this module, set the following environment variable:
37  * NSPR_LOG_MODULES=sbURIChecker:5
38  */
39 #ifdef PR_LOGGING
40 static PRLogModuleInfo* gURICheckerLog = nsnull;
41 #endif
42 
43 #undef LOG
44 #define LOG(args) PR_LOG(gURICheckerLog, PR_LOG_WARN, args)
45 
46 /* static */
47 nsresult
48 sbURIChecker::CheckURI(nsACString& aDomain,
49  nsACString& aPath,
50  nsIURI* aURI)
51 {
52 #ifdef PR_LOGGING
53  if (!gURICheckerLog) {
54  gURICheckerLog = PR_NewLogModule("sbURIChecker");
55  }
56  LOG(("sbURIChecker::CheckURI(domain:%s path:%s)",
57  aDomain.BeginReading(), aPath.BeginReading()));
58 #endif
59  NS_ENSURE_ARG_POINTER(aURI);
60 
61  nsCString domain(aDomain);
62  nsresult rv = CheckDomain( domain, aURI );
63  if ( NS_FAILED(rv) ) {
64  LOG(("sbURIChecker::CheckURI() -- FAILED domain Check"));
65  return rv;
66  }
67 
68  nsCString path(aPath);
69  rv = CheckPath( path, aURI );
70  if ( NS_FAILED(rv) ) {
71  LOG(("sbURIChecker::CheckURI() -- FAILED path Check"));
72  return rv;
73  }
74 
75  // everything passed, assign into the inputs
76  if ( aDomain.IsEmpty() ) {
77  aDomain.Assign(domain);
78  }
79  if ( aPath.IsEmpty() ) {
80  aPath.Assign(path);
81  }
82  return NS_OK;
83 }
84 
85 /* static */
86 nsresult
87 sbURIChecker::CheckDomain( nsACString &aDomain, nsIURI *aSiteURI )
88 {
89  NS_ENSURE_ARG_POINTER(aSiteURI);
90  LOG(( "sbURIChecker::CheckDomain(%s)", aDomain.BeginReading() ));
91 
92  // get host from URI
93  nsCString host;
94  nsresult rv = aSiteURI->GetHost(host);
95  NS_ENSURE_SUCCESS( rv, rv );
96 
97  nsCString fixedHost;
98  rv = sbURIChecker::FixupDomain( host, fixedHost );
99  NS_ENSURE_SUCCESS( rv, rv );
100 
101  host.Assign(fixedHost);
102 
103  if ( !aDomain.IsEmpty() ) {
104  LOG(("sbURIChecker::CheckDomain() -- Have a domain from the user"));
105  // remove trailing dots, lowercase it
106  nsCString fixedDomain;
107  rv = sbURIChecker::FixupDomain( aDomain, fixedDomain );
108  NS_ENSURE_SUCCESS( rv, rv );
109 
110  aDomain.Assign(fixedDomain);
111 
112  // Deal first with numerical ip addresses
113  PRNetAddr addr;
114  if ( PR_StringToNetAddr( host.get(), &addr ) == PR_SUCCESS ) {
115  // numerical ip address
116  LOG(("sbURIChecker::CheckDomain() -- Numerical Address "));
117  if ( !aDomain.Equals(host) ) {
118  LOG(("sbURIChecker::CheckDomain() -- FAILED ip address check"));
119  return NS_ERROR_FAILURE;
120  }
121  } else {
122  // domain based host, check it against host from URI
123  LOG(("sbURIChecker::CheckDomain() -- Domain based host "));
124 
125  // make sure the domain wasn't '.com' - it should have a dot in it
126  // we need to skip this check if the host is localhost
127  PRInt32 dot = aDomain.FindChar('.');
128  if ( dot < 0 && !host.Equals("localhost")) {
129  LOG(("sbURIChecker::CheckDomain() -- FAILED dot test "));
130  return NS_ERROR_FAILURE;
131  }
132 
133  // prepend a dot so bar.com doesn't match foobar.com but does foo.bar.com
134  aDomain.Insert( NS_LITERAL_CSTRING("."), 0 );
135 
136  PRInt32 domainLength = aDomain.Length();
137  PRInt32 lengthDiff = host.Length() - domainLength;
138  if ( lengthDiff == -1 ) {
139  LOG(("sbURIChecker::CheckDomain() -- long domain check"));
140  // special case: from user: .bar.com vs. from URI: bar.com
141  // XXXredfive - I actually think we'll see this most often because
142  // of the prepending of the dot to the user supplied domain
143  if ( !StringEndsWith(aDomain, host) ) {
144  LOG(("sbURIChecker::CheckDomain() -- FAILED long domain check"));
145  return NS_ERROR_FAILURE;
146  }
147  } else if ( lengthDiff == 0 ) {
148  LOG(("sbURIChecker::CheckDomain() -- same length check"));
149  // same length better be the same strings
150  if ( !aDomain.Equals(host) ) {
151  LOG(("sbURIChecker::CheckDomain() -- FAILED same length check"));
152  return NS_ERROR_FAILURE;
153  }
154  } else if ( lengthDiff > 0 ) {
155  LOG(("sbURIChecker::CheckDomain() -- parent domain check"));
156  // normal case URI host is longer that host from user
157  // from user: .bar.com from URI: foo.bar.com
158  if ( !StringEndsWith(host, aDomain) ) {
159  LOG(("sbURIChecker::CheckDomain() -- FAILED parent domain check"));
160  return NS_ERROR_FAILURE;
161  }
162  } else {
163  // domains are WAY off, the user domain is more than 1 char longer than
164  // the URI domain. ie: user: jgaunt.com URI: ""
165  LOG(("sbURIChecker::CheckDomain() -- FAILED, user domain is superset"));
166  return NS_ERROR_FAILURE;
167  }
168 
169  // remove the leading dot we added
170  aDomain.Cut( 0, 1 );
171  }
172  } else {
173  LOG(( "sbURIChecker::CheckDomain() -- NO domain from the user"));
174  // If the user didn't specify a host
175  // if the URI host is empty, make sure we're file://
176  if ( host.IsEmpty() ) {
177  PRBool isFileURI;
178  rv = aSiteURI->SchemeIs( "file", &isFileURI );
179  NS_ENSURE_SUCCESS( rv, rv );
180 
181  if (!isFileURI) {
182  // non-file URI without a host!!!
183  LOG(("sbURIChecker::CheckDomain() -- FAILED file scheme check"));
184  return NS_ERROR_FAILURE;
185  }
186 
187  // clear the isVoid flag if set
188  aDomain.Truncate();
189  } else {
190  // no domain from the user but there is a domain from the URI
191  aDomain.Assign(host);
192  }
193  }
194 
195  LOG(("sbURIChecker::CheckDomain() -- PASSED match test"));
196  return NS_OK;
197 }
198 
199 /* static */
200 nsresult
201 sbURIChecker::CheckPath( nsACString &aPath, nsIURI *aSiteURI )
202 {
203  // aPath may be empty
204  NS_ENSURE_ARG_POINTER(aSiteURI);
205  LOG(( "sbURIChecker::CheckPath(%s)", aPath.BeginReading() ));
206 
207  nsresult rv;
208 
209  nsCString fixedSitePath;
210  rv = sbURIChecker::FixupPath( aSiteURI, fixedSitePath );
211  NS_ENSURE_SUCCESS( rv, rv );
212 
213  if ( aPath.IsEmpty() ) {
214  // If the path was empty we use aSiteURI that was retrieved from the system.
215  aPath.Assign(fixedSitePath);
216 
217  // The rest of this function will ensure that the path is actually a subpath
218  // of aURI. If nothing was passed in aPath then we already know that this
219  // is true because we constructed aPath from aURI. Therefore we're done and
220  // can go ahead and return.
221  return NS_OK;
222  }
223 
224  // Compare fixedPath to fixedSitePath to make sure that fixedPath is within
225  // fixedSitePath.
226  nsCString fixedPath;
227  rv = sbURIChecker::FixupPath( aPath, fixedPath );
228  NS_ENSURE_SUCCESS( rv, rv );
229 
230  // Verify that this path is indeed part of the site URI.
231  if ( !StringBeginsWith( fixedSitePath, fixedPath ) ) {
232  LOG(("sbURIChecker::CheckPath() -- FAILED Path Prefix Check"));
233  return NS_ERROR_FAILURE;
234  }
235 
236  LOG(("sbURIChecker::CheckPath() -- PASSED Path Prefix Check"));
237 
238  aPath.Assign(fixedPath);
239  return NS_OK;
240 }
241 
242 /* static */
243 nsresult
244 sbURIChecker::FixupDomain( const nsACString& aDomain,
245  nsACString& _retval )
246 {
247  // aDomain may be empty
248  if ( aDomain.IsEmpty() ) {
249  _retval.Truncate();
250  return NS_OK;
251  }
252 
253  nsCString domain(aDomain);
254 
255  domain.Trim("./");
256  ToLowerCase(domain);
257 
258  _retval.Assign(domain);
259  return NS_OK;
260 }
261 
262 /* static */
263 nsresult
265  nsACString& _retval )
266 {
267  NS_ASSERTION( aURI, "Don't you dare pass me a null pointer!" );
268 
269  nsresult rv;
270  nsCOMPtr<nsIURL> url( do_QueryInterface( aURI, &rv ) );
271  NS_ENSURE_SUCCESS( rv, rv );
272 
273  // According to nsIURL the directory will always have a trailing slash (???).
274  // However, if the spec from aURI did *not* have a trailing slash then the
275  // fileName attribute of url may be set. If it is then we assume it is
276  // actually a directory as long as the fileExtension is empty. Thus the
277  // following transformations will result:
278  //
279  // Original spec from aURI ---------> path
280  //
281  // http://www.foo.com/bar/baz/ -----> /bar/baz/
282  // http://www.foo.com/bar/baz ------> /bar/baz/
283  // http://www.foo.com/bar/baz.ext --> /bar/
284 
285  nsCString path;
286  rv = url->GetDirectory(path);
287  NS_ENSURE_SUCCESS( rv, rv );
288 
289  nsCString fileName;
290  rv = url->GetFileName(fileName);
291  NS_ENSURE_SUCCESS( rv, rv );
292 
293  if ( !fileName.IsEmpty() ) {
294  nsCString fileExt;
295  rv = url->GetFileExtension(fileExt);
296  NS_ENSURE_SUCCESS( rv, rv );
297 
298  if ( fileExt.IsEmpty() ) {
299  // If there is no file extension then assume it is actually a directory
300  // and append a trailing slash.
301  path.Append(fileName);
302  path.AppendLiteral("/");
303  }
304  }
305 
306  _retval.Assign(path);
307  return NS_OK;
308 }
309 
310 /* static */
311 nsresult
312 sbURIChecker::FixupPath( const nsACString& aPath,
313  nsACString& _retval )
314 {
315  // aPath may be empty
316  if ( aPath.IsEmpty() ) {
317  _retval.Truncate();
318  return NS_OK;
319  }
320 
321  NS_NAMED_LITERAL_CSTRING( slashString, "/" );
322 
323  // Construct a dummy URL that incorporates the path that the user passed in.
324  nsCString dummyURL("http://dummy.com");
325 
326  // Make sure that aPath begins with a slash. Otherwise we could end up with
327  // something like "foo.combar" rather than "foo.com/bar".
328  if ( !StringBeginsWith( aPath, slashString ) ) {
329  dummyURL.Append(slashString);
330  }
331 
332  dummyURL.Append(aPath);
333 
334  nsCOMPtr<nsIURI> uri;
335  nsresult rv = NS_NewURI( getter_AddRefs(uri), dummyURL );
336  NS_ENSURE_SUCCESS( rv, rv );
337 
338  // Hand off.
339  return sbURIChecker::FixupPath( uri, _retval );
340 }
return NS_OK
_updateCookies aPath
static nsresult CheckDomain(nsACString &aDomain, nsIURI *aSiteURI)
static nsresult CheckURI(nsACString &aDomain, nsACString &aPath, nsIURI *aURI)
static nsresult FixupDomain(const nsACString &aDomain, nsACString &_retval)
#define LOG(args)
static nsresult CheckPath(nsACString &aPath, nsIURI *aSiteURI)
static nsresult FixupPath(nsIURI *aURI, nsACString &_retval)
var uri
Definition: FeedWriter.js:1135
function url(spec)