Ejemplo n.º 1
0
nsresult
nsHyphenator::Hyphenate(const nsAString& aString,
                        nsTArray<PRPackedBool>& aHyphens)
{
  if (!aHyphens.SetLength(aString.Length())) {
    return NS_ERROR_OUT_OF_MEMORY;
  }
  memset(aHyphens.Elements(), PR_FALSE, aHyphens.Length());

  PRBool inWord = PR_FALSE;
  PRUint32 wordStart = 0, wordLimit = 0;
  for (PRUint32 i = 0; i < aString.Length(); i++) {
    PRUnichar ch = aString[i];

    nsIUGenCategory::nsUGenCategory cat = mCategories->Get(ch);
    if (cat == nsIUGenCategory::kLetter || cat == nsIUGenCategory::kMark) {
      if (!inWord) {
        inWord = PR_TRUE;
        wordStart = i;
      }
      wordLimit = i + 1;
      if (i < aString.Length() - 1) {
        continue;
      }
    }

    if (inWord) {
      NS_ConvertUTF16toUTF8 utf8(aString.BeginReading() + wordStart,
                                 wordLimit - wordStart);
      nsAutoTArray<char,200> utf8hyphens;
      utf8hyphens.SetLength(utf8.Length() + 5);
      char **rep = nsnull;
      int *pos = nsnull;
      int *cut = nsnull;
      int err = hnj_hyphen_hyphenate2((HyphenDict*)mDict,
                                      utf8.BeginReading(), utf8.Length(),
                                      utf8hyphens.Elements(), nsnull,
                                      &rep, &pos, &cut);
      if (!err) {
        PRUint32 utf16offset = wordStart;
        const char *cp = utf8.BeginReading();
        while (cp < utf8.EndReading()) {
          if (UTF8traits::isASCII(*cp)) { // single-byte utf8 char
            cp++;
            utf16offset++;
          } else if (UTF8traits::is2byte(*cp)) { // 2-byte sequence
            cp += 2;
            utf16offset++;
          } else if (UTF8traits::is3byte(*cp)) { // 3-byte sequence
            cp += 3;
            utf16offset++;
          } else { // must be a 4-byte sequence (no need to check validity,
                   // as this was just created with NS_ConvertUTF16toUTF8)
            NS_ASSERTION(UTF8traits::is4byte(*cp), "unexpected utf8 byte");
            cp += 4;
            utf16offset += 2;
          }
          NS_ASSERTION(cp <= utf8.EndReading(), "incomplete utf8 string?");
          NS_ASSERTION(utf16offset <= aString.Length(), "length mismatch?");
          if (utf8hyphens[cp - utf8.BeginReading() - 1] & 0x01) {
            aHyphens[utf16offset - 1] = PR_TRUE;
          }
        }
      }
    }
    
    inWord = PR_FALSE;
  }

  return NS_OK;
}
Ejemplo n.º 2
0
bool
nsDSURIContentListener::CheckOneFrameOptionsPolicy(nsIHttpChannel* aHttpChannel,
                                                   const nsAString& aPolicy)
{
  static const char allowFrom[] = "allow-from";
  const uint32_t allowFromLen = ArrayLength(allowFrom) - 1;
  bool isAllowFrom =
    StringHead(aPolicy, allowFromLen).LowerCaseEqualsLiteral(allowFrom);

  // return early if header does not have one of the values with meaning
  if (!aPolicy.LowerCaseEqualsLiteral("deny") &&
      !aPolicy.LowerCaseEqualsLiteral("sameorigin") &&
      !isAllowFrom) {
    return true;
  }

  nsCOMPtr<nsIURI> uri;
  aHttpChannel->GetURI(getter_AddRefs(uri));

  // XXXkhuey when does this happen?  Is returning true safe here?
  if (!mDocShell) {
    return true;
  }

  // We need to check the location of this window and the location of the top
  // window, if we're not the top.  X-F-O: SAMEORIGIN requires that the
  // document must be same-origin with top window.  X-F-O: DENY requires that
  // the document must never be framed.
  nsCOMPtr<nsPIDOMWindowOuter> thisWindow = mDocShell->GetWindow();
  // If we don't have DOMWindow there is no risk of clickjacking
  if (!thisWindow) {
    return true;
  }

  // GetScriptableTop, not GetTop, because we want this to respect
  // <iframe mozbrowser> boundaries.
  nsCOMPtr<nsPIDOMWindowOuter> topWindow = thisWindow->GetScriptableTop();

  // if the document is in the top window, it's not in a frame.
  if (thisWindow == topWindow) {
    return true;
  }

  // Find the top docshell in our parent chain that doesn't have the system
  // principal and use it for the principal comparison.  Finding the top
  // content-type docshell doesn't work because some chrome documents are
  // loaded in content docshells (see bug 593387).
  nsCOMPtr<nsIDocShellTreeItem> thisDocShellItem(
    do_QueryInterface(static_cast<nsIDocShell*>(mDocShell)));
  nsCOMPtr<nsIDocShellTreeItem> parentDocShellItem;
  nsCOMPtr<nsIDocShellTreeItem> curDocShellItem = thisDocShellItem;
  nsCOMPtr<nsIDocument> topDoc;
  nsresult rv;
  nsCOMPtr<nsIScriptSecurityManager> ssm =
    do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
  if (!ssm) {
    MOZ_CRASH();
  }

  // Traverse up the parent chain and stop when we see a docshell whose
  // parent has a system principal, or a docshell corresponding to
  // <iframe mozbrowser>.
  while (NS_SUCCEEDED(
           curDocShellItem->GetParent(getter_AddRefs(parentDocShellItem))) &&
         parentDocShellItem) {
    nsCOMPtr<nsIDocShell> curDocShell = do_QueryInterface(curDocShellItem);
    if (curDocShell && curDocShell->GetIsMozBrowserOrApp()) {
      break;
    }

    bool system = false;
    topDoc = parentDocShellItem->GetDocument();
    if (topDoc) {
      if (NS_SUCCEEDED(
            ssm->IsSystemPrincipal(topDoc->NodePrincipal(), &system)) &&
          system) {
        // Found a system-principled doc: last docshell was top.
        break;
      }
    } else {
      return false;
    }
    curDocShellItem = parentDocShellItem;
  }

  // If this document has the top non-SystemPrincipal docshell it is not being
  // framed or it is being framed by a chrome document, which we allow.
  if (curDocShellItem == thisDocShellItem) {
    return true;
  }

  // If the value of the header is DENY, and the previous condition is
  // not met (current docshell is not the top docshell), prohibit the
  // load.
  if (aPolicy.LowerCaseEqualsLiteral("deny")) {
    ReportXFOViolation(curDocShellItem, uri, eDENY);
    return false;
  }

  topDoc = curDocShellItem->GetDocument();
  nsCOMPtr<nsIURI> topUri;
  topDoc->NodePrincipal()->GetURI(getter_AddRefs(topUri));

  // If the X-Frame-Options value is SAMEORIGIN, then the top frame in the
  // parent chain must be from the same origin as this document.
  if (aPolicy.LowerCaseEqualsLiteral("sameorigin")) {
    rv = ssm->CheckSameOriginURI(uri, topUri, true);
    if (NS_FAILED(rv)) {
      ReportXFOViolation(curDocShellItem, uri, eSAMEORIGIN);
      return false; /* wasn't same-origin */
    }
  }

  // If the X-Frame-Options value is "allow-from [uri]", then the top
  // frame in the parent chain must be from that origin
  if (isAllowFrom) {
    if (aPolicy.Length() == allowFromLen ||
        (aPolicy[allowFromLen] != ' ' &&
         aPolicy[allowFromLen] != '\t')) {
      ReportXFOViolation(curDocShellItem, uri, eALLOWFROM);
      return false;
    }
    rv = NS_NewURI(getter_AddRefs(uri), Substring(aPolicy, allowFromLen));
    if (NS_FAILED(rv)) {
      return false;
    }

    rv = ssm->CheckSameOriginURI(uri, topUri, true);
    if (NS_FAILED(rv)) {
      ReportXFOViolation(curDocShellItem, uri, eALLOWFROM);
      return false;
    }
  }

  return true;
}
Ejemplo n.º 3
0
nsresult
nsKeygenFormProcessor::GetPublicKey(nsAString& aValue, nsAString& aChallenge, 
				    nsAFlatString& aKeyType,
				    nsAString& aOutPublicKey, nsAString& aKeyParams)
{
    nsNSSShutDownPreventionLock locker;
    nsresult rv = NS_ERROR_FAILURE;
    char *keystring = nullptr;
    char *keyparamsString = nullptr, *str = nullptr;
    uint32_t keyGenMechanism;
    int32_t primeBits;
    PK11SlotInfo *slot = nullptr;
    PK11RSAGenParams rsaParams;
    SECOidTag algTag;
    int keysize = 0;
    void *params;
    SECKEYPrivateKey *privateKey = nullptr;
    SECKEYPublicKey *publicKey = nullptr;
    CERTSubjectPublicKeyInfo *spkInfo = nullptr;
    PLArenaPool *arena = nullptr;
    SECStatus sec_rv = SECFailure;
    SECItem spkiItem;
    SECItem pkacItem;
    SECItem signedItem;
    CERTPublicKeyAndChallenge pkac;
    pkac.challenge.data = nullptr;
    nsIGeneratingKeypairInfoDialogs * dialogs;
    nsKeygenThread *KeygenRunnable = 0;
    nsCOMPtr<nsIKeygenThread> runnable;
    
    // permanent and sensitive flags for keygen
    PK11AttrFlags attrFlags = PK11_ATTR_TOKEN | PK11_ATTR_SENSITIVE | PK11_ATTR_PRIVATE;

    // Get the key size //
    for (size_t i = 0; i < number_of_key_size_choices; ++i) {
        if (aValue.Equals(mSECKeySizeChoiceList[i].name)) {
            keysize = mSECKeySizeChoiceList[i].size;
            break;
        }
    }
    if (!keysize) {
        goto loser;
    }

    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    if (!arena) {
        goto loser;
    }

    // Set the keygen mechanism
    if (aKeyType.IsEmpty() || aKeyType.LowerCaseEqualsLiteral("rsa")) {
        keyGenMechanism = CKM_RSA_PKCS_KEY_PAIR_GEN;
    } else if (aKeyType.LowerCaseEqualsLiteral("dsa")) {
        char * end;
        keyparamsString = ToNewCString(aKeyParams);
        if (!keyparamsString) {
            rv = NS_ERROR_OUT_OF_MEMORY;
            goto loser;
        }

        keyGenMechanism = CKM_DSA_KEY_PAIR_GEN;
        if (strcmp(keyparamsString, "null") == 0)
            goto loser;
        str = keyparamsString;
        bool found_match = false;
        do {
            end = strchr(str, ',');
            if (end != nullptr)
                *end = '\0';
            primeBits = pqg_prime_bits(str);
            if (keysize == primeBits) {
                found_match = true;
                break;
            }
            str = end + 1;
        } while (end != nullptr);
        if (!found_match) {
            goto loser;
        }
    } else if (aKeyType.LowerCaseEqualsLiteral("ec")) {
        keyparamsString = ToNewCString(aKeyParams);
        if (!keyparamsString) {
            rv = NS_ERROR_OUT_OF_MEMORY;
            goto loser;
        }

        keyGenMechanism = CKM_EC_KEY_PAIR_GEN;
        /* ecParams are initialized later */
    } else {
        goto loser;
    }

    // Get the slot
    rv = GetSlot(keyGenMechanism, &slot);
    if (NS_FAILED(rv)) {
        goto loser;
    }
    switch (keyGenMechanism) {
        case CKM_RSA_PKCS_KEY_PAIR_GEN:
            rsaParams.keySizeInBits = keysize;
            rsaParams.pe = DEFAULT_RSA_KEYGEN_PE;
            algTag = DEFAULT_RSA_KEYGEN_ALG;
            params = &rsaParams;
            break;
        case CKM_DSA_KEY_PAIR_GEN:
            // XXX Fix this! XXX //
            goto loser;
        case CKM_EC_KEY_PAIR_GEN:
            /* XXX We ought to rethink how the KEYGEN tag is 
             * displayed. The pulldown selections presented
             * to the user must depend on the keytype.
             * The displayed selection could be picked
             * from the keyparams attribute (this is currently called
             * the pqg attribute).
             * For now, we pick ecparams from the keyparams field
             * if it specifies a valid supported curve, or else 
             * we pick one of secp384r1, secp256r1 or secp192r1
             * respectively depending on the user's selection
             * (High, Medium, Low). 
             * (RSA uses RSA-2048, RSA-1024 and RSA-512 for historical
             * reasons, while ECC choices represent a stronger mapping)
             * NOTE: The user's selection
             * is silently ignored when a valid curve is presented
             * in keyparams.
             */
            if ((params = decode_ec_params(keyparamsString)) == nullptr) {
                /* The keyparams attribute did not specify a valid
                 * curve name so use a curve based on the keysize.
                 * NOTE: Here keysize is used only as an indication of
                 * High/Medium/Low strength; elliptic curve
                 * cryptography uses smaller keys than RSA to provide
                 * equivalent security.
                 */
                switch (keysize) {
                case 2048:
                    params = decode_ec_params("secp384r1");
                    break;
                case 1024:
                case 512:
                    params = decode_ec_params("secp256r1");
                    break;
                } 
            }
            /* XXX The signature algorithm ought to choose the hashing
             * algorithm based on key size once ECDSA variations based
             * on SHA256 SHA384 and SHA512 are standardized.
             */
            algTag = SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST;
            break;
      default:
          goto loser;
      }

    /* Make sure token is initialized. */
    rv = setPassword(slot, m_ctx);
    if (NS_FAILED(rv))
        goto loser;

    sec_rv = PK11_Authenticate(slot, true, m_ctx);
    if (sec_rv != SECSuccess) {
        goto loser;
    }

    rv = getNSSDialogs((void**)&dialogs,
                       NS_GET_IID(nsIGeneratingKeypairInfoDialogs),
                       NS_GENERATINGKEYPAIRINFODIALOGS_CONTRACTID);

    if (NS_SUCCEEDED(rv)) {
        KeygenRunnable = new nsKeygenThread();
        NS_IF_ADDREF(KeygenRunnable);
    }

    if (NS_FAILED(rv) || !KeygenRunnable) {
        rv = NS_OK;
        privateKey = PK11_GenerateKeyPairWithFlags(slot, keyGenMechanism, params,
                                                   &publicKey, attrFlags, m_ctx);
    } else {
        KeygenRunnable->SetParams( slot, attrFlags, nullptr, 0,
                                   keyGenMechanism, params, m_ctx );

        runnable = do_QueryInterface(KeygenRunnable);
        
        if (runnable) {
            {
              nsPSMUITracker tracker;
              if (tracker.isUIForbidden()) {
                rv = NS_ERROR_NOT_AVAILABLE;
              }
              else {
                rv = dialogs->DisplayGeneratingKeypairInfo(m_ctx, runnable);
                // We call join on the thread, 
                // so we can be sure that no simultaneous access to the passed parameters will happen.
                KeygenRunnable->Join();
              }
            }

            NS_RELEASE(dialogs);
            if (NS_SUCCEEDED(rv)) {
                PK11SlotInfo *used_slot = nullptr;
                rv = KeygenRunnable->ConsumeResult(&used_slot, &privateKey, &publicKey);
                if (NS_SUCCEEDED(rv) && used_slot) {
                  PK11_FreeSlot(used_slot);
                }
            }
        }
    }
    
    if (NS_FAILED(rv) || !privateKey) {
        goto loser;
    }
    // just in case we'll need to authenticate to the db -jp //
    privateKey->wincx = m_ctx;

    /*
     * Create a subject public key info from the public key.
     */
    spkInfo = SECKEY_CreateSubjectPublicKeyInfo(publicKey);
    if ( !spkInfo ) {
        goto loser;
    }
    
    /*
     * Now DER encode the whole subjectPublicKeyInfo.
     */
    sec_rv=DER_Encode(arena, &spkiItem, CERTSubjectPublicKeyInfoTemplate, spkInfo);
    if (sec_rv != SECSuccess) {
        goto loser;
    }

    /*
     * set up the PublicKeyAndChallenge data structure, then DER encode it
     */
    pkac.spki = spkiItem;
    pkac.challenge.len = aChallenge.Length();
    pkac.challenge.data = (unsigned char *)ToNewCString(aChallenge);
    if (!pkac.challenge.data) {
        rv = NS_ERROR_OUT_OF_MEMORY;
        goto loser;
    }
    
    sec_rv = DER_Encode(arena, &pkacItem, CERTPublicKeyAndChallengeTemplate, &pkac);
    if ( sec_rv != SECSuccess ) {
        goto loser;
    }

    /*
     * now sign the DER encoded PublicKeyAndChallenge
     */
    sec_rv = SEC_DerSignData(arena, &signedItem, pkacItem.data, pkacItem.len,
			 privateKey, algTag);
    if ( sec_rv != SECSuccess ) {
        goto loser;
    }
    
    /*
     * Convert the signed public key and challenge into base64/ascii.
     */
    keystring = BTOA_DataToAscii(signedItem.data, signedItem.len);
    if (!keystring) {
        rv = NS_ERROR_OUT_OF_MEMORY;
        goto loser;
    }

    CopyASCIItoUTF16(keystring, aOutPublicKey);
    nsCRT::free(keystring);

    rv = NS_OK;
loser:
    if ( sec_rv != SECSuccess ) {
        if ( privateKey ) {
            PK11_DestroyTokenObject(privateKey->pkcs11Slot,privateKey->pkcs11ID);
        }
        if ( publicKey ) {
            PK11_DestroyTokenObject(publicKey->pkcs11Slot,publicKey->pkcs11ID);
        }
    }
    if ( spkInfo ) {
        SECKEY_DestroySubjectPublicKeyInfo(spkInfo);
    }
    if ( publicKey ) {
        SECKEY_DestroyPublicKey(publicKey);
    }
    if ( privateKey ) {
        SECKEY_DestroyPrivateKey(privateKey);
    }
    if ( arena ) {
        PORT_FreeArena(arena, true);
    }
    if (slot != nullptr) {
        PK11_FreeSlot(slot);
    }
    if (KeygenRunnable) {
        NS_RELEASE(KeygenRunnable);
    }
    if (keyparamsString) {
        nsMemory::Free(keyparamsString);
    }
    if (pkac.challenge.data) {
        nsMemory::Free(pkac.challenge.data);
    }
    return rv;
}
Ejemplo n.º 4
0
nsresult
nsHyphenator::Hyphenate(const nsAString& aString,
                        nsTArray<bool>& aHyphens)
{
  if (!aHyphens.SetLength(aString.Length())) {
    return NS_ERROR_OUT_OF_MEMORY;
  }
  memset(aHyphens.Elements(), PR_FALSE, aHyphens.Length());

  bool inWord = false;
  PRUint32 wordStart = 0, wordLimit = 0;
  PRUint32 chLen;
  for (PRUint32 i = 0; i < aString.Length(); i += chLen) {
    PRUint32 ch = aString[i];
    chLen = 1;

    if (NS_IS_HIGH_SURROGATE(ch)) {
      if (i + 1 < aString.Length() && NS_IS_LOW_SURROGATE(aString[i+1])) {
        ch = SURROGATE_TO_UCS4(ch, aString[i+1]);
        chLen = 2;
      } else {
        NS_WARNING("unpaired surrogate found during hyphenation");
      }
    }

    nsIUGenCategory::nsUGenCategory cat = mCategories->Get(ch);
    if (cat == nsIUGenCategory::kLetter || cat == nsIUGenCategory::kMark) {
      if (!inWord) {
        inWord = PR_TRUE;
        wordStart = i;
      }
      wordLimit = i + chLen;
      if (i + chLen < aString.Length()) {
        continue;
      }
    }

    if (inWord) {
      const PRUnichar *begin = aString.BeginReading();
      NS_ConvertUTF16toUTF8 utf8(begin + wordStart,
                                 wordLimit - wordStart);
      nsAutoTArray<char,200> utf8hyphens;
      utf8hyphens.SetLength(utf8.Length() + 5);
      char **rep = nsnull;
      int *pos = nsnull;
      int *cut = nsnull;
      int err = hnj_hyphen_hyphenate2((HyphenDict*)mDict,
                                      utf8.BeginReading(), utf8.Length(),
                                      utf8hyphens.Elements(), nsnull,
                                      &rep, &pos, &cut);
      if (!err) {
        // Surprisingly, hnj_hyphen_hyphenate2 converts the 'hyphens' buffer
        // from utf8 code unit indexing (which would match the utf8 input
        // string directly) to Unicode character indexing.
        // We then need to convert this to utf16 code unit offsets for Gecko.
        const char *hyphPtr = utf8hyphens.Elements();
        const PRUnichar *cur = begin + wordStart;
        const PRUnichar *end = begin + wordLimit;
        while (cur < end) {
          if (*hyphPtr & 0x01) {
            aHyphens[cur - begin] = PR_TRUE;
          }
          cur++;
          if (cur < end && NS_IS_LOW_SURROGATE(*cur) &&
              NS_IS_HIGH_SURROGATE(*(cur-1)))
          {
            cur++;
          }
          hyphPtr++;
        }
      }
    }
    
    inWord = PR_FALSE;
  }

  return NS_OK;
}
Ejemplo n.º 5
0
NS_IMETHODIMP
nsHtml5Parser::Parse(const nsAString& aSourceBuffer,
                     void* aKey,
                     const nsACString& aContentType, // ignored
                     PRBool aLastCall,
                     nsDTDMode aMode) // ignored
{
  NS_PRECONDITION(!mExecutor->IsFragmentMode(),
                  "Document.write called in fragment mode!");

  // Maintain a reference to ourselves so we don't go away
  // till we're completely done. The old parser grips itself in this method.
  nsCOMPtr<nsIParser> kungFuDeathGrip(this);
  
  // Gripping the other objects just in case, since the other old grip
  // required grips to these, too.
  nsRefPtr<nsHtml5StreamParser> streamKungFuDeathGrip(mStreamParser);
  nsRefPtr<nsHtml5TreeOpExecutor> treeOpKungFuDeathGrip(mExecutor);

  if (!mExecutor->HasStarted()) {
    NS_ASSERTION(!mStreamParser,
                 "Had stream parser but document.write started life cycle.");
    // This is the first document.write() on a document.open()ed document
    mExecutor->SetParser(this);
    mTreeBuilder->setScriptingEnabled(mExecutor->IsScriptEnabled());
    mTokenizer->start();
    mExecutor->Start();
    /*
     * If you move the following line, be very careful not to cause 
     * WillBuildModel to be called before the document has had its 
     * script global object set.
     */
    mExecutor->WillBuildModel(eDTDMode_unknown);
  }

  // Return early if the parser has processed EOF
  if (mExecutor->IsComplete()) {
    return NS_OK;
  }

  if (aLastCall && aSourceBuffer.IsEmpty() && aKey == GetRootContextKey()) {
    // document.close()
    NS_ASSERTION(!mStreamParser,
                 "Had stream parser but got document.close().");
    mDocumentClosed = PR_TRUE;
    if (!mBlocked) {
      ParseUntilBlocked();
    }
    return NS_OK;
  }

  NS_ASSERTION(IsInsertionPointDefined(),
               "Doc.write reached parser with undefined insertion point.");

  NS_ASSERTION(!(mStreamParser && !aKey),
               "Got a null key in a non-script-created parser");

  if (aSourceBuffer.IsEmpty()) {
    return NS_OK;
  }

  nsRefPtr<nsHtml5UTF16Buffer> buffer =
    new nsHtml5UTF16Buffer(aSourceBuffer.Length());
  memcpy(buffer->getBuffer(),
         aSourceBuffer.BeginReading(),
         aSourceBuffer.Length() * sizeof(PRUnichar));
  buffer->setEnd(aSourceBuffer.Length());

  // The buffer is inserted to the stream here in case it won't be parsed
  // to completion.
  // The script is identified by aKey. If there's nothing in the buffer
  // chain for that key, we'll insert at the head of the queue.
  // When the script leaves something in the queue, a zero-length
  // key-holder "buffer" is inserted in the queue. If the same script
  // leaves something in the chain again, it will be inserted immediately
  // before the old key holder belonging to the same script.
  nsHtml5UTF16Buffer* prevSearchBuf = nsnull;
  nsHtml5UTF16Buffer* searchBuf = mFirstBuffer;

  // after document.open, the first level of document.write has null key
  if (aKey) {
    while (searchBuf != mLastBuffer) {
      if (searchBuf->key == aKey) {
        // found a key holder
        // now insert the new buffer between the previous buffer
        // and the key holder.
        buffer->next = searchBuf;
        if (prevSearchBuf) {
          prevSearchBuf->next = buffer;
        } else {
          mFirstBuffer = buffer;
        }
        break;
      }
      prevSearchBuf = searchBuf;
      searchBuf = searchBuf->next;
    }
    if (searchBuf == mLastBuffer) {
      // key was not found
      nsHtml5UTF16Buffer* keyHolder = new nsHtml5UTF16Buffer(aKey);
      keyHolder->next = mFirstBuffer;
      buffer->next = keyHolder;
      mFirstBuffer = buffer;
    }
  } else {
    // we have a first level document.write after document.open()
    // insert immediately before mLastBuffer
    while (searchBuf != mLastBuffer) {
      prevSearchBuf = searchBuf;
      searchBuf = searchBuf->next;
    }
    buffer->next = mLastBuffer;
    if (prevSearchBuf) {
      prevSearchBuf->next = buffer;
    } else {
      mFirstBuffer = buffer;
    }
  }

  while (!mBlocked && buffer->hasMore()) {
    buffer->adjust(mLastWasCR);
    mLastWasCR = PR_FALSE;
    if (buffer->hasMore()) {
      PRInt32 lineNumberSave;
      PRBool inRootContext = (!mStreamParser && (aKey == mRootContextKey));
      if (inRootContext) {
        mTokenizer->setLineNumber(mRootContextLineNumber);
      } else {
        // we aren't the root context, so save the line number on the
        // *stack* so that we can restore it.
        lineNumberSave = mTokenizer->getLineNumber();
      }

      mLastWasCR = mTokenizer->tokenizeBuffer(buffer);

      if (inRootContext) {
        mRootContextLineNumber = mTokenizer->getLineNumber();
      } else {
        mTokenizer->setLineNumber(lineNumberSave);
      }

      if (mTreeBuilder->HasScript()) {
        mTreeBuilder->Flush(); // Move ops to the executor
        mExecutor->FlushDocumentWrite(); // run the ops
      }
      // Ignore suspension requests
    }
  }

  if (!mBlocked) { // buffer was tokenized to completion
    NS_ASSERTION(!buffer->hasMore(), "Buffer wasn't tokenized to completion?");
    // Scripting semantics require a forced tree builder flush here
    mTreeBuilder->Flush(); // Move ops to the executor
    mExecutor->FlushDocumentWrite(); // run the ops
  } else if (buffer->hasMore()) {
    // The buffer wasn't tokenized to completion. Tokenize the untokenized
    // content in order to preload stuff. This content will be retokenized
    // later for normal parsing.
    if (!mDocWriteSpeculatorActive) {
      mDocWriteSpeculatorActive = PR_TRUE;
      if (!mDocWriteSpeculativeTreeBuilder) {
        // Lazily initialize if uninitialized
        mDocWriteSpeculativeTreeBuilder =
            new nsHtml5TreeBuilder(nsnull, mExecutor->GetStage());
        mDocWriteSpeculativeTreeBuilder->setScriptingEnabled(
            mTreeBuilder->isScriptingEnabled());
        mDocWriteSpeculativeTokenizer =
            new nsHtml5Tokenizer(mDocWriteSpeculativeTreeBuilder);
        mDocWriteSpeculativeTokenizer->setInterner(&mAtomTable);
        mDocWriteSpeculativeTokenizer->start();
      }
      mDocWriteSpeculativeTokenizer->resetToDataState();
      mDocWriteSpeculativeTreeBuilder->loadState(mTreeBuilder, &mAtomTable);
      mDocWriteSpeculativeLastWasCR = PR_FALSE;
    }

    // Note that with multilevel document.write if we didn't just activate the
    // speculator, it's possible that the speculator is now in the wrong state.
    // That's OK for the sake of simplicity. The worst that can happen is
    // that the speculative loads aren't exactly right. The content will be
    // reparsed anyway for non-preload purposes.

    PRInt32 originalStart = buffer->getStart();
    while (buffer->hasMore()) {
      buffer->adjust(mDocWriteSpeculativeLastWasCR);
      if (buffer->hasMore()) {
        mDocWriteSpeculativeLastWasCR =
            mDocWriteSpeculativeTokenizer->tokenizeBuffer(buffer);
      }
    }
    buffer->setStart(originalStart);

    mDocWriteSpeculativeTreeBuilder->Flush();
    mDocWriteSpeculativeTreeBuilder->DropHandles();
    mExecutor->FlushSpeculativeLoads();
  }

  return NS_OK;
}
Ejemplo n.º 6
0
void
nsCSSSelector::AppendToStringWithoutCombinatorsOrNegations
                   (nsAString& aString, CSSStyleSheet* aSheet,
                   bool aIsNegated,
                   bool aUseStandardNamespacePrefixes) const
{
  nsAutoString temp;
  bool isPseudoElement = IsPseudoElement();

  // For non-pseudo-element selectors or for lone pseudo-elements, deal with
  // namespace prefixes.
  bool wroteNamespace = false;
  if (!isPseudoElement || !mNext) {
    // append the namespace prefix if needed
    nsXMLNameSpaceMap *sheetNS = aSheet ? aSheet->GetNameSpaceMap() : nullptr;

    // sheetNS is non-null if and only if we had an @namespace rule.  If it's
    // null, that means that the only namespaces we could have are the
    // wildcard namespace (which can be implicit in this case) and the "none"
    // namespace, which then needs to be explicitly specified.
    if (aUseStandardNamespacePrefixes) {
#ifdef DEBUG
      // We have no sheet to look up prefix information from.  This is
      // only for debugging, so use some "standard" prefixes that
      // are recognizable.
      wroteNamespace =
        AppendStandardNamespacePrefixToString(aString, mNameSpace);
      if (wroteNamespace) {
        aString.Append(char16_t('|'));
      }
#endif
    } else if (!sheetNS) {
      NS_ASSERTION(mNameSpace == kNameSpaceID_Unknown ||
                   mNameSpace == kNameSpaceID_None,
                   "How did we get this namespace?");
      if (mNameSpace == kNameSpaceID_None) {
        aString.Append(char16_t('|'));
        wroteNamespace = true;
      }
    } else if (sheetNS->FindNameSpaceID(nullptr) == mNameSpace) {
      // We have the default namespace (possibly including the wildcard
      // namespace).  Do nothing.
      NS_ASSERTION(mNameSpace == kNameSpaceID_Unknown ||
                   CanBeNamespaced(aIsNegated),
                   "How did we end up with this namespace?");
    } else if (mNameSpace == kNameSpaceID_None) {
      NS_ASSERTION(CanBeNamespaced(aIsNegated),
                   "How did we end up with this namespace?");
      aString.Append(char16_t('|'));
      wroteNamespace = true;
    } else if (mNameSpace != kNameSpaceID_Unknown) {
      NS_ASSERTION(CanBeNamespaced(aIsNegated),
                   "How did we end up with this namespace?");
      nsIAtom *prefixAtom = sheetNS->FindPrefix(mNameSpace);
      NS_ASSERTION(prefixAtom, "how'd we get a non-default namespace "
                   "without a prefix?");
      nsStyleUtil::AppendEscapedCSSIdent(nsDependentAtomString(prefixAtom),
                                         aString);
      aString.Append(char16_t('|'));
      wroteNamespace = true;
    } else {
      // A selector for an element in any namespace, while the default
      // namespace is something else.  :not() is special in that the default
      // namespace is not implied for non-type selectors, so if this is a
      // negated non-type selector we don't need to output an explicit wildcard
      // namespace here, since those default to a wildcard namespace.
      if (CanBeNamespaced(aIsNegated)) {
        aString.AppendLiteral("*|");
        wroteNamespace = true;
      }
    }
  }
      
  if (!mLowercaseTag) {
    // Universal selector:  avoid writing the universal selector when we
    // can avoid it, especially since we're required to avoid it for the
    // inside of :not()
    if (wroteNamespace ||
        (!mIDList && !mClassList && !mPseudoClassList && !mAttrList &&
         (aIsNegated || !mNegations))) {
      aString.Append(char16_t('*'));
    }
  } else {
    // Append the tag name
    nsAutoString tag;
    (isPseudoElement ? mLowercaseTag : mCasedTag)->ToString(tag);
    if (isPseudoElement) {
      if (!mNext) {
        // Lone pseudo-element selector -- toss in a wildcard type selector
        // XXXldb Why?
        aString.Append(char16_t('*'));
      }
      // While our atoms use one colon, most pseudo-elements require two
      // colons (those not in CSS level 2) and all pseudo-elements allow
      // two colons. So serialize to the non-deprecated two colon syntax.
      aString.Append(char16_t(':'));
      // This should not be escaped since (a) the pseudo-element string
      // has a ":" that can't be escaped and (b) all pseudo-elements at
      // this point are known, and therefore we know they don't need
      // escaping.
      aString.Append(tag);
    } else {
      nsStyleUtil::AppendEscapedCSSIdent(tag, aString);
    }
  }

  // Append the id, if there is one
  if (mIDList) {
    nsAtomList* list = mIDList;
    while (list != nullptr) {
      list->mAtom->ToString(temp);
      aString.Append(char16_t('#'));
      nsStyleUtil::AppendEscapedCSSIdent(temp, aString);
      list = list->mNext;
    }
  }

  // Append each class in the linked list
  if (mClassList) {
    if (isPseudoElement) {
#ifdef MOZ_XUL
      MOZ_ASSERT(nsCSSAnonBoxes::IsTreePseudoElement(mLowercaseTag),
                 "must be tree pseudo-element");

      aString.Append(char16_t('('));
      for (nsAtomList* list = mClassList; list; list = list->mNext) {
        nsStyleUtil::AppendEscapedCSSIdent(nsDependentAtomString(list->mAtom), aString);
        aString.Append(char16_t(','));
      }
      // replace the final comma with a close-paren
      aString.Replace(aString.Length() - 1, 1, char16_t(')'));
#else
      NS_ERROR("Can't happen");
#endif
    } else {
      nsAtomList* list = mClassList;
      while (list != nullptr) {
        list->mAtom->ToString(temp);
        aString.Append(char16_t('.'));
        nsStyleUtil::AppendEscapedCSSIdent(temp, aString);
        list = list->mNext;
      }
    }
  }

  // Append each attribute selector in the linked list
  if (mAttrList) {
    nsAttrSelector* list = mAttrList;
    while (list != nullptr) {
      aString.Append(char16_t('['));
      // Append the namespace prefix
      if (list->mNameSpace == kNameSpaceID_Unknown) {
        aString.Append(char16_t('*'));
        aString.Append(char16_t('|'));
      } else if (list->mNameSpace != kNameSpaceID_None) {
        if (aUseStandardNamespacePrefixes) {
#ifdef DEBUG
          AppendStandardNamespacePrefixToString(aString, list->mNameSpace);
          aString.Append(char16_t('|'));
#endif
        } else if (aSheet) {
          nsXMLNameSpaceMap *sheetNS = aSheet->GetNameSpaceMap();
          nsIAtom *prefixAtom = sheetNS->FindPrefix(list->mNameSpace);
          // Default namespaces don't apply to attribute selectors, so
          // we must have a useful prefix.
          NS_ASSERTION(prefixAtom,
                       "How did we end up with a namespace if the prefix "
                       "is unknown?");
          nsAutoString prefix;
          prefixAtom->ToString(prefix);
          nsStyleUtil::AppendEscapedCSSIdent(prefix, aString);
          aString.Append(char16_t('|'));
        }
      }
      // Append the attribute name
      list->mCasedAttr->ToString(temp);
      nsStyleUtil::AppendEscapedCSSIdent(temp, aString);

      if (list->mFunction != NS_ATTR_FUNC_SET) {
        // Append the function
        if (list->mFunction == NS_ATTR_FUNC_INCLUDES)
          aString.Append(char16_t('~'));
        else if (list->mFunction == NS_ATTR_FUNC_DASHMATCH)
          aString.Append(char16_t('|'));
        else if (list->mFunction == NS_ATTR_FUNC_BEGINSMATCH)
          aString.Append(char16_t('^'));
        else if (list->mFunction == NS_ATTR_FUNC_ENDSMATCH)
          aString.Append(char16_t('$'));
        else if (list->mFunction == NS_ATTR_FUNC_CONTAINSMATCH)
          aString.Append(char16_t('*'));

        aString.Append(char16_t('='));
      
        // Append the value
        nsStyleUtil::AppendEscapedCSSString(list->mValue, aString);

        if (list->mValueCaseSensitivity ==
              nsAttrSelector::ValueCaseSensitivity::CaseInsensitive) {
          aString.Append(NS_LITERAL_STRING(" i"));
        }
      }

      aString.Append(char16_t(']'));
      
      list = list->mNext;
    }
  }

  // Append each pseudo-class in the linked list
  for (nsPseudoClassList* list = mPseudoClassList; list; list = list->mNext) {
    nsCSSPseudoClasses::PseudoTypeToString(list->mType, temp);
    // This should not be escaped since (a) the pseudo-class string
    // has a ":" that can't be escaped and (b) all pseudo-classes at
    // this point are known, and therefore we know they don't need
    // escaping.
    aString.Append(temp);
    if (list->u.mMemory) {
      aString.Append(char16_t('('));
      if (nsCSSPseudoClasses::HasStringArg(list->mType)) {
        nsStyleUtil::AppendEscapedCSSIdent(
          nsDependentString(list->u.mString), aString);
      } else if (nsCSSPseudoClasses::HasNthPairArg(list->mType)) {
        int32_t a = list->u.mNumbers[0],
                b = list->u.mNumbers[1];
        temp.Truncate();
        if (a != 0) {
          if (a == -1) {
            temp.Append(char16_t('-'));
          } else if (a != 1) {
            temp.AppendInt(a);
          }
          temp.Append(char16_t('n'));
        }
        if (b != 0 || a == 0) {
          if (b >= 0 && a != 0) // check a != 0 for whether we printed above
            temp.Append(char16_t('+'));
          temp.AppendInt(b);
        }
        aString.Append(temp);
      } else {
        NS_ASSERTION(nsCSSPseudoClasses::HasSelectorListArg(list->mType),
                     "unexpected pseudo-class");
        nsString tmp;
        list->u.mSelectors->ToString(tmp, aSheet);
        aString.Append(tmp);
      }
      aString.Append(char16_t(')'));
    }
  }
}
Ejemplo n.º 7
0
nsresult nsPrefBranch::CheckSanityOfStringLength(const char* aPrefName, const nsAString& aValue) {
  return CheckSanityOfStringLength(aPrefName, aValue.Length());
}
Ejemplo n.º 8
0
NS_IMETHODIMP
nsHtml5Parser::Parse(const nsAString& aSourceBuffer,
                     void* aKey,
                     const nsACString& aContentType,
                     bool aLastCall,
                     nsDTDMode aMode) // ignored
{
    nsresult rv;
    if (NS_FAILED(rv = mExecutor->IsBroken())) {
        return rv;
    }
    if (aSourceBuffer.Length() > INT32_MAX) {
        return mExecutor->MarkAsBroken(NS_ERROR_OUT_OF_MEMORY);
    }

    // Maintain a reference to ourselves so we don't go away
    // till we're completely done. The old parser grips itself in this method.
    nsCOMPtr<nsIParser> kungFuDeathGrip(this);

    // Gripping the other objects just in case, since the other old grip
    // required grips to these, too.
    nsRefPtr<nsHtml5StreamParser> streamKungFuDeathGrip(GetStreamParser());
    nsRefPtr<nsHtml5TreeOpExecutor> treeOpKungFuDeathGrip(mExecutor);

    if (!mExecutor->HasStarted()) {
        NS_ASSERTION(!GetStreamParser(),
                     "Had stream parser but document.write started life cycle.");
        // This is the first document.write() on a document.open()ed document
        mExecutor->SetParser(this);
        mTreeBuilder->setScriptingEnabled(mExecutor->IsScriptEnabled());

        bool isSrcdoc = false;
        nsCOMPtr<nsIChannel> channel;
        rv = GetChannel(getter_AddRefs(channel));
        if (NS_SUCCEEDED(rv)) {
            isSrcdoc = NS_IsSrcdocChannel(channel);
        }
        mTreeBuilder->setIsSrcdocDocument(isSrcdoc);

        mTokenizer->start();
        mExecutor->Start();
        if (!aContentType.EqualsLiteral("text/html")) {
            mTreeBuilder->StartPlainText();
            mTokenizer->StartPlainText();
        }
        /*
         * If you move the following line, be very careful not to cause
         * WillBuildModel to be called before the document has had its
         * script global object set.
         */
        mExecutor->WillBuildModel(eDTDMode_unknown);
    }

    // Return early if the parser has processed EOF
    if (mExecutor->IsComplete()) {
        return NS_OK;
    }

    if (aLastCall && aSourceBuffer.IsEmpty() && !aKey) {
        // document.close()
        NS_ASSERTION(!GetStreamParser(),
                     "Had stream parser but got document.close().");
        if (mDocumentClosed) {
            // already closed
            return NS_OK;
        }
        mDocumentClosed = true;
        if (!mBlocked && !mInDocumentWrite) {
            ParseUntilBlocked();
        }
        return NS_OK;
    }

    // If we got this far, we are dealing with a document.write or
    // document.writeln call--not document.close().

    NS_ASSERTION(IsInsertionPointDefined(),
                 "Doc.write reached parser with undefined insertion point.");

    NS_ASSERTION(!(GetStreamParser() && !aKey),
                 "Got a null key in a non-script-created parser");

    // XXX is this optimization bogus?
    if (aSourceBuffer.IsEmpty()) {
        return NS_OK;
    }

    // This guard is here to prevent document.close from tokenizing synchronously
    // while a document.write (that wrote the script that called document.close!)
    // is still on the call stack.
    mozilla::AutoRestore<bool> guard(mInDocumentWrite);
    mInDocumentWrite = true;

    // The script is identified by aKey. If there's nothing in the buffer
    // chain for that key, we'll insert at the head of the queue.
    // When the script leaves something in the queue, a zero-length
    // key-holder "buffer" is inserted in the queue. If the same script
    // leaves something in the chain again, it will be inserted immediately
    // before the old key holder belonging to the same script.
    //
    // We don't do the actual data insertion yet in the hope that the data gets
    // tokenized and there no data or less data to copy to the heap after
    // tokenization. Also, this way, we avoid inserting one empty data buffer
    // per document.write, which matters for performance when the parser isn't
    // blocked and a badly-authored script calls document.write() once per
    // input character. (As seen in a benchmark!)
    //
    // The insertion into the input stream happens conceptually before anything
    // gets tokenized. To make sure multi-level document.write works right,
    // it's necessary to establish the location of our parser key up front
    // in case this is the first write with this key.
    //
    // In a document.open() case, the first write level has a null key, so that
    // case is handled separately, because normal buffers containing data
    // have null keys.

    // These don't need to be owning references, because they always point to
    // the buffer queue and buffers can't be removed from the buffer queue
    // before document.write() returns. The buffer queue clean-up happens the
    // next time ParseUntilBlocked() is called.
    // However, they are made owning just in case the reasoning above is flawed
    // and a flaw would lead to worse problems with plain pointers. If this
    // turns out to be a perf problem, it's worthwhile to consider making
    // prevSearchbuf a plain pointer again.
    nsRefPtr<nsHtml5OwningUTF16Buffer> prevSearchBuf;
    nsRefPtr<nsHtml5OwningUTF16Buffer> firstLevelMarker;

    if (aKey) {
        if (mFirstBuffer == mLastBuffer) {
            nsHtml5OwningUTF16Buffer* keyHolder = new nsHtml5OwningUTF16Buffer(aKey);
            keyHolder->next = mLastBuffer;
            mFirstBuffer = keyHolder;
        } else if (mFirstBuffer->key != aKey) {
            prevSearchBuf = mFirstBuffer;
            for (;;) {
                if (prevSearchBuf->next == mLastBuffer) {
                    // key was not found
                    nsHtml5OwningUTF16Buffer* keyHolder =
                        new nsHtml5OwningUTF16Buffer(aKey);
                    keyHolder->next = mFirstBuffer;
                    mFirstBuffer = keyHolder;
                    prevSearchBuf = nullptr;
                    break;
                }
                if (prevSearchBuf->next->key == aKey) {
                    // found a key holder
                    break;
                }
                prevSearchBuf = prevSearchBuf->next;
            }
        } // else mFirstBuffer is the keyholder

        // prevSearchBuf is the previous buffer before the keyholder or null if
        // there isn't one.
    } else {
        // We have a first-level write in the document.open() case. We insert before
        // mLastBuffer, effectively, by making mLastBuffer be a new sentinel object
        // and redesignating the previous mLastBuffer as our firstLevelMarker.  We
        // need to put a marker there, because otherwise additional document.writes
        // from nested event loops would insert in the wrong place. Sigh.
        mLastBuffer->next = new nsHtml5OwningUTF16Buffer((void*)nullptr);
        firstLevelMarker = mLastBuffer;
        mLastBuffer = mLastBuffer->next;
    }

    nsHtml5DependentUTF16Buffer stackBuffer(aSourceBuffer);

    while (!mBlocked && stackBuffer.hasMore()) {
        stackBuffer.adjust(mLastWasCR);
        mLastWasCR = false;
        if (stackBuffer.hasMore()) {
            int32_t lineNumberSave;
            bool inRootContext = (!GetStreamParser() && !aKey);
            if (inRootContext) {
                mTokenizer->setLineNumber(mRootContextLineNumber);
            } else {
                // we aren't the root context, so save the line number on the
                // *stack* so that we can restore it.
                lineNumberSave = mTokenizer->getLineNumber();
            }

            mLastWasCR = mTokenizer->tokenizeBuffer(&stackBuffer);

            if (inRootContext) {
                mRootContextLineNumber = mTokenizer->getLineNumber();
            } else {
                mTokenizer->setLineNumber(lineNumberSave);
            }

            if (mTreeBuilder->HasScript()) {
                mTreeBuilder->Flush(); // Move ops to the executor
                mExecutor->FlushDocumentWrite(); // run the ops
                // Flushing tree ops can cause all sorts of things.
                // Return early if the parser got terminated.
                if (mExecutor->IsComplete()) {
                    return NS_OK;
                }
            }
            // Ignore suspension requests
        }
    }

    nsRefPtr<nsHtml5OwningUTF16Buffer> heapBuffer;
    if (stackBuffer.hasMore()) {
        // The buffer wasn't tokenized to completion. Create a copy of the tail
        // on the heap.
        heapBuffer = stackBuffer.FalliblyCopyAsOwningBuffer();
        if (!heapBuffer) {
            // Allocation failed. The parser is now broken.
            return mExecutor->MarkAsBroken(NS_ERROR_OUT_OF_MEMORY);
        }
    }

    if (heapBuffer) {
        // We have something to insert before the keyholder holding in the non-null
        // aKey case and we have something to swap into firstLevelMarker in the
        // null aKey case.
        if (aKey) {
            NS_ASSERTION(mFirstBuffer != mLastBuffer,
                         "Where's the keyholder?");
            // the key holder is still somewhere further down the list from
            // prevSearchBuf (which may be null)
            if (mFirstBuffer->key == aKey) {
                NS_ASSERTION(!prevSearchBuf,
                             "Non-null prevSearchBuf when mFirstBuffer is the key holder?");
                heapBuffer->next = mFirstBuffer;
                mFirstBuffer = heapBuffer;
            } else {
                if (!prevSearchBuf) {
                    prevSearchBuf = mFirstBuffer;
                }
                // We created a key holder earlier, so we will find it without walking
                // past the end of the list.
                while (prevSearchBuf->next->key != aKey) {
                    prevSearchBuf = prevSearchBuf->next;
                }
                heapBuffer->next = prevSearchBuf->next;
                prevSearchBuf->next = heapBuffer;
            }
        } else {
            NS_ASSERTION(firstLevelMarker, "How come we don't have a marker.");
            firstLevelMarker->Swap(heapBuffer);
        }
    }

    if (!mBlocked) { // buffer was tokenized to completion
        NS_ASSERTION(!stackBuffer.hasMore(),
                     "Buffer wasn't tokenized to completion?");
        // Scripting semantics require a forced tree builder flush here
        mTreeBuilder->Flush(); // Move ops to the executor
        mExecutor->FlushDocumentWrite(); // run the ops
    } else if (stackBuffer.hasMore()) {
        // The buffer wasn't tokenized to completion. Tokenize the untokenized
        // content in order to preload stuff. This content will be retokenized
        // later for normal parsing.
        if (!mDocWriteSpeculatorActive) {
            mDocWriteSpeculatorActive = true;
            if (!mDocWriteSpeculativeTreeBuilder) {
                // Lazily initialize if uninitialized
                mDocWriteSpeculativeTreeBuilder =
                    new nsHtml5TreeBuilder(nullptr, mExecutor->GetStage());
                mDocWriteSpeculativeTreeBuilder->setScriptingEnabled(
                    mTreeBuilder->isScriptingEnabled());
                mDocWriteSpeculativeTokenizer =
                    new nsHtml5Tokenizer(mDocWriteSpeculativeTreeBuilder, false);
                mDocWriteSpeculativeTokenizer->setInterner(&mAtomTable);
                mDocWriteSpeculativeTokenizer->start();
            }
            mDocWriteSpeculativeTokenizer->resetToDataState();
            mDocWriteSpeculativeTreeBuilder->loadState(mTreeBuilder, &mAtomTable);
            mDocWriteSpeculativeLastWasCR = false;
        }

        // Note that with multilevel document.write if we didn't just activate the
        // speculator, it's possible that the speculator is now in the wrong state.
        // That's OK for the sake of simplicity. The worst that can happen is
        // that the speculative loads aren't exactly right. The content will be
        // reparsed anyway for non-preload purposes.

        // The buffer position for subsequent non-speculative parsing now lives
        // in heapBuffer, so it's ok to let the buffer position of stackBuffer
        // to be overwritten and not restored below.
        while (stackBuffer.hasMore()) {
            stackBuffer.adjust(mDocWriteSpeculativeLastWasCR);
            if (stackBuffer.hasMore()) {
                mDocWriteSpeculativeLastWasCR =
                    mDocWriteSpeculativeTokenizer->tokenizeBuffer(&stackBuffer);
            }
        }

        mDocWriteSpeculativeTreeBuilder->Flush();
        mDocWriteSpeculativeTreeBuilder->DropHandles();
        mExecutor->FlushSpeculativeLoads();
    }

    return NS_OK;
}
Ejemplo n.º 9
0
void
ToUpperCase(nsAString& aString)
{
  PRUnichar *buf = aString.BeginWriting();
  ToUpperCase(buf, buf, aString.Length());
}
Ejemplo n.º 10
0
void
HTMLTextAreaElement::SetRangeText(const nsAString& aReplacement,
                                  uint32_t aStart, uint32_t aEnd,
                                  const SelectionMode& aSelectMode,
                                  ErrorResult& aRv, int32_t aSelectionStart,
                                  int32_t aSelectionEnd)
{
  if (aStart > aEnd) {
    aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
    return;
  }

  nsAutoString value;
  GetValueInternal(value, false);
  uint32_t inputValueLength = value.Length();

  if (aStart > inputValueLength) {
    aStart = inputValueLength;
  }

  if (aEnd > inputValueLength) {
    aEnd = inputValueLength;
  }

  if (aSelectionStart == -1 && aSelectionEnd == -1) {
    aRv = GetSelectionRange(&aSelectionStart, &aSelectionEnd);
    if (aRv.Failed()) {
      if (mState.IsSelectionCached()) {
        aSelectionStart = mState.GetSelectionProperties().GetStart();
        aSelectionEnd = mState.GetSelectionProperties().GetEnd();
        aRv = NS_OK;
      }
    }
  }

  if (aStart <= aEnd) {
    value.Replace(aStart, aEnd - aStart, aReplacement);
    nsresult rv =
      SetValueInternal(value, nsTextEditorState::eSetValue_ByContent);
    if (NS_FAILED(rv)) {
      aRv.Throw(rv);
      return;
    }
  }

  uint32_t newEnd = aStart + aReplacement.Length();
  int32_t delta =  aReplacement.Length() - (aEnd - aStart);

  switch (aSelectMode) {
    case mozilla::dom::SelectionMode::Select:
    {
      aSelectionStart = aStart;
      aSelectionEnd = newEnd;
    }
    break;
    case mozilla::dom::SelectionMode::Start:
    {
      aSelectionStart = aSelectionEnd = aStart;
    }
    break;
    case mozilla::dom::SelectionMode::End:
    {
      aSelectionStart = aSelectionEnd = newEnd;
    }
    break;
    case mozilla::dom::SelectionMode::Preserve:
    {
      if ((uint32_t)aSelectionStart > aEnd) {
        aSelectionStart += delta;
      } else if ((uint32_t)aSelectionStart > aStart) {
        aSelectionStart = aStart;
      }

      if ((uint32_t)aSelectionEnd > aEnd) {
        aSelectionEnd += delta;
      } else if ((uint32_t)aSelectionEnd > aStart) {
        aSelectionEnd = newEnd;
      }
    }
    break;
    default:
      MOZ_CRASH("Unknown mode!");
  }

  Optional<nsAString> direction;
  SetSelectionRange(aSelectionStart, aSelectionEnd, direction, aRv);
}
nsresult
nsHTMLCanvasElement::ToDataURLImpl(const nsAString& aMimeType,
                                   nsIVariant* aEncoderOptions,
                                   nsAString& aDataURL)
{
  bool fallbackToPNG = false;

  nsIntSize size = GetWidthHeight();
  if (size.height == 0 || size.width == 0) {
    aDataURL = NS_LITERAL_STRING("data:,");
    return NS_OK;
  }

  nsAutoString type;
  nsContentUtils::ASCIIToLower(aMimeType, type);

  nsAutoString params;

  // Quality parameter is only valid for the image/jpeg MIME type
  if (type.EqualsLiteral("image/jpeg")) {
    PRUint16 vartype;

    if (aEncoderOptions &&
        NS_SUCCEEDED(aEncoderOptions->GetDataType(&vartype)) &&
        vartype <= nsIDataType::VTYPE_DOUBLE) {

      double quality;
      // Quality must be between 0.0 and 1.0, inclusive
      if (NS_SUCCEEDED(aEncoderOptions->GetAsDouble(&quality)) &&
          quality >= 0.0 && quality <= 1.0) {
        params.AppendLiteral("quality=");
        params.AppendInt(NS_lround(quality * 100.0));
      }
    }
  }

  // If we haven't parsed the params check for proprietary options.
  // The proprietary option -moz-parse-options will take a image lib encoder
  // parse options string as is and pass it to the encoder.
  bool usingCustomParseOptions = false;
  if (params.Length() == 0) {
    NS_NAMED_LITERAL_STRING(mozParseOptions, "-moz-parse-options:");
    nsAutoString paramString;
    if (NS_SUCCEEDED(aEncoderOptions->GetAsAString(paramString)) && 
        StringBeginsWith(paramString, mozParseOptions)) {
      nsDependentSubstring parseOptions = Substring(paramString, 
                                                    mozParseOptions.Length(), 
                                                    paramString.Length() - 
                                                    mozParseOptions.Length());
      params.Append(parseOptions);
      usingCustomParseOptions = true;
    }
  }

  nsCOMPtr<nsIInputStream> stream;
  nsresult rv = ExtractData(type, params, getter_AddRefs(stream),
                            fallbackToPNG);

  // If there are unrecognized custom parse options, we should fall back to 
  // the default values for the encoder without any options at all.
  if (rv == NS_ERROR_INVALID_ARG && usingCustomParseOptions) {
    fallbackToPNG = false;
    rv = ExtractData(type, EmptyString(), getter_AddRefs(stream), fallbackToPNG);
  }

  NS_ENSURE_SUCCESS(rv, rv);

  // build data URL string
  if (fallbackToPNG)
    aDataURL = NS_LITERAL_STRING("data:image/png;base64,");
  else
    aDataURL = NS_LITERAL_STRING("data:") + type +
      NS_LITERAL_STRING(";base64,");

  PRUint32 count;
  rv = stream->Available(&count);
  NS_ENSURE_SUCCESS(rv, rv);

  return Base64EncodeInputStream(stream, aDataURL, count, aDataURL.Length());
}
Ejemplo n.º 12
0
// Parses the encoder options and sets the bits per pixel to use and PNG or BMP
// See InitFromData for a description of the parse options
nsresult
nsICOEncoder::ParseOptions(const nsAString& aOptions, uint32_t* bpp, 
                           bool *usePNG)
{
  // If no parsing options just use the default of 24BPP and PNG yes
  if (aOptions.Length() == 0) {
    if (usePNG) {
      *usePNG = true;
    }
    if (bpp) {
      *bpp = 24;
    }
  }

  // Parse the input string into a set of name/value pairs.
  // From format: format=<png|bmp>;bpp=<bpp_value>
  // to format: [0] = format=<png|bmp>, [1] = bpp=<bpp_value>
  nsTArray<nsCString> nameValuePairs;
  if (!ParseString(NS_ConvertUTF16toUTF8(aOptions), ';', nameValuePairs)) {
    return NS_ERROR_INVALID_ARG;
  }

  // For each name/value pair in the set
  for (int i = 0; i < nameValuePairs.Length(); ++i) {

    // Split the name value pair [0] = name, [1] = value
    nsTArray<nsCString> nameValuePair;
    if (!ParseString(nameValuePairs[i], '=', nameValuePair)) {
      return NS_ERROR_INVALID_ARG;
    }
    if (nameValuePair.Length() != 2) {
      return NS_ERROR_INVALID_ARG;
    }

    // Parse the format portion of the string format=<png|bmp>;bpp=<bpp_value>
    if (nameValuePair[0].Equals("format", nsCaseInsensitiveCStringComparator())) {
      if (nameValuePair[1].Equals("png", nsCaseInsensitiveCStringComparator())) {
        *usePNG = true;
      }
      else if (nameValuePair[1].Equals("bmp", nsCaseInsensitiveCStringComparator())) {
        *usePNG = false;
      }
      else {
        return NS_ERROR_INVALID_ARG;
      }
    }

    // Parse the bpp portion of the string format=<png|bmp>;bpp=<bpp_value>
    if (nameValuePair[0].Equals("bpp", nsCaseInsensitiveCStringComparator())) {
      if (nameValuePair[1].Equals("24")) {
        *bpp = 24;
      }
      else if (nameValuePair[1].Equals("32")) {
        *bpp = 32;
      }
      else {
        return NS_ERROR_INVALID_ARG;
      }
    }
  }

  return NS_OK;
}
nsresult
BluetoothHfpManager::HandleVolumeChanged(const nsAString& aData)
{
  MOZ_ASSERT(NS_IsMainThread());

  // The string that we're interested in will be a JSON string that looks like:
  //  {"key":"volumeup", "value":1.0}
  //  {"key":"volumedown", "value":0.2}

  JSContext* cx = nsContentUtils::GetSafeJSContext();
  if (!cx) {
    return NS_OK;
  }

  JS::Value val;
  if (!JS_ParseJSON(cx, aData.BeginReading(), aData.Length(), &val)) {
    return JS_ReportPendingException(cx) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
  }

  if (!val.isObject()) {
    return NS_OK;
  }

  JSObject& obj(val.toObject());

  JS::Value key;
  if (!JS_GetProperty(cx, &obj, "key", &key)) {
    MOZ_ASSERT(!JS_IsExceptionPending(cx));
    return NS_ERROR_OUT_OF_MEMORY;
  }

  if (!key.isString()) {
    return NS_OK;
  }

  JSBool match;
  if (!JS_StringEqualsAscii(cx, key.toString(), AUDIO_VOLUME_MASTER, &match)) {
    MOZ_ASSERT(!JS_IsExceptionPending(cx));
    return NS_ERROR_OUT_OF_MEMORY;
  }

  if (!match) {
    return NS_OK;
  }

  JS::Value value;
  if (!JS_GetProperty(cx, &obj, "value", &value)) {
    MOZ_ASSERT(!JS_IsExceptionPending(cx));
    return NS_ERROR_OUT_OF_MEMORY;
  }

  if (!value.isNumber()) {
    return NS_ERROR_UNEXPECTED;
  }

  // AG volume range: [0.0, 1.0]
  float volume = value.toNumber();

  // HS volume range: [0, 15]
  mCurrentVgs = ceil(volume * 15);

  nsDiscriminatedUnion du;
  du.mType = 0;
  du.u.mInt8Value = mCurrentVgs;

  nsCString vgs;
  if (NS_FAILED(nsVariant::ConvertToACString(du, vgs))) {
    NS_WARNING("Failed to convert volume to string");
    return NS_ERROR_FAILURE;
  }

  nsAutoCString newVgs;
  newVgs += "+VGS: ";
  newVgs += vgs;

  SendLine(newVgs.get());

  return NS_OK;
}
Ejemplo n.º 14
0
NS_IMETHODIMP
nsTypeAheadFind::Find(const nsAString& aSearchString, bool aLinksOnly,
                      uint16_t* aResult)
{
  *aResult = FIND_NOTFOUND;

  nsCOMPtr<nsIPresShell> presShell (GetPresShell());
  if (!presShell) {
    nsCOMPtr<nsIDocShell> ds (do_QueryReferent(mDocShell));
    NS_ENSURE_TRUE(ds, NS_ERROR_FAILURE);

    presShell = ds->GetPresShell();
    NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
    mPresShell = do_GetWeakReference(presShell);
  }

  nsCOMPtr<nsISelection> selection;
  nsCOMPtr<nsISelectionController> selectionController =
    do_QueryReferent(mSelectionController);
  if (!selectionController) {
    GetSelection(presShell, getter_AddRefs(selectionController),
                 getter_AddRefs(selection)); // cache for reuse
    mSelectionController = do_GetWeakReference(selectionController);
  } else {
    selectionController->GetSelection(
      nsISelectionController::SELECTION_NORMAL, getter_AddRefs(selection));
  }

  if (selection)
    selection->CollapseToStart();

  if (aSearchString.IsEmpty()) {
    mTypeAheadBuffer.Truncate();

    // These will be initialized to their true values after the first character
    // is typed
    mStartFindRange = nullptr;
    mSelectionController = nullptr;

    *aResult = FIND_FOUND;
    return NS_OK;
  }

  bool atEnd = false;    
  if (mTypeAheadBuffer.Length()) {
    const nsAString& oldStr = Substring(mTypeAheadBuffer, 0, mTypeAheadBuffer.Length());
    const nsAString& newStr = Substring(aSearchString, 0, mTypeAheadBuffer.Length());
    if (oldStr.Equals(newStr))
      atEnd = true;
  
    const nsAString& newStr2 = Substring(aSearchString, 0, aSearchString.Length());
    const nsAString& oldStr2 = Substring(mTypeAheadBuffer, 0, aSearchString.Length());
    if (oldStr2.Equals(newStr2))
      atEnd = true;
    
    if (!atEnd)
      mStartFindRange = nullptr;
  }

  if (!mIsSoundInitialized && !mNotFoundSoundURL.IsEmpty()) {
    // This makes sure system sound library is loaded so that
    // there's no lag before the first sound is played
    // by waiting for the first keystroke, we still get the startup time benefits.
    mIsSoundInitialized = true;
    mSoundInterface = do_CreateInstance("@mozilla.org/sound;1");
    if (mSoundInterface && !mNotFoundSoundURL.EqualsLiteral("beep")) {
      mSoundInterface->Init();
    }
  }

#ifdef XP_WIN
  // After each keystroke, ensure sound object is destroyed, to free up memory 
  // allocated for error sound, otherwise Windows' nsISound impl 
  // holds onto the last played sound, using up memory.
  mSoundInterface = nullptr;
#endif

  int32_t bufferLength = mTypeAheadBuffer.Length();

  mTypeAheadBuffer = aSearchString;

  bool isFirstVisiblePreferred = false;

  // --------- Initialize find if 1st char ----------
  if (bufferLength == 0) {
    // If you can see the selection (not collapsed or thru caret browsing),
    // or if already focused on a page element, start there.
    // Otherwise we're going to start at the first visible element
    bool isSelectionCollapsed = true;
    if (selection)
      selection->GetIsCollapsed(&isSelectionCollapsed);

    // If true, we will scan from top left of visible area
    // If false, we will scan from start of selection
    isFirstVisiblePreferred = !atEnd && !mCaretBrowsingOn && isSelectionCollapsed;
    if (isFirstVisiblePreferred) {
      // Get the focused content. If there is a focused node, ensure the
      // selection is at that point. Otherwise, we will just want to start
      // from the caret position or the beginning of the document.
      nsPresContext* presContext = presShell->GetPresContext();
      NS_ENSURE_TRUE(presContext, NS_OK);

      nsCOMPtr<nsIDocument> document =
        do_QueryInterface(presShell->GetDocument());
      if (!document)
        return NS_ERROR_UNEXPECTED;

      nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID);
      if (fm) {
        nsPIDOMWindowOuter* window = document->GetWindow();
        nsCOMPtr<nsIDOMElement> focusedElement;
        nsCOMPtr<mozIDOMWindowProxy> focusedWindow;
        fm->GetFocusedElementForWindow(window, false,
                                       getter_AddRefs(focusedWindow),
                                       getter_AddRefs(focusedElement));
        // If the root element is focused, then it's actually the document
        // that has the focus, so ignore this.
        if (focusedElement &&
            !SameCOMIdentity(focusedElement, document->GetRootElement())) {
          fm->MoveCaretToFocus(window);
          isFirstVisiblePreferred = false;
        }
      }
    }
  }

  // ----------- Find the text! ---------------------
  // Beware! This may flush notifications via synchronous
  // ScrollSelectionIntoView.
  nsresult rv = FindItNow(nullptr, aLinksOnly, isFirstVisiblePreferred,
                          false, aResult);

  // ---------Handle success or failure ---------------
  if (NS_SUCCEEDED(rv)) {
    if (mTypeAheadBuffer.Length() == 1) {
      // If first letter, store where the first find succeeded
      // (mStartFindRange)

      mStartFindRange = nullptr;
      if (selection) {
        nsCOMPtr<nsIDOMRange> startFindRange;
        selection->GetRangeAt(0, getter_AddRefs(startFindRange));
        if (startFindRange)
          startFindRange->CloneRange(getter_AddRefs(mStartFindRange));
      }
    }
  }
  else {
    // Error sound
    if (mTypeAheadBuffer.Length() > mLastFindLength)
      PlayNotFoundSound();
  }

  SaveFind();
  return NS_OK;
}
Ejemplo n.º 15
0
NS_IMETHODIMP
nsFaviconService::ReplaceFaviconDataFromDataURL(nsIURI* aFaviconURI,
                                               const nsAString& aDataURL,
                                               PRTime aExpiration,
                                               nsIPrincipal* aLoadingPrincipal)
{
  NS_ENSURE_ARG(aFaviconURI);
  NS_ENSURE_TRUE(aDataURL.Length() > 0, NS_ERROR_INVALID_ARG);
  if (aExpiration == 0) {
    aExpiration = PR_Now() + MAX_FAVICON_EXPIRATION;
  }

  nsCOMPtr<nsIURI> dataURI;
  nsresult rv = NS_NewURI(getter_AddRefs(dataURI), aDataURL);
  NS_ENSURE_SUCCESS(rv, rv);

  // Use the data: protocol handler to convert the data.
  nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv);
  NS_ENSURE_SUCCESS(rv, rv);
  nsCOMPtr<nsIProtocolHandler> protocolHandler;
  rv = ioService->GetProtocolHandler("data", getter_AddRefs(protocolHandler));
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<nsIPrincipal> loadingPrincipal = aLoadingPrincipal;
  MOZ_ASSERT(loadingPrincipal, "please provide aLoadingPrincipal for this favicon");
  if (!loadingPrincipal) {
    // Bug 1227289 : Let's default to the systemPrincipal if no loadingPrincipal is provided
    // so addons not providing a loadingPrincipal do not break in release builds.
    const char16_t* params[] = {
      MOZ_UTF16("nsFaviconService::ReplaceFaviconDataFromDataURL()"),
      MOZ_UTF16("nsFaviconService::ReplaceFaviconDataFromDataURL(..., [optional aLoadingPrincipal])")
    };
    nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
                                    NS_LITERAL_CSTRING("Security by Default"),
                                    nullptr, // aDocument
                                    nsContentUtils::eNECKO_PROPERTIES,
                                    "APIDeprecationWarning",
                                    params, ArrayLength(params));

    loadingPrincipal = nsContentUtils::GetSystemPrincipal();
  }
  NS_ENSURE_TRUE(loadingPrincipal, NS_ERROR_FAILURE);

  nsCOMPtr<nsILoadInfo> loadInfo =
    new mozilla::LoadInfo(loadingPrincipal,
                          nullptr, // aTriggeringPrincipal
                          nullptr, // aLoadingNode
                          nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS |
                          nsILoadInfo::SEC_ALLOW_CHROME |
                          nsILoadInfo::SEC_DISALLOW_SCRIPT,
                          nsIContentPolicy::TYPE_INTERNAL_IMAGE);

  nsCOMPtr<nsIChannel> channel;
  rv = protocolHandler->NewChannel2(dataURI, loadInfo, getter_AddRefs(channel));
  NS_ENSURE_SUCCESS(rv, rv);

  // Blocking stream is OK for data URIs.
  nsCOMPtr<nsIInputStream> stream;
  rv = channel->Open2(getter_AddRefs(stream));
  NS_ENSURE_SUCCESS(rv, rv);

  uint64_t available64;
  rv = stream->Available(&available64);
  NS_ENSURE_SUCCESS(rv, rv);
  if (available64 == 0 || available64 > UINT32_MAX / sizeof(uint8_t))
    return NS_ERROR_FILE_TOO_BIG;
  uint32_t available = (uint32_t)available64;

  // Read all the decoded data.
  uint8_t* buffer = static_cast<uint8_t*>
                               (moz_xmalloc(sizeof(uint8_t) * available));
  if (!buffer)
    return NS_ERROR_OUT_OF_MEMORY;
  uint32_t numRead;
  rv = stream->Read(TO_CHARBUFFER(buffer), available, &numRead);
  if (NS_FAILED(rv) || numRead != available) {
    free(buffer);
    return rv;
  }

  nsAutoCString mimeType;
  rv = channel->GetContentType(mimeType);
  if (NS_FAILED(rv)) {
    free(buffer);
    return rv;
  }

  // ReplaceFaviconData can now do the dirty work.
  rv = ReplaceFaviconData(aFaviconURI, buffer, available, mimeType, aExpiration);
  free(buffer);
  NS_ENSURE_SUCCESS(rv, rv);

  return NS_OK;
}
Ejemplo n.º 16
0
void
nsHTMLContentSerializer::AppendAndTranslateEntities(const nsAString& aStr,
                                                     nsAString& aOutputStr)
{
  if (mBodyOnly && !mInBody) {
    return;
  }

  if (mDisableEntityEncoding) {
    aOutputStr.Append(aStr);
    return;
  }

  bool nonBasicEntities =
    !!(mFlags & (nsIDocumentEncoder::OutputEncodeLatin1Entities |
                 nsIDocumentEncoder::OutputEncodeHTMLEntities   |
                 nsIDocumentEncoder::OutputEncodeW3CEntities));

  if (!nonBasicEntities &&
      (mFlags & (nsIDocumentEncoder::OutputEncodeBasicEntities))) {
    const char **entityTable = mInAttribute ? kAttrEntities : kEntities;
    PRUint32 start = 0;
    const PRUint32 len = aStr.Length();
    for (PRUint32 i = 0; i < len; ++i) {
      const char* entity = nsnull;
      i = FindNextBasicEntity(aStr, len, i, entityTable, &entity);
      PRUint32 normalTextLen = i - start; 
      if (normalTextLen) {
        aOutputStr.Append(Substring(aStr, start, normalTextLen));
      }
      if (entity) {
        aOutputStr.AppendASCII(entity);
        start = i + 1;
      }
    }
    return;
  } else if (nonBasicEntities) {
    nsIParserService* parserService = nsContentUtils::GetParserService();

    if (!parserService) {
      NS_ERROR("Can't get parser service");
      return;
    }

    nsReadingIterator<PRUnichar> done_reading;
    aStr.EndReading(done_reading);

    // for each chunk of |aString|...
    PRUint32 advanceLength = 0;
    nsReadingIterator<PRUnichar> iter;

    const char **entityTable = mInAttribute ? kAttrEntities : kEntities;
    nsCAutoString entityReplacement;

    for (aStr.BeginReading(iter);
         iter != done_reading;
         iter.advance(PRInt32(advanceLength))) {
      PRUint32 fragmentLength = iter.size_forward();
      PRUint32 lengthReplaced = 0; // the number of UTF-16 codepoints
                                    //  replaced by a particular entity
      const PRUnichar* c = iter.get();
      const PRUnichar* fragmentStart = c;
      const PRUnichar* fragmentEnd = c + fragmentLength;
      const char* entityText = nsnull;
      const char* fullConstEntityText = nsnull;
      char* fullEntityText = nsnull;

      advanceLength = 0;
      // for each character in this chunk, check if it
      // needs to be replaced
      for (; c < fragmentEnd; c++, advanceLength++) {
        PRUnichar val = *c;
        if (val <= kValNBSP && entityTable[val]) {
          fullConstEntityText = entityTable[val];
          break;
        } else if (val > 127 &&
                  ((val < 256 &&
                    mFlags & nsIDocumentEncoder::OutputEncodeLatin1Entities) ||
                    mFlags & nsIDocumentEncoder::OutputEncodeHTMLEntities)) {
          entityReplacement.Truncate();
          parserService->HTMLConvertUnicodeToEntity(val, entityReplacement);

          if (!entityReplacement.IsEmpty()) {
            entityText = entityReplacement.get();
            break;
          }
        }
        else if (val > 127 &&
                  mFlags & nsIDocumentEncoder::OutputEncodeW3CEntities &&
                  mEntityConverter) {
          if (NS_IS_HIGH_SURROGATE(val) &&
              c + 1 < fragmentEnd &&
              NS_IS_LOW_SURROGATE(*(c + 1))) {
            PRUint32 valUTF32 = SURROGATE_TO_UCS4(val, *(++c));
            if (NS_SUCCEEDED(mEntityConverter->ConvertUTF32ToEntity(valUTF32,
                              nsIEntityConverter::entityW3C, &fullEntityText))) {
              lengthReplaced = 2;
              break;
            }
            else {
              advanceLength++;
            }
          }
          else if (NS_SUCCEEDED(mEntityConverter->ConvertToEntity(val,
                                nsIEntityConverter::entityW3C, 
                                &fullEntityText))) {
            lengthReplaced = 1;
            break;
          }
        }
      }

      aOutputStr.Append(fragmentStart, advanceLength);
      if (entityText) {
        aOutputStr.Append(PRUnichar('&'));
        AppendASCIItoUTF16(entityText, aOutputStr);
        aOutputStr.Append(PRUnichar(';'));
        advanceLength++;
      }
      else if (fullConstEntityText) {
        aOutputStr.AppendASCII(fullConstEntityText);
        ++advanceLength;
      }
      // if it comes from nsIEntityConverter, it already has '&' and ';'
      else if (fullEntityText) {
        AppendASCIItoUTF16(fullEntityText, aOutputStr);
        nsMemory::Free(fullEntityText);
        advanceLength += lengthReplaced;
      }
    }
  } else {
    nsXMLContentSerializer::AppendAndTranslateEntities(aStr, aOutputStr);
  }
}
Ejemplo n.º 17
0
NS_IMETHODIMP
mozSpellChecker::Replace(const nsAString &aOldWord, const nsAString &aNewWord, bool aAllOccurrences)
{
  if(!mConverter)
    return NS_ERROR_NULL_POINTER;

  nsAutoString newWord(aNewWord); // sigh

  if(aAllOccurrences){
    int32_t selOffset;
    int32_t startBlock,currentBlock,currOffset;
    int32_t begin,end;
    bool done;
    nsresult result;
    nsAutoString str;

    // find out where we are
    result = SetupDoc(&selOffset);
    if(NS_FAILED(result))
      return result;
    result = GetCurrentBlockIndex(mTextServicesDocument,&startBlock);
    if(NS_FAILED(result))
      return result;

    //start at the beginning
    result = mTextServicesDocument->FirstBlock();
    currOffset=0;
    currentBlock = 0;
    while (NS_SUCCEEDED(mTextServicesDocument->IsDone(&done)) && !done) {
      result = mTextServicesDocument->GetCurrentTextBlock(&str);
      do {
        result = mConverter->FindNextWord(str.get(),str.Length(),currOffset,&begin,&end);
        if (NS_SUCCEEDED(result) && (begin != -1)) {
          if (aOldWord.Equals(Substring(str, begin, end-begin))) {
            // if we are before the current selection point but in the same
            // block move the selection point forwards
            if (currentBlock == startBlock && begin < selOffset) {
              selOffset +=
                int32_t(aNewWord.Length()) - int32_t(aOldWord.Length());
              if (selOffset < begin) {
                selOffset=begin;
              }
            }
            mTextServicesDocument->SetSelection(begin, end-begin);
            mTextServicesDocument->InsertText(&newWord);
            mTextServicesDocument->GetCurrentTextBlock(&str);
            end += (aNewWord.Length() - aOldWord.Length());  // recursion was cute in GEB, not here.
          }
        }
        currOffset = end;
      } while(currOffset != -1);
      mTextServicesDocument->NextBlock();
      currentBlock++;
      currOffset=0;
    }

    // We are done replacing.  Put the selection point back where we found  it (or equivalent);
    result = mTextServicesDocument->FirstBlock();
    currentBlock = 0;
    while(NS_SUCCEEDED(mTextServicesDocument->IsDone(&done)) && !done &&
          currentBlock < startBlock) {
      mTextServicesDocument->NextBlock();
    }

//After we have moved to the block where the first occurrence of replace was done, put the
//selection to the next word following it. In case there is no word following it i.e if it happens
//to be the last word in that block, then move to the next block and put the selection to the
//first word in that block, otherwise when the Setupdoc() is called, it queries the LastSelectedBlock()
//and the selection offset of the last occurrence of the replaced word is taken instead of the first
//occurrence and things get messed up as reported in the bug 244969

    if (NS_SUCCEEDED(mTextServicesDocument->IsDone(&done)) && !done){
      nsString str;
      result = mTextServicesDocument->GetCurrentTextBlock(&str);
      result = mConverter->FindNextWord(str.get(),str.Length(),selOffset,&begin,&end);
      if (end == -1) {
        mTextServicesDocument->NextBlock();
        selOffset=0;
        result = mTextServicesDocument->GetCurrentTextBlock(&str);
        result = mConverter->FindNextWord(str.get(),str.Length(),selOffset,&begin,&end);
        mTextServicesDocument->SetSelection(begin, 0);
      } else {
        mTextServicesDocument->SetSelection(begin, 0);
      }
    }
  } else {
    mTextServicesDocument->InsertText(&newWord);
  }
  return NS_OK;
}
Ejemplo n.º 18
0
NS_IMETHODIMP
nsFaviconService::ReplaceFaviconDataFromDataURL(nsIURI* aFaviconURI,
                                               const nsAString& aDataURL,
                                               PRTime aExpiration)
{
  NS_ENSURE_ARG(aFaviconURI);
  NS_ENSURE_TRUE(aDataURL.Length() > 0, NS_ERROR_INVALID_ARG);
  if (aExpiration == 0) {
    aExpiration = PR_Now() + MAX_FAVICON_EXPIRATION;
  }

  nsCOMPtr<nsIURI> dataURI;
  nsresult rv = NS_NewURI(getter_AddRefs(dataURI), aDataURL);
  NS_ENSURE_SUCCESS(rv, rv);

  // Use the data: protocol handler to convert the data.
  nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv);
  NS_ENSURE_SUCCESS(rv, rv);
  nsCOMPtr<nsIProtocolHandler> protocolHandler;
  rv = ioService->GetProtocolHandler("data", getter_AddRefs(protocolHandler));
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<nsILoadInfo> loadInfo =
    new mozilla::LoadInfo(nsContentUtils::GetSystemPrincipal(),
                          nullptr, // aTriggeringPrincipal
                          nullptr, // aLoadingNode
                          nsILoadInfo::SEC_NORMAL,
                          nsIContentPolicy::TYPE_IMAGE);

  nsCOMPtr<nsIChannel> channel;
  rv = protocolHandler->NewChannel2(dataURI, loadInfo, getter_AddRefs(channel));
  NS_ENSURE_SUCCESS(rv, rv);

  // Blocking stream is OK for data URIs.
  nsCOMPtr<nsIInputStream> stream;
  rv = channel->Open(getter_AddRefs(stream));
  NS_ENSURE_SUCCESS(rv, rv);

  uint64_t available64;
  rv = stream->Available(&available64);
  NS_ENSURE_SUCCESS(rv, rv);
  if (available64 == 0 || available64 > UINT32_MAX / sizeof(uint8_t))
    return NS_ERROR_FILE_TOO_BIG;
  uint32_t available = (uint32_t)available64;

  // Read all the decoded data.
  uint8_t* buffer = static_cast<uint8_t*>
                               (moz_xmalloc(sizeof(uint8_t) * available));
  if (!buffer)
    return NS_ERROR_OUT_OF_MEMORY;
  uint32_t numRead;
  rv = stream->Read(TO_CHARBUFFER(buffer), available, &numRead);
  if (NS_FAILED(rv) || numRead != available) {
    free(buffer);
    return rv;
  }

  nsAutoCString mimeType;
  rv = channel->GetContentType(mimeType);
  if (NS_FAILED(rv)) {
    free(buffer);
    return rv;
  }

  // ReplaceFaviconData can now do the dirty work.
  rv = ReplaceFaviconData(aFaviconURI, buffer, available, mimeType, aExpiration);
  free(buffer);
  NS_ENSURE_SUCCESS(rv, rv);

  return NS_OK;
}
Ejemplo n.º 19
0
/* static */ void
SVGPathSegUtils::GetValueAsString(const float* aSeg, nsAString& aValue)
{
  // Adding new seg type? Is the formatting below acceptable for the new types?
  PR_STATIC_ASSERT(NS_SVG_PATH_SEG_LAST_VALID_TYPE ==
                     nsIDOMSVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL);
  PR_STATIC_ASSERT(NS_SVG_PATH_SEG_MAX_ARGS == 7);

  PRUint32 type = DecodeType(aSeg[0]);
  PRUnichar typeAsChar = GetPathSegTypeAsLetter(type);

  // Special case arcs:
  if (IsArcType(type)) {
    bool largeArcFlag = aSeg[4] != 0.0f;
    bool sweepFlag = aSeg[5] != 0.0f;
    nsTextFormatter::ssprintf(aValue,
                              NS_LITERAL_STRING("%c%g,%g %g %d,%d %g,%g").get(),
                              typeAsChar, aSeg[1], aSeg[2], aSeg[3],
                              largeArcFlag, sweepFlag, aSeg[6], aSeg[7]);
  } else {

    switch (ArgCountForType(type)) {
    case 0:
      aValue = typeAsChar;
      break;

    case 1:
      nsTextFormatter::ssprintf(aValue, NS_LITERAL_STRING("%c%g").get(),
                                typeAsChar, aSeg[1]);
      break;

    case 2:
      nsTextFormatter::ssprintf(aValue, NS_LITERAL_STRING("%c%g,%g").get(),
                                typeAsChar, aSeg[1], aSeg[2]);
      break;

    case 4:
      nsTextFormatter::ssprintf(aValue, NS_LITERAL_STRING("%c%g,%g %g,%g").get(),
                                typeAsChar, aSeg[1], aSeg[2], aSeg[3], aSeg[4]);
      break;

    case 6:
      nsTextFormatter::ssprintf(aValue,
                                NS_LITERAL_STRING("%c%g,%g %g,%g %g,%g").get(),
                                typeAsChar, aSeg[1], aSeg[2], aSeg[3], aSeg[4],
                                aSeg[5], aSeg[6]);
      break;

    default:
      NS_ABORT_IF_FALSE(false, "Unknown segment type");
      aValue = NS_LITERAL_STRING("<unknown-segment-type>").get();
      return;
    }
  }
  
  // nsTextFormatter::ssprintf is one of the nsTextFormatter methods that
  // randomly appends '\0' to its output string, which means that the length
  // of the output string is one too long. We need to manually remove that '\0'
  // until nsTextFormatter is fixed.
  //
  if (aValue[aValue.Length() - 1] == PRUnichar('\0')) {
    aValue.SetLength(aValue.Length() - 1);
  }
}
Ejemplo n.º 20
0
/* static */ nsresult
SRICheck::IntegrityMetadata(const nsAString& aMetadataList,
                            const nsIDocument* aDocument,
                            SRIMetadata* outMetadata)
{
  NS_ENSURE_ARG_POINTER(outMetadata);
  NS_ENSURE_ARG_POINTER(aDocument);
  MOZ_ASSERT(outMetadata->IsEmpty()); // caller must pass empty metadata

  if (!Preferences::GetBool("security.sri.enable", false)) {
    SRILOG(("SRICheck::IntegrityMetadata, sri is disabled (pref)"));
    return NS_ERROR_SRI_DISABLED;
  }

  // put a reasonable bound on the length of the metadata
  NS_ConvertUTF16toUTF8 metadataList(aMetadataList);
  if (metadataList.Length() > SRICheck::MAX_METADATA_LENGTH) {
    metadataList.Truncate(SRICheck::MAX_METADATA_LENGTH);
  }
  MOZ_ASSERT(metadataList.Length() <= aMetadataList.Length());

  // the integrity attribute is a list of whitespace-separated hashes
  // and options so we need to look at them one by one and pick the
  // strongest (valid) one
  nsCWhitespaceTokenizer tokenizer(metadataList);
  nsAutoCString token;
  for (uint32_t i=0; tokenizer.hasMoreTokens() &&
         i < SRICheck::MAX_METADATA_TOKENS; ++i) {
    token = tokenizer.nextToken();

    SRIMetadata metadata(token);
    if (metadata.IsMalformed()) {
      NS_ConvertUTF8toUTF16 tokenUTF16(token);
      const char16_t* params[] = { tokenUTF16.get() };
      nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
                                      NS_LITERAL_CSTRING("Sub-resource Integrity"),
                                      aDocument,
                                      nsContentUtils::eSECURITY_PROPERTIES,
                                      "MalformedIntegrityHash",
                                      params, ArrayLength(params));
    } else if (!metadata.IsAlgorithmSupported()) {
      nsAutoCString alg;
      metadata.GetAlgorithm(&alg);
      NS_ConvertUTF8toUTF16 algUTF16(alg);
      const char16_t* params[] = { algUTF16.get() };
      nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
                                      NS_LITERAL_CSTRING("Sub-resource Integrity"),
                                      aDocument,
                                      nsContentUtils::eSECURITY_PROPERTIES,
                                      "UnsupportedHashAlg",
                                      params, ArrayLength(params));
    }

    nsAutoCString alg1, alg2;
    if (MOZ_LOG_TEST(SRILogHelper::GetSriLog(), mozilla::LogLevel::Debug)) {
      outMetadata->GetAlgorithm(&alg1);
      metadata.GetAlgorithm(&alg2);
    }
    if (*outMetadata == metadata) {
      SRILOG(("SRICheck::IntegrityMetadata, alg '%s' is the same as '%s'",
              alg1.get(), alg2.get()));
      *outMetadata += metadata; // add new hash to strongest metadata
    } else if (*outMetadata < metadata) {
      SRILOG(("SRICheck::IntegrityMetadata, alg '%s' is weaker than '%s'",
              alg1.get(), alg2.get()));
      *outMetadata = metadata; // replace strongest metadata with current
    }
  }

  if (MOZ_LOG_TEST(SRILogHelper::GetSriLog(), mozilla::LogLevel::Debug)) {
    if (outMetadata->IsValid()) {
      nsAutoCString alg;
      outMetadata->GetAlgorithm(&alg);
      SRILOG(("SRICheck::IntegrityMetadata, using a '%s' hash", alg.get()));
    } else if (outMetadata->IsEmpty()) {
      SRILOG(("SRICheck::IntegrityMetadata, no metadata"));
    } else {
      SRILOG(("SRICheck::IntegrityMetadata, no valid metadata found"));
    }
  }
  return NS_OK;
}
Ejemplo n.º 21
0
 explicit StringUnicharInputStream(const nsAString& aString) :
   mString(aString), mPos(0), mLen(aString.Length()) { }
