nsIRDFResource *aNodeType, nsCOMPtr<nsIRDFResource> &bookmarkNode)
nsIRDFResource *nodeType, nsCOMPtr<nsIRDFResource> &bookmarkNode)
BookmarkParser::ParseBookmarkInfo(BookmarkField *fields, PRBool isBookmarkFlag,                const nsString &aLine, const nsCOMPtr<nsIRDFContainer> &aContainer,                nsIRDFResource *aNodeType, nsCOMPtr<nsIRDFResource> &bookmarkNode){    NS_PRECONDITION(aContainer != nsnull, "null ptr");    if (! aContainer)        return NS_ERROR_NULL_POINTER;    bookmarkNode = nsnull;    PRInt32     lineLen = aLine.Length();    PRInt32     attrStart=0;    if (isBookmarkFlag == PR_TRUE)    {        attrStart = aLine.Find(kOpenAnchor, PR_TRUE, attrStart);        if (attrStart < 0)  return NS_ERROR_UNEXPECTED;        attrStart += sizeof(kOpenAnchor)-1;    }    else    {        attrStart = aLine.Find(kOpenHeading, PR_TRUE, attrStart);        if (attrStart < 0)  return NS_ERROR_UNEXPECTED;        attrStart += sizeof(kOpenHeading)-1;    }    // free up any allocated data in field table BEFORE processing    for (BookmarkField *preField = fields; preField->mName; ++preField)    {        NS_IF_RELEASE(preField->mValue);    }    // loop over attributes    while((attrStart < lineLen) && (aLine[attrStart] != '>'))    {        while(nsCRT::IsAsciiSpace(aLine[attrStart]))   ++attrStart;        PRBool  fieldFound = PR_FALSE;        nsAutoString id;        id.AssignWithConversion(kIDEquals);        for (BookmarkField *field = fields; field->mName; ++field)        {            nsAutoString name;            name.AssignWithConversion(field->mName);            if (mIsImportOperation && name.Equals(id))                 // For import operations, we don't want to save the unique                // identifier for folders, because this can cause bugs like                 // 74969 (importing duplicate bookmark folder hierachy causes                 // bookmarks file to grow infinitely).                continue;            if (field->mProperty == kNC_BookmarksToolbarFolder                && mFoundPersonalToolbarFolder)                // We don't want to assert a BTF arc twice.                continue;              if (aLine.Find(field->mName, PR_TRUE, attrStart, 1) == attrStart)            {                attrStart += strlen(field->mName);                // skip to terminating quote of string                PRInt32 termQuote = aLine.FindChar(PRUnichar('\"'), attrStart);                if (termQuote > attrStart)                {                    // process data                    nsAutoString    data;                    aLine.Mid(data, attrStart, termQuote-attrStart);                    attrStart = termQuote + 1;                    fieldFound = PR_TRUE;                    if (!data.IsEmpty())                    {                        // XXX Bug 58421 We should not ever hit this assertion                        NS_ASSERTION(!field->mValue, "Field already has a value");                        // but prevent a leak if we do hit it                        NS_IF_RELEASE(field->mValue);                        nsresult rv = (*field->mParse)(field->mProperty, data, &field->mValue);                        if (NS_FAILED(rv)) break;                    }                }                break;            }        }        if (fieldFound == PR_FALSE)        {            // skip to next attribute            while((attrStart < lineLen) && (aLine[attrStart] != '>') &&                (!nsCRT::IsAsciiSpace(aLine[attrStart])))            {                ++attrStart;            }        }    }    nsresult    rv;    // Note: the first entry MUST be the ID/resource of the bookmark    nsCOMPtr<nsIRDFResource> bookmark = do_QueryInterface(fields[0].mValue);    if (!bookmark)    {        // We've never seen this bookmark/folder before. Assign it an anonymous ID        rv = gRDF->GetAnonymousResource(getter_AddRefs(bookmark));        NS_ASSERTION(NS_SUCCEEDED(rv), "unable to create anonymous resource for folder");    }    if (bookmark)    {        const char* bookmarkURI;        bookmark->GetValueConst(&bookmarkURI);        bookmarkNode = bookmark;        // assert appropriate node type        PRBool isIEFavoriteRoot = PR_FALSE;        if (!mIEFavoritesRoot.IsEmpty())        {            if (!nsCRT::strcmp(mIEFavoritesRoot.get(), bookmarkURI))            {                mFoundIEFavoritesRoot = PR_TRUE;                isIEFavoriteRoot = PR_TRUE;            }        }        if ((isIEFavoriteRoot == PR_TRUE) || ((aNodeType == kNC_IEFavorite) && (isBookmarkFlag == PR_FALSE)))        {            rv = mDataSource->Assert(bookmark, kRDF_type, kNC_IEFavoriteFolder, PR_TRUE);        }        else if (aNodeType == kNC_IEFavorite ||                 aNodeType == kNC_IEFavoriteFolder ||                 aNodeType == kNC_BookmarkSeparator)        {            rv = mDataSource->Assert(bookmark, kRDF_type, aNodeType, PR_TRUE);        }        // process data        for (BookmarkField *field = fields; field->mName; ++field)        {            if (field->mValue && field->mProperty)            {                updateAtom(mDataSource, bookmark, field->mProperty,                           field->mValue, nsnull);                if (field->mProperty == kNC_BookmarksToolbarFolder)                    mFoundPersonalToolbarFolder = PR_TRUE;            }        }        // look for bookmark name (and unescape)        if (aLine[attrStart] == '>')        {            PRInt32 nameEnd;            if (isBookmarkFlag == PR_TRUE)                nameEnd = aLine.Find(kCloseAnchor, PR_TRUE, ++attrStart);            else                nameEnd = aLine.Find(kCloseHeading, PR_TRUE, ++attrStart);            if (nameEnd > attrStart)            {                nsAutoString    name;                aLine.Mid(name, attrStart, nameEnd-attrStart);                if (!name.IsEmpty())                {                    Unescape(name);                    nsCOMPtr<nsIRDFNode>    nameNode;                    rv = ParseLiteral(kNC_Name, name, getter_AddRefs(nameNode));                    if (NS_SUCCEEDED(rv) && nameNode)                        updateAtom(mDataSource, bookmark, kNC_Name, nameNode, nsnull);                }            }        }        if (isBookmarkFlag == PR_FALSE)        {            rv = gRDFC->MakeSeq(mDataSource, bookmark, nsnull);            NS_ASSERTION(NS_SUCCEEDED(rv), "unable to make new folder as sequence");            if (NS_SUCCEEDED(rv))            {                // And now recursively parse the rest of the file...                rv = Parse(bookmark, aNodeType);                NS_ASSERTION(NS_SUCCEEDED(rv), "unable to parse bookmarks");            }        }        // prevent duplicates                                                               PRInt32 aIndex;                                                                     nsCOMPtr<nsIRDFResource> containerRes;        aContainer->GetResource(getter_AddRefs(containerRes));        if (containerRes && NS_SUCCEEDED(gRDFC->IndexOf(mDataSource, containerRes, bookmark, &aIndex)) &&                             (aIndex < 0))                                                                   {                                                                                     // The last thing we do is add the bookmark to the container.                     // This ensures the minimal amount of reflow.                                     rv = aContainer->AppendElement(bookmark);                                         NS_ASSERTION(NS_SUCCEEDED(rv), "unable to add bookmark to container");          }          }    // free up any allocated data in field table AFTER processing    for (BookmarkField *postField = fields; postField->mName; ++postField)    {        NS_IF_RELEASE(postField->mValue);    }    return NS_OK;}