Skip to content
This repository has been archived by the owner on Dec 11, 2019. It is now read-only.

Commit

Permalink
Merge pull request #12471 from bsclifton/fix-bookmark-export
Browse files Browse the repository at this point in the history
Properly encode entries when saving bookmarks to a file
  • Loading branch information
NejcZdovc committed Jan 3, 2018
2 parents eefeaad + 8044892 commit ab25724
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 27 deletions.
26 changes: 22 additions & 4 deletions app/browser/bookmarksExporter.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,27 @@ const showDialog = (state) => {
if (fileName) {
personal = createBookmarkArray(state)
other = createBookmarkArray(state, -1, false)
fs.writeFileSync(fileName, createBookmarkHTML(personal, other))
try {
fs.writeFileSync(fileName, createBookmarkHTML(personal, other))
} catch (e) {
console.log('Error exporting bookmarks: ', e)
}
}
})
}

const encodeHref = (string) => {
return (string || '')
.replace(/"/g, '"')
}

const encodeTitle = (string) => {
return (string || '')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
}

const createBookmarkArray = (state, parentFolderId = 0, first = true, depth = 1) => {
const bookmarks = bookmarksState.getBookmarksWithFolders(state, parentFolderId)
let payload = []
Expand All @@ -60,10 +76,12 @@ const createBookmarkArray = (state, parentFolderId = 0, first = true, depth = 1)

for (let site of bookmarks) {
if (bookmarkUtil.isBookmark(site) && site.get('location')) {
title = site.get('title', site.get('location'))
payload.push(`${indentNext}<DT><A HREF="${site.get('location')}">${title}</A>`)
title = encodeTitle(site.get('title', site.get('location')))
const href = encodeHref(site.get('location'))
payload.push(`${indentNext}<DT><A HREF="${href}">${title}</A>`)
} else if (bookmarkFoldersUtil.isFolder(site)) {
payload.push(`${indentNext}<DT><H3>${site.get('title')}</H3>`)
title = encodeTitle(site.get('title'))
payload.push(`${indentNext}<DT><H3>${title}</H3>`)
payload = payload.concat(createBookmarkArray(state, site.get('folderId'), true, (depth + 1)))
}
}
Expand Down
6 changes: 3 additions & 3 deletions test/fixtures/bookmarkExport.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ <H1>Bookmarks</H1>
</DL><p>
<DT><H3>folder 3</H3>
<DL><p>
<DT><A HREF="https://brave.com/5">Website 5</A>
<DT><A HREF="https://brave.com/5">Title &lt;/A&gt; with &quot;characters&quot; in it</A>
</DL><p>
</DL><p>
<DT><A HREF="https://brave.com/6">Website 6</A>
<DT><A HREF="javascript:(function(){var x,n,nD,z,i; function htmlEscape(s){s=s.replace(/&/g,'&amp;');s=s.replace(/>/g,'&gt;');s=s.replace(/</g,'&lt;');return s;} function attrQuoteEscape(s){s=s.replace(/&/g,'&amp;'); s=s.replace(/&quot;/g, '&quot;');return s;} x=prompt(&quot;show links with this word/phrase in link text or target url (leave blank to list all links):&quot;, &quot;&quot;); n=0; if(x!=null) { x=x.toLowerCase(); nD = window.open().document; nD.writeln('<html><head><title>Links containing &quot;'+htmlEscape(x)+'&quot;</title><base target=&quot;_blank&quot;></head><body>'); nD.writeln('Links on <a href=&quot;'+attrQuoteEscape(location.href)+'&quot;>'+htmlEscape(location.href)+'</a><br> with link text or target url containing &quot;' + htmlEscape(x) + '&quot;<br><hr>'); z = document.links; for (i = 0; i < z.length; ++i) { if ((z[i].innerHTML && z[i].innerHTML.toLowerCase().indexOf(x) != -1) || z[i].href.toLowerCase().indexOf(x) != -1 ) { nD.writeln(++n + '. <a href=&quot;' + attrQuoteEscape(z[i].href) + '&quot;>' + (z[i].innerHTML || htmlEscape(z[i].href)) + '</a><br>'); } } nD.writeln('<hr></body></html>'); nD.close(); } })();">Bookmarklet example</A>
<DT><H3>folder 4</H3>
<DL><p>
</DL><p>
Expand All @@ -34,4 +34,4 @@ <H1>Bookmarks</H1>
<DT><H3>folder 6</H3>
<DL><p>
</DL><p>
</DL><p>
</DL><p>
44 changes: 24 additions & 20 deletions test/unit/app/browser/exportBookmarksTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,15 @@ describe('Bookmarks export', function () {
type: siteTags.BOOKMARK
},
'https://brave.com/5|0|3': {
title: 'Website 5',
title: 'Title </A> with "characters" in it',
location: 'https://brave.com/5',
parentFolderId: 3,
key: 'https://brave.com/5|0|3',
type: siteTags.BOOKMARK
},
'https://brave.com/6|0|0': {
title: 'Website 6',
location: 'https://brave.com/6',
title: 'Bookmarklet example',
location: 'javascript:(function(){var x,n,nD,z,i; function htmlEscape(s){s=s.replace(/&/g,\'&amp;\');s=s.replace(/>/g,\'&gt;\');s=s.replace(/</g,\'&lt;\');return s;} function attrQuoteEscape(s){s=s.replace(/&/g,\'&amp;\'); s=s.replace(/"/g, \'&quot;\');return s;} x=prompt("show links with this word/phrase in link text or target url (leave blank to list all links):", ""); n=0; if(x!=null) { x=x.toLowerCase(); nD = window.open().document; nD.writeln(\'<html><head><title>Links containing "\'+htmlEscape(x)+\'"</title><base target="_blank"></head><body>\'); nD.writeln(\'Links on <a href="\'+attrQuoteEscape(location.href)+\'">\'+htmlEscape(location.href)+\'</a><br> with link text or target url containing &quot;\' + htmlEscape(x) + \'&quot;<br><hr>\'); z = document.links; for (i = 0; i < z.length; ++i) { if ((z[i].innerHTML && z[i].innerHTML.toLowerCase().indexOf(x) != -1) || z[i].href.toLowerCase().indexOf(x) != -1 ) { nD.writeln(++n + \'. <a href="\' + attrQuoteEscape(z[i].href) + \'">\' + (z[i].innerHTML || htmlEscape(z[i].href)) + \'</a><br>\'); } } nD.writeln(\'<hr></body></html>\'); nD.close(); } })();',
parentFolderId: 0,
key: 'https://brave.com/6|0|0',
type: siteTags.BOOKMARK
Expand Down Expand Up @@ -163,10 +163,10 @@ describe('Bookmarks export', function () {
' </DL><p>',
' <DT><H3>folder 3</H3>',
' <DL><p>',
' <DT><A HREF="https://brave.com/5">Website 5</A>',
' <DT><A HREF="https://brave.com/5">Title &lt;/A&gt; with &quot;characters&quot; in it</A>',
' </DL><p>',
' </DL><p>',
' <DT><A HREF="https://brave.com/6">Website 6</A>',
' <DT><A HREF="javascript:(function(){var x,n,nD,z,i; function htmlEscape(s){s=s.replace(/&/g,\'&amp;\');s=s.replace(/>/g,\'&gt;\');s=s.replace(/</g,\'&lt;\');return s;} function attrQuoteEscape(s){s=s.replace(/&/g,\'&amp;\'); s=s.replace(/&quot;/g, \'&quot;\');return s;} x=prompt(&quot;show links with this word/phrase in link text or target url (leave blank to list all links):&quot;, &quot;&quot;); n=0; if(x!=null) { x=x.toLowerCase(); nD = window.open().document; nD.writeln(\'<html><head><title>Links containing &quot;\'+htmlEscape(x)+\'&quot;</title><base target=&quot;_blank&quot;></head><body>\'); nD.writeln(\'Links on <a href=&quot;\'+attrQuoteEscape(location.href)+\'&quot;>\'+htmlEscape(location.href)+\'</a><br> with link text or target url containing &quot;\' + htmlEscape(x) + \'&quot;<br><hr>\'); z = document.links; for (i = 0; i < z.length; ++i) { if ((z[i].innerHTML && z[i].innerHTML.toLowerCase().indexOf(x) != -1) || z[i].href.toLowerCase().indexOf(x) != -1 ) { nD.writeln(++n + \'. <a href=&quot;\' + attrQuoteEscape(z[i].href) + \'&quot;>\' + (z[i].innerHTML || htmlEscape(z[i].href)) + \'</a><br>\'); } } nD.writeln(\'<hr></body></html>\'); nD.close(); } })();">Bookmarklet example</A>',
' <DT><H3>folder 4</H3>',
' <DL><p>',
' </DL><p>',
Expand All @@ -185,25 +185,29 @@ describe('Bookmarks export', function () {
' </DL><p>'
]

it('personal array', function () {
const gen = exporter.createBookmarkArray(state)
assert.deepEqual(gen, personalArray)
})
describe('createBookmarkArray', function () {
it('serializes the regular bookmarks', function () {
const gen = exporter.createBookmarkArray(state)
assert.deepEqual(gen, personalArray)
})

it('other array', function () {
const gen = exporter.createBookmarkArray(state, -1, false)
assert.deepEqual(gen, otherArray)
it('serializes the "other" bookmarks', function () {
const gen = exporter.createBookmarkArray(state, -1, false)
assert.deepEqual(gen, otherArray)
})
})

it('generated html', function () {
const personal = exporter.createBookmarkArray(state)
const other = exporter.createBookmarkArray(state, -1, false)
let result = exporter.createBookmarkHTML(personal, other)
let expected = fs.readFileSync('./test/fixtures/bookmarkExport.html', 'utf8')
describe('createBookmarkHTML', function () {
it('generates an HTML response', function () {
const personal = exporter.createBookmarkArray(state)
const other = exporter.createBookmarkArray(state, -1, false)
let result = exporter.createBookmarkHTML(personal, other)
let expected = fs.readFileSync('./test/fixtures/bookmarkExport.html', 'utf8')

result = result.replace(/\s+/g, ' ')
expected = expected.replace(/\s+/g, ' ')
result = result.replace(/\s+/g, ' ').trim()
expected = expected.replace(/\s+/g, ' ').trim()

assert.equal(result, expected)
assert.equal(result, expected)
})
})
})

0 comments on commit ab25724

Please sign in to comment.