Ejemplo n.º 22
0
NS_IMETHODIMP
nsRecentBadCertsService::GetRecentBadCert(const nsAString & aHostNameWithPort, 
                                          nsISSLStatus **aStatus)
{
  NS_ENSURE_ARG_POINTER(aStatus);
  if (!aHostNameWithPort.Length())
    return NS_ERROR_INVALID_ARG;

  *aStatus = nullptr;
  nsRefPtr<nsSSLStatus> status = new nsSSLStatus();
  if (!status)
    return NS_ERROR_OUT_OF_MEMORY;

  SECItem foundDER;
  foundDER.len = 0;
  foundDER.data = nullptr;

  bool isDomainMismatch = false;
  bool isNotValidAtThisTime = false;
  bool isUntrusted = false;

  {
    ReentrantMonitorAutoEnter lock(monitor);
    for (size_t i=0; i<const_recently_seen_list_size; ++i) {
      if (mCerts[i].mHostWithPort.Equals(aHostNameWithPort)) {
        SECStatus srv = SECITEM_CopyItem(nullptr, &foundDER, &mCerts[i].mDERCert);
        if (srv != SECSuccess)
          return NS_ERROR_OUT_OF_MEMORY;

        isDomainMismatch = mCerts[i].isDomainMismatch;
        isNotValidAtThisTime = mCerts[i].isNotValidAtThisTime;
        isUntrusted = mCerts[i].isUntrusted;
      }
    }
  }

  if (foundDER.len) {
    CERTCertificate *nssCert;
    CERTCertDBHandle *certdb = CERT_GetDefaultCertDB();
    nssCert = CERT_FindCertByDERCert(certdb, &foundDER);
    if (!nssCert) 
      nssCert = CERT_NewTempCertificate(certdb, &foundDER,
                                        nullptr, // no nickname
                                        false, // not perm
                                        true); // copy der

    SECITEM_FreeItem(&foundDER, false);

    if (!nssCert)
      return NS_ERROR_FAILURE;

    status->mServerCert = nsNSSCertificate::Create(nssCert);
    CERT_DestroyCertificate(nssCert);

    status->mHaveCertErrorBits = true;
    status->mIsDomainMismatch = isDomainMismatch;
    status->mIsNotValidAtThisTime = isNotValidAtThisTime;
    status->mIsUntrusted = isUntrusted;

    *aStatus = status;
    NS_IF_ADDREF(*aStatus);
  }

  return NS_OK;
}
Ejemplo n.º 23
0
bool nsTextAddress::GetField(const nsAString &aLine, int32_t index,
                             nsString &field, char16_t delim) {
  bool result = false;
  int32_t pos = 0;
  int32_t maxLen = aLine.Length();
  char16_t tab = char16_t('\t');
  char16_t doubleQuote = char16_t('"');

  field.Truncate();

  if (delim == tab) tab = 0;

  while (index && (pos < maxLen)) {
    while (((aLine[pos] == char16_t(' ')) || (aLine[pos] == tab)) &&
           (pos < maxLen)) {
      pos++;
    }
    if (pos >= maxLen) break;
    if (aLine[pos] == doubleQuote) {
      do {
        pos++;
        if (((pos + 1) < maxLen) && (aLine[pos] == doubleQuote) &&
            (aLine[pos + 1] == doubleQuote)) {
          pos += 2;
        }
      } while ((pos < maxLen) && (aLine[pos] != doubleQuote));
      if (pos < maxLen) pos++;
    }
    if (pos >= maxLen) break;

    while ((pos < maxLen) && (aLine[pos] != delim)) pos++;

    if (pos >= maxLen) break;

    index--;
    pos++;
  }

  if (pos >= maxLen) return result;

  result = true;

  while ((pos < maxLen) && ((aLine[pos] == ' ') || (aLine[pos] == tab))) pos++;

  int32_t fLen = 0;
  int32_t startPos = pos;
  bool quoted = false;
  if (aLine[pos] == '"') {
    startPos++;
    fLen = -1;
    do {
      pos++;
      fLen++;
      if (((pos + 1) < maxLen) && (aLine[pos] == doubleQuote) &&
          (aLine[pos + 1] == doubleQuote)) {
        quoted = true;
        pos += 2;
        fLen += 2;
      }
    } while ((pos < maxLen) && (aLine[pos] != doubleQuote));
  } else {
    while ((pos < maxLen) && (aLine[pos] != delim)) {
      pos++;
      fLen++;
    }
  }

  if (!fLen) {
    return result;
  }

  field.Append(nsDependentSubstring(aLine, startPos, fLen));
  field.Trim(kWhitespace);

  if (quoted) {
    int32_t offset = field.Find("\"\"");
    while (offset != -1) {
      field.Cut(offset, 1);
      offset = MsgFind(field, "\"\"", false, offset + 1);
    }
  }

  return result;
}
Ejemplo n.º 24
0
NS_IMETHODIMP
nsDOMOfflineResourceList::MozAdd(const nsAString& aURI)
{
  if (IS_CHILD_PROCESS()) 
    return NS_ERROR_NOT_IMPLEMENTED;

  nsresult rv = Init();
  NS_ENSURE_SUCCESS(rv, rv);

  if (!nsContentUtils::OfflineAppAllowed(mDocumentURI)) {
    return NS_ERROR_DOM_SECURITY_ERR;
  }

  nsCOMPtr<nsIApplicationCache> appCache = GetDocumentAppCache();
  if (!appCache) {
    return NS_ERROR_DOM_INVALID_STATE_ERR;
  }

  if (aURI.Length() > MAX_URI_LENGTH) return NS_ERROR_DOM_BAD_URI;

  // this will fail if the URI is not absolute
  nsCOMPtr<nsIURI> requestedURI;
  rv = NS_NewURI(getter_AddRefs(requestedURI), aURI);
  NS_ENSURE_SUCCESS(rv, rv);

  nsAutoCString scheme;
  rv = requestedURI->GetScheme(scheme);
  NS_ENSURE_SUCCESS(rv, rv);

  bool match;
  rv = mManifestURI->SchemeIs(scheme.get(), &match);
  NS_ENSURE_SUCCESS(rv, rv);

  if (!match) {
    return NS_ERROR_DOM_SECURITY_ERR;
  }

  uint32_t length;
  rv = GetMozLength(&length);
  NS_ENSURE_SUCCESS(rv, rv);
  uint32_t maxEntries =
    Preferences::GetUint(kMaxEntriesPref, DEFAULT_MAX_ENTRIES);

  if (length > maxEntries) return NS_ERROR_NOT_AVAILABLE;

  ClearCachedKeys();

  nsCOMPtr<nsIOfflineCacheUpdate> update =
    do_CreateInstance(NS_OFFLINECACHEUPDATE_CONTRACTID, &rv);
  NS_ENSURE_SUCCESS(rv, rv);

  nsAutoCString clientID;
  rv = appCache->GetClientID(clientID);
  NS_ENSURE_SUCCESS(rv, rv);

  rv = update->InitPartial(mManifestURI, clientID, mDocumentURI);
  NS_ENSURE_SUCCESS(rv, rv);

  rv = update->AddDynamicURI(requestedURI);
  NS_ENSURE_SUCCESS(rv, rv);

  rv = update->Schedule();
  NS_ENSURE_SUCCESS(rv, rv);

  return NS_OK;
}
Ejemplo n.º 25
0
NS_IMETHODIMP
nsHtml5Parser::ParseHtml5Fragment(const nsAString& aSourceBuffer,
                                  nsIContent* aTargetNode,
                                  nsIAtom* aContextLocalName,
                                  PRInt32 aContextNamespace,
                                  PRBool aQuirks,
                                  PRBool aPreventScriptExecution)
{
  nsIDocument* doc = aTargetNode->GetOwnerDoc();
  NS_ENSURE_TRUE(doc, NS_ERROR_NOT_AVAILABLE);
  
  nsIURI* uri = doc->GetDocumentURI();
  NS_ENSURE_TRUE(uri, NS_ERROR_NOT_AVAILABLE);

  mExecutor->EnableFragmentMode(aPreventScriptExecution);

  Initialize(doc, uri, nsnull, nsnull);

  mExecutor->SetParser(this);
  mExecutor->SetNodeInfoManager(doc->NodeInfoManager());

  nsIContent* target = aTargetNode;
  mTreeBuilder->setFragmentContext(aContextLocalName,
                                   aContextNamespace,
                                   &target,
                                   aQuirks);

#ifdef DEBUG
  if (!aPreventScriptExecution) {
    nsCOMPtr<nsIDOMDocumentFragment> domFrag = do_QueryInterface(aTargetNode);
    NS_ASSERTION(domFrag,
        "If script execution isn't prevented, must parse to DOM fragment.");
  }
#endif

  NS_PRECONDITION(!mExecutor->HasStarted(),
                  "Tried to start parse without initializing the parser.");
  mTreeBuilder->setScriptingEnabled(mExecutor->IsScriptEnabled());
  mTokenizer->start();
  mExecutor->Start(); // Don't call WillBuildModel in fragment case
  if (!aSourceBuffer.IsEmpty()) {
    PRBool lastWasCR = PR_FALSE;
    nsHtml5UTF16Buffer buffer(aSourceBuffer.Length());
    memcpy(buffer.getBuffer(),
           aSourceBuffer.BeginReading(),
           aSourceBuffer.Length() * sizeof(PRUnichar));
    buffer.setEnd(aSourceBuffer.Length());
    while (buffer.hasMore()) {
      buffer.adjust(lastWasCR);
      lastWasCR = PR_FALSE;
      if (buffer.hasMore()) {
        lastWasCR = mTokenizer->tokenizeBuffer(&buffer);
        if (mTreeBuilder->HasScript()) {
          // Flush on each script, because the execution prevention code
          // can handle at most one script per flush.
          mTreeBuilder->Flush(); // Move ops to the executor
          mExecutor->FlushDocumentWrite(); // run the ops
        }
      }
    }
  }
  mTokenizer->eof();
  mTreeBuilder->StreamEnded();
  mTreeBuilder->Flush();
  mExecutor->FlushDocumentWrite();
  mTokenizer->end();
  mExecutor->DropParserAndPerfHint();
  mExecutor->DropHeldElements();
  mTreeBuilder->DropHandles();
  mAtomTable.Clear();
  return NS_OK;
}
Ejemplo n.º 26
0
RangedPtr<const char16_t>
SVGContentUtils::GetEndRangedPtr(const nsAString& aString)
{
  return RangedPtr<const char16_t>(aString.Data() + aString.Length(),
                                    aString.Data(), aString.Length());
}
nsresult
nsXHTMLContentSerializer::EscapeURI(nsIContent* aContent, const nsAString& aURI, nsAString& aEscapedURI)
{
  // URL escape %xx cannot be used in JS.
  // No escaping if the scheme is 'javascript'.
  if (IsJavaScript(aContent, nsGkAtoms::href, kNameSpaceID_None, aURI)) {
    aEscapedURI = aURI;
    return NS_OK;
  }

  // nsITextToSubURI does charset convert plus uri escape
  // This is needed to convert to a document charset which is needed to support existing browsers.
  // But we eventually want to use UTF-8 instead of a document charset, then the code would be much simpler.
  // See HTML 4.01 spec, "Appendix B.2.1 Non-ASCII characters in URI attribute values"
  nsCOMPtr<nsITextToSubURI> textToSubURI;
  nsAutoString uri(aURI); // in order to use FindCharInSet()
  nsresult rv = NS_OK;

  if (!mCharset.IsEmpty() && !IsASCII(uri)) {
    textToSubURI = do_GetService(NS_ITEXTTOSUBURI_CONTRACTID, &rv);
    NS_ENSURE_SUCCESS(rv, rv);
  }

  PRInt32 start = 0;
  PRInt32 end;
  nsAutoString part;
  nsXPIDLCString escapedURI;
  aEscapedURI.Truncate(0);

  // Loop and escape parts by avoiding escaping reserved characters
  // (and '%', '#', as well as '[' and ']' for IPv6 address literals).
  while ((end = uri.FindCharInSet("%#;/?:@&=+$,[]", start)) != -1) {
    part = Substring(aURI, start, (end-start));
    if (textToSubURI && !IsASCII(part)) {
      rv = textToSubURI->ConvertAndEscape(mCharset.get(), part.get(), getter_Copies(escapedURI));
      NS_ENSURE_SUCCESS(rv, rv);
    }
    else {
      escapedURI.Adopt(nsEscape(NS_ConvertUTF16toUTF8(part).get(), url_Path));
    }
    AppendASCIItoUTF16(escapedURI, aEscapedURI);

    // Append a reserved character without escaping.
    part = Substring(aURI, end, 1);
    aEscapedURI.Append(part);
    start = end + 1;
  }

  if (start < (PRInt32) aURI.Length()) {
    // Escape the remaining part.
    part = Substring(aURI, start, aURI.Length()-start);
    if (textToSubURI) {
      rv = textToSubURI->ConvertAndEscape(mCharset.get(), part.get(), getter_Copies(escapedURI));
      NS_ENSURE_SUCCESS(rv, rv);
    }
    else {
      escapedURI.Adopt(nsEscape(NS_ConvertUTF16toUTF8(part).get(), url_Path));
    }
    AppendASCIItoUTF16(escapedURI, aEscapedURI);
  }

  return rv;
}
Ejemplo n.º 28
0
/*
 * Converts the value of the given double to a String, and places
 * The result into the destination String.
 * @return the given dest string
 */
