NS_CStringSetDataRange(nsACString& aStr,
                       uint32_t aCutOffset, uint32_t aCutLength,
                       const char* aData, uint32_t aDataLength)
{
  if (aCutOffset == UINT32_MAX) {
    // append case
    if (aData) {
      aStr.Append(aData, aDataLength);
    }
    return NS_OK; // XXX report errors
  }

  if (aCutLength == UINT32_MAX) {
    aCutLength = aStr.Length() - aCutOffset;
  }

  if (aData) {
    if (aDataLength == UINT32_MAX) {
      aStr.Replace(aCutOffset, aCutLength, nsDependentCString(aData));
    } else {
      aStr.Replace(aCutOffset, aCutLength, Substring(aData, aDataLength));
    }
  } else {
    aStr.Cut(aCutOffset, aCutLength);
  }

  return NS_OK; // XXX report errors
}
NS_CStringSetDataRange(nsACString &aStr,
                       PRUint32 aCutOffset, PRUint32 aCutLength,
                       const char *aData, PRUint32 aDataLength)
{
  if (aCutOffset == PR_UINT32_MAX)
  {
    // append case
    if (aData)
      aStr.Append(aData, aDataLength);
    return NS_OK; // XXX report errors
  }

  if (aCutLength == PR_UINT32_MAX)
    aCutLength = aStr.Length() - aCutOffset;

  if (aData)
  {
    if (aDataLength == PR_UINT32_MAX)
      aStr.Replace(aCutOffset, aCutLength, nsDependentCString(aData));
    else
      aStr.Replace(aCutOffset, aCutLength, Substring(aData, aDataLength));
  }
  else
    aStr.Cut(aCutOffset, aCutLength);

  return NS_OK; // XXX report errors
}
/* static */
nsresult
sbURIChecker::CheckDomain( nsACString &aDomain, nsIURI *aSiteURI )
{
  NS_ENSURE_ARG_POINTER(aSiteURI);
  LOG(( "sbURIChecker::CheckDomain(%s)", aDomain.BeginReading() ));

  // get host from URI
  nsCString host;
  nsresult rv = aSiteURI->GetHost(host);
  NS_ENSURE_SUCCESS( rv, rv );

  nsCString fixedHost;
  rv = sbURIChecker::FixupDomain( host, fixedHost );
  NS_ENSURE_SUCCESS( rv, rv );

  host.Assign(fixedHost);

  if ( !aDomain.IsEmpty() ) {
    LOG(("sbURIChecker::CheckDomain() -- Have a domain from the user"));
    // remove trailing dots, lowercase it
    nsCString fixedDomain;
    rv = sbURIChecker::FixupDomain( aDomain, fixedDomain );
    NS_ENSURE_SUCCESS( rv, rv );

    aDomain.Assign(fixedDomain);

    // Deal first with numerical ip addresses
    PRNetAddr addr;
    if ( PR_StringToNetAddr( host.get(), &addr ) == PR_SUCCESS ) {
      // numerical ip address
      LOG(("sbURIChecker::CheckDomain() -- Numerical Address "));
      if ( !aDomain.Equals(host) ) {
        LOG(("sbURIChecker::CheckDomain() -- FAILED ip address check"));
        return NS_ERROR_FAILURE;
      }
    } else {
      // domain based host, check it against host from URI
      LOG(("sbURIChecker::CheckDomain() -- Domain based host "));

      // make sure the domain wasn't '.com' - it should have a dot in it
      // we need to skip this check if the host is localhost
      PRInt32 dot = aDomain.FindChar('.');
      if ( dot < 0 && !host.Equals("localhost")) {
        LOG(("sbURIChecker::CheckDomain() -- FAILED dot test "));
        return NS_ERROR_FAILURE;
      }

      // prepend a dot so bar.com doesn't match foobar.com but does foo.bar.com
      aDomain.Insert( NS_LITERAL_CSTRING("."), 0 );

      PRInt32 domainLength = aDomain.Length();
      PRInt32 lengthDiff = host.Length() - domainLength;
      if ( lengthDiff == -1 ) {
        LOG(("sbURIChecker::CheckDomain() -- long domain check"));
        // special case:  from user: .bar.com   vs. from URI:  bar.com
        // XXXredfive - I actually think we'll see this most often because
        //             of the prepending of the dot to the user supplied domain
        if ( !StringEndsWith(aDomain, host) ) {
          LOG(("sbURIChecker::CheckDomain() -- FAILED long domain check"));
          return NS_ERROR_FAILURE;
        }
      } else if ( lengthDiff == 0 ) {
        LOG(("sbURIChecker::CheckDomain() -- same length check"));
        // same length better be the same strings
        if ( !aDomain.Equals(host) ) {
          LOG(("sbURIChecker::CheckDomain() -- FAILED same length check"));
          return NS_ERROR_FAILURE;
        }
      } else if ( lengthDiff > 0 ) {
        LOG(("sbURIChecker::CheckDomain() -- parent domain check"));
        // normal case URI host is longer that host from user
        //   from user: .bar.com   from URI:  foo.bar.com
        if ( !StringEndsWith(host, aDomain) ) {
          LOG(("sbURIChecker::CheckDomain() -- FAILED parent domain check"));
          return NS_ERROR_FAILURE;
        }
      } else {
        // domains are WAY off, the user domain is more than 1 char longer than
        // the URI domain. ie: user: jgaunt.com URI: ""
        LOG(("sbURIChecker::CheckDomain() -- FAILED, user domain is superset"));
        return NS_ERROR_FAILURE;
      }

      // remove the leading dot we added
      aDomain.Cut( 0, 1 );
    }
  } else {
    LOG(( "sbURIChecker::CheckDomain() -- NO domain from the user"));
    // If the user didn't specify a host
    // if the URI host is empty, make sure we're file://
    if ( host.IsEmpty() ) {
      PRBool isFileURI;
      rv = aSiteURI->SchemeIs( "file", &isFileURI );
      NS_ENSURE_SUCCESS( rv, rv );

      if (!isFileURI) {
        // non-file URI without a host!!!
        LOG(("sbURIChecker::CheckDomain() -- FAILED file scheme check"));
        return NS_ERROR_FAILURE;
      }
      
      // clear the isVoid flag if set
      aDomain.Truncate();
    } else {
      // no domain from the user but there is a domain from the URI
      aDomain.Assign(host);
    }
  }

  LOG(("sbURIChecker::CheckDomain() -- PASSED match test"));
  return NS_OK;
}