void Double::toString(double aValue, nsAString& aDest)
{

    // check for special cases

    if (isNaN(aValue)) {
        aDest.AppendLiteral("NaN");
        return;
    }
    if (isInfinite(aValue)) {
        if (aValue < 0)
            aDest.Append(PRUnichar('-'));
        aDest.AppendLiteral("Infinity");
        return;
    }

    // Mantissa length is 17, so this is plenty
    const int buflen = 20;
    char buf[buflen];

    PRIntn intDigits, sign;
    char* endp;
    PR_dtoa(aValue, 0, 0, &intDigits, &sign, &endp, buf, buflen - 1);

    // compute length
    PRInt32 length = endp - buf;
    if (length > intDigits) {
        // decimal point needed
        ++length;
        if (intDigits < 1) {
            // leading zeros, -intDigits + 1
            length += 1 - intDigits;
        }
    }
    else {
        // trailing zeros, total length given by intDigits
        length = intDigits;
    }
    if (aValue < 0)
        ++length;
    // grow the string
    PRUint32 oldlength = aDest.Length();
    if (!EnsureStringLength(aDest, oldlength + length))
        return; // out of memory
    nsAString::iterator dest;
    aDest.BeginWriting(dest).advance(PRInt32(oldlength));
    if (aValue < 0) {
        *dest = '-'; ++dest;
    }
    int i;
    // leading zeros
    if (intDigits < 1) {
        *dest = '0'; ++dest;
        *dest = '.'; ++dest;
        for (i = 0; i > intDigits; --i) {
            *dest = '0'; ++dest;
        }
    }
    // mantissa
    int firstlen = PR_MIN(intDigits, endp - buf);
    for (i = 0; i < firstlen; i++) {
        *dest = buf[i]; ++dest;
    }
    if (i < endp - buf) {
        if (i > 0) {
            *dest = '.'; ++dest;
        }
        for (; i < endp - buf; i++) {
            *dest = buf[i]; ++dest;
        }
    }
    // trailing zeros
    for (; i < intDigits; i++) {
        *dest = '0'; ++dest;
    }
}
Ejemplo n.º 29
0
nsresult
nsIndexedToHTML::FormatInputStream(nsIRequest* aRequest, nsISupports *aContext, const nsAString &aBuffer) 
{
    nsresult rv = NS_OK;

    // set up unicode encoder
    if (!mUnicodeEncoder) {
      nsXPIDLCString encoding;
      rv = mParser->GetEncoding(getter_Copies(encoding));
      if (NS_SUCCEEDED(rv)) {
        nsCOMPtr<nsICharsetConverterManager> charsetConverterManager;
        charsetConverterManager = do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &rv);
        rv = charsetConverterManager->GetUnicodeEncoder(encoding.get(), 
                                                          getter_AddRefs(mUnicodeEncoder));
        if (NS_SUCCEEDED(rv))
            rv = mUnicodeEncoder->SetOutputErrorBehavior(nsIUnicodeEncoder::kOnError_Replace, 
                                                       nullptr, (char16_t)'?');
      }
    }

    // convert the data with unicode encoder
    char *buffer = nullptr;
    int32_t dstLength;
    if (NS_SUCCEEDED(rv)) {
      int32_t unicharLength = aBuffer.Length();
      rv = mUnicodeEncoder->GetMaxLength(PromiseFlatString(aBuffer).get(), 
                                         unicharLength, &dstLength);
      if (NS_SUCCEEDED(rv)) {
        buffer = (char *) moz_malloc(dstLength);
        NS_ENSURE_TRUE(buffer, NS_ERROR_OUT_OF_MEMORY);

        rv = mUnicodeEncoder->Convert(PromiseFlatString(aBuffer).get(), &unicharLength, 
                                      buffer, &dstLength);
        if (NS_SUCCEEDED(rv)) {
          int32_t finLen = 0;
          rv = mUnicodeEncoder->Finish(buffer + dstLength, &finLen);
          if (NS_SUCCEEDED(rv))
            dstLength += finLen;
        }
      }
    }

    // if conversion error then fallback to UTF-8
    if (NS_FAILED(rv)) {
      rv = NS_OK;
      if (buffer) {
        nsMemory::Free(buffer);
        buffer = nullptr;
      }
    }

    nsCOMPtr<nsIInputStream> inputData;
    if (buffer) {
      rv = NS_NewCStringInputStream(getter_AddRefs(inputData), Substring(buffer, dstLength));
      nsMemory::Free(buffer);
      NS_ENSURE_SUCCESS(rv, rv);
      rv = mListener->OnDataAvailable(aRequest, aContext,
                                      inputData, 0, dstLength);
    }
    else {
      NS_ConvertUTF16toUTF8 utf8Buffer(aBuffer);
      rv = NS_NewCStringInputStream(getter_AddRefs(inputData), utf8Buffer);
      NS_ENSURE_SUCCESS(rv, rv);
      rv = mListener->OnDataAvailable(aRequest, aContext,
                                      inputData, 0, utf8Buffer.Length());
    }
    return (rv);
}
bool
TruncateComments(const nsAString& src, nsAString* const out)
{
    const size_t dstByteCount = src.Length() * sizeof(src[0]);
    const UniqueBuffer dst(malloc(dstByteCount));
    if (!dst)
        return false;

    auto srcItr = src.BeginReading();
    const auto srcEnd = src.EndReading();
    const auto dstBegin = (decltype(src[0])*)dst.get();
    auto dstItr = dstBegin;

    const auto fnEmitUntil = [&](const decltype(srcItr)& nextSrcItr) {
        while (srcItr != nextSrcItr) {
            *dstItr = *srcItr;
            ++srcItr;
            ++dstItr;
        }
    };

    const auto fnFindSoonestOf = [&](const nsString* needles, size_t needleCount,
                                     size_t* const out_foundId)
    {
        auto foundItr = srcItr;
        while (foundItr != srcEnd) {
            const auto haystack = Substring(foundItr, srcEnd);
            for (size_t i = 0; i < needleCount; i++) {
                if (StringBeginsWith(haystack, needles[i])) {
                    *out_foundId = i;
                    return foundItr;
                }
            }
            ++foundItr;
        }
        *out_foundId = needleCount;
        return foundItr;
    };

    ////

    const nsString commentBeginnings[] = { NS_LITERAL_STRING("//"),
                                           NS_LITERAL_STRING("/*"),
                                           nsString() }; // Final empty string for "found
                                                         // nothing".
    const nsString lineCommentEndings[] = { NS_LITERAL_STRING("\\\n"),
                                            NS_LITERAL_STRING("\n"),
                                            nsString() };
    const nsString blockCommentEndings[] = { NS_LITERAL_STRING("\n"),
                                             NS_LITERAL_STRING("*/"),
                                             nsString() };

    while (srcItr != srcEnd) {
        size_t foundId;
        fnEmitUntil( fnFindSoonestOf(commentBeginnings, 2, &foundId) );
        fnEmitUntil(srcItr + commentBeginnings[foundId].Length()); // Final empty string
                                                                   // allows us to skip
                                                                   // forward here
                                                                   // unconditionally.
        switch (foundId) {
        case 0: // line comment
            while (true) {
                size_t endId;
                srcItr = fnFindSoonestOf(lineCommentEndings, 2, &endId);
                fnEmitUntil(srcItr + lineCommentEndings[endId].Length());
                if (endId == 0)
                    continue;
                break;
            }
            break;

        case 1: // block comment
            while (true) {
                size_t endId;
                srcItr = fnFindSoonestOf(blockCommentEndings, 2, &endId);
                fnEmitUntil(srcItr + blockCommentEndings[endId].Length());
                if (endId == 0)
                    continue;
                break;
            }
            break;

        default: // not found
            break;
        }
    }

    MOZ_ASSERT((dstBegin+1) - dstBegin == 1);
    const uint32_t dstCharLen = dstItr - dstBegin;
    if (!out->Assign(dstBegin, dstCharLen, mozilla::fallible))
        return false;

    return true;
}