Skip to content

Commit

Permalink
Merge pull request #70 from TangoMan75/master
Browse files Browse the repository at this point in the history
  • Loading branch information
ArthurHoaro authored Jan 31, 2021
2 parents 76ff8d7 + 7017391 commit 5b2eb8d
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 42 deletions.
8 changes: 7 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
composer.lock
vendor
logs/
!.gitkeep

/logs/

###> squizlabs/php_codesniffer ###
/.phpcs-cache
/phpcs.xml
###< squizlabs/php_codesniffer ###
82 changes: 46 additions & 36 deletions NetscapeBookmarkParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -120,56 +120,66 @@ public function parseString(string $bookmarkString): array

$lines = explode("\n", $this->sanitizeString($bookmarkString));

foreach ($lines as $line_no => $line) {
foreach ($lines as $lineNumber => $line) {
$item = [];

$this->logger->info('PARSING LINE #' . $line_no);
$this->logger->debug('[#' . $line_no . '] Content: ' . $line);
if (preg_match('/^<h\d.*>(.*)<\/h\d>/i', $line, $m1)) {
$this->logger->info('PARSING LINE #' . $lineNumber);
$this->logger->debug('[#' . $lineNumber . '] Content: ' . $line);
if (preg_match('/^<h\d.*>(.*)<\/h\d>/i', $line, $header)) {
// a header is matched:
// - links may be grouped in a (sub-)folder
// - append the header's content to the folder tags
$tag = static::sanitizeTags($m1[1]);
$tag = static::sanitizeTags($header[1]);

$groupedFolderTags[] = $tag;
$folderTags = static::flattenTagsList($groupedFolderTags);
$this->logger->debug('[#' . $line_no . '] Header found: ' . implode(' ', $tag));
$this->logger->debug('[#' . $lineNumber . '] Header found: ' . implode(' ', $tag));
continue;
} elseif (preg_match('/^<\/DL>/i', $line)) {
// </DL> matched: stop using header value
$tag = array_pop($groupedFolderTags);
$folderTags = static::flattenTagsList($groupedFolderTags);
$this->logger->debug('[#' . $line_no . '] Header ended: ' . implode(' ', $tag ?? []));
$this->logger->debug('[#' . $lineNumber . '] Header ended: ' . implode(' ', $tag ?? []));
continue;
}

if (preg_match('/<a/i', $line, $m2)) {
$this->logger->debug('[#' . $line_no . '] Link found');
if (preg_match('/href="(.*?)"/i', $line, $m3)) {
$item['uri'] = $m3[1];
$this->logger->debug('[#' . $line_no . '] URL found: ' . $m3[1]);
if (preg_match('/<a/i', $line)) {
$this->logger->debug('[#' . $lineNumber . '] Link found');
if (preg_match('/href="(.*?)"/i', $line, $href)) {
$item['uri'] = $href[1];
$this->logger->debug('[#' . $lineNumber . '] URL found: ' . $href[1]);
} else {
$item['uri'] = '';
$this->logger->debug('[#' . $line_no . '] Empty URL');
$this->logger->debug('[#' . $lineNumber . '] Empty URL');
}

if (preg_match('/<a.*?[^br]>(.*?)<\/a>/i', $line, $m4)) {
$item['title'] = $m4[1];
$this->logger->debug('[#' . $line_no . '] Title found: ' . $m4[1]);
if (preg_match('/icon="(.*?)"/i', $line, $icon)) {
$item['icon'] = $icon[1];
$this->logger->debug('[#' . $lineNumber . '] ICON found: ' . $href[1]);
} else {
$item['icon'] = '';
$this->logger->debug('[#' . $lineNumber . '] Empty ICON');
}

if (preg_match('/<a.*?[^br]>(.*?)<\/a>/i', $line, $title)) {
$item['title'] = $title[1];
$this->logger->debug('[#' . $lineNumber . '] Title found: ' . $title[1]);
} else {
$item['title'] = 'untitled';
$this->logger->debug('[#' . $line_no . '] Empty title');
$this->logger->debug('[#' . $lineNumber . '] Empty title');
}

if (preg_match('/(description|note)="(.*?)"/i', $line, $m5)) {
$item['note'] = $m5[2];
$this->logger->debug('[#' . $line_no . '] Content found: ' . substr($m5[2], 0, 50) . '...');
} elseif (preg_match('/<dd>(.*?)$/i', $line, $m6)) {
$item['note'] = str_replace('<br>', "\n", $m6[1]);
$this->logger->debug('[#' . $line_no . '] Content found: ' . substr($m6[1], 0, 50) . '...');
if (preg_match('/(description|note)="(.*?)"/i', $line, $description)) {
$item['note'] = $description[2];
$this->logger->debug(
'[#' . $lineNumber . '] Content found: ' . substr($description[2], 0, 50) . '...'
);
} elseif (preg_match('/<dd>(.*?)$/i', $line, $note)) {
$item['note'] = str_replace('<br>', "\n", $note[1]);
$this->logger->debug('[#' . $lineNumber . '] Content found: ' . substr($note[1], 0, 50) . '...');
} else {
$item['note'] = '';
$this->logger->debug('[#' . $line_no . '] Empty content');
$this->logger->debug('[#' . $lineNumber . '] Empty content');
}

$tags = [];
Expand All @@ -180,32 +190,32 @@ public function parseString(string $bookmarkString): array
$tags = array_merge($tags, $folderTags);
}

if (preg_match('/(tags?|labels?|folders?)="(.*?)"/i', $line, $m7)) {
$separator = strpos($m7[2], ',') !== false ? ',' : ' ';
if (preg_match('/(tags?|labels?|folders?)="(.*?)"/i', $line, $labels)) {
$separator = strpos($labels[2], ',') !== false ? ',' : ' ';
$tags = array_merge(
$tags,
static::splitTagString($m7[2], $separator)
static::splitTagString($labels[2], $separator)
);
}
$item['tags'] = $tags;
$this->logger->debug('[#' . $line_no . '] Tag list: ' . implode(' ', $item['tags']));
$this->logger->debug('[#' . $lineNumber . '] Tag list: ' . implode(' ', $item['tags']));

if (preg_match('/add_date="(.*?)"/i', $line, $m8)) {
$item['time'] = $this->parseDate($m8[1]);
if (preg_match('/add_date="(.*?)"/i', $line, $addDate)) {
$item['time'] = $this->parseDate($addDate[1]);
} else {
$item['time'] = time();
}
$this->logger->debug('[#' . $line_no . '] Date: ' . $item['time']);
$this->logger->debug('[#' . $lineNumber . '] Date: ' . $item['time']);

if (preg_match('/(public|published|pub)="(.*?)"/i', $line, $m9)) {
$item['pub'] = $this->parseBoolean($m9[2]) ? 1 : 0;
} elseif (preg_match('/(private|shared)="(.*?)"/i', $line, $m10)) {
$item['pub'] = $this->parseBoolean($m10[2]) ? 0 : 1;
if (preg_match('/(public|published|pub)="(.*?)"/i', $line, $public)) {
$item['pub'] = $this->parseBoolean($public[2]) ? 1 : 0;
} elseif (preg_match('/(private|shared)="(.*?)"/i', $line, $private)) {
$item['pub'] = $this->parseBoolean($private[2]) ? 0 : 1;
} else {
$item['pub'] = $this->defaultPub;
}
$this->logger->debug(
'[#' . $line_no . '] Visibility: ' . ($item['pub'] ? 'public' : 'private')
'[#' . $lineNumber . '] Visibility: ' . ($item['pub'] ? 'public' : 'private')
);

$items[] = $item;
Expand Down
11 changes: 8 additions & 3 deletions phpcs.xml.dist
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
<?xml version="1.0"?>
<ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="PHP_CodeSniffer" xsi:noNamespaceSchemaLocation="phpcs.xsd">

<!-- Documentation: https://github.com/squizlabs/PHP_CodeSniffer -->

<arg name="basepath" value="."/>
<arg name="cache" value=".phpcs-cache"/>
<arg name="colors"/>
<arg name="extensions" value="php"/>

<file>NetscapeBookmarkParser.php</file>
<file>tests</file>

<rule ref="PSR12" />

<rule ref="Generic.PHP.RequireStrictTypes.MissingDeclaration" />
<rule ref="Generic.Arrays.DisallowLongArraySyntax" />
<rule ref="Generic.Arrays.DisallowLongArraySyntax"/>

<file>NetscapeBookmarkParser.php</file>
<file>tests</file>
</ruleset>
17 changes: 17 additions & 0 deletions tests/ParseChromiumBookmarksTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,23 @@ protected function tearDown(): void
@unlink(LoggerTestsUtils::getLogFile());
}

public function testParseChromiumBookmarkShouldIncludeIcon()
{
$parser = new NetscapeBookmarkParser(false, null, '1');
$bkm = $parser->parseFile('tests/input/chromium_flat.htm');

// https://github.com/squizlabs/PHP_CodeSniffer/wiki/Advanced-Usage#ignoring-parts-of-a-file
// phpcs:disable Generic.Files.LineLength
$this->assertEquals('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACeElEQVQ4jX1TW0hUURRd+8yZuaPOdQxNiSiipAdjICISNhBFVIIRiBoYRP9BSSBFBXPnoyj666O+AoOEmMmpNBUKHSQRiTCDKYqeX6KBzuOa4zzu2X3M+NbW1zn77LX3WntzgI1gsFh1Z6Z1sTzkuggzgUgBAB4nSt1SqThRFADn33jzAvmEPU/jDXA6L1E6tUMxVFn3wg9rIen/TTSxtgitIAsQqf2BeBsT34bNfnlfeeFQZDIqSMhWCe7IZLjt51f3eM5mXiUAoIVtee/yYCgeORCarVrrbG9g5mxVKBbeYE5MAFD9PFpS22c+rHkZ688lhJftBXIN6nvjX04MzXVUPpkpXrQsAOL6vsQFTWLEoWkuAXULzAQML0tsJQsA0hbfTMBRXVpMo95XsRYQMR0eiDaRwh3Fsmm0UY9sspVVkz/UG6uRQnURc7vUiK6RxMXBk3oEYZYY9qvKunP27++6MjAMBSL2BNjx6TOyeb4YO03jx15Hr5OiG9QwGP0l55Oe3sZtSfj9BMNQx9/Mep02WafY6ibBuhDijFOlHwWPlk8BTDD85K1td+savxd2sJovcBW0BIMCPh8DTFn5cYyt9IAg4UGWt3Mi2xkcfvBnkWz4fCgpyBZKwRlqHoq+gA0Tz45sMdb5/w+aw7P3FKOC2t7GdrNl9ZBAyGXZ7yfT88lpAG6HoFSCCADcu8rU9NQ0KgDAVVRkqcwVZpxKWdxIAHB+ZHKnUtpdaYOHhC3DSoFZ5UZPAEGAAGYiAitpKf4gNefVzjrXFK1cU0P/t+KS8gqHjjmYJqDrLphmTrKuAyaAvwupVI93q7m04qXDJt91QzCLRfI/LI8pZq5PEwYAAAAASUVORK5CYII=', $bkm[0]['icon']);
// phpcs:enable

$parser = new NetscapeBookmarkParser(true, null, '1');
$bkm = $parser->parseFile('tests/input/chromium_nested.htm');
// phpcs:disable Generic.Files.LineLength
$this->assertEquals('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAB2UlEQVQ4jYWTz2uScRzHXz5uQfp46i6uQ4QhQf4DgzpFPVtKlxmNrkG2npOSY1rgcX/ARoeCdliroHaJLYg8RoeQIDoEQqvUkqRNI/V5dzAft/mjL3zh++HL683788vzfI71Cye4jIeB87sNjsA3OfiHYPMjjzzKomFwowWL70+DMUHu5FvMI8NFjHFwemWbzOoWSx+i7P4ZIuABYxR8Y/kppmni8/m4ufxkpIhxGL724hjplW1CoSm+ff3Czs5ngsEgmdUtUu8iAyLGfth6COtvfpDP5/lerTI7e4kZa4ZKpUy73eLO/VeDTpRDexl0dgp1y4JM09SthQU3zmaX1Gg0JEmlUkl2PKpft5FyiObiQThgmioUCnIcR+lUSrZty3Ec1et1VStlNZtN1Wo12fGo9jLI6FXTdSThdDq9LrmnWCxy0bKo138iCfSv+24Kx/su/H6/riQSbpxMJhUIBAToVDgsO3ZGu70UlOs+Dov0biQSUaVcVjqVEqDpEC6sHPIo13faaIG1Bi8/uXPCxuMNYrE4tVqN6+fD3DtXxr9vKif299Q3Cc/m+iIC5q/O4/V6ef3g7gAMcMDBKCfTIdhMMAB3BcYsk7UGHWc0jMDzv3WW4OiYdf4LzLYa1HClursAAAAASUVORK5CYII=', $bkm[1]['icon']);
// phpcs:enable
}

/**
* Parse flat Chromium bookmarks (no directories)
*/
Expand Down
6 changes: 4 additions & 2 deletions tests/ParseShaarliBookmarksTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,8 @@ public function testParseLegacy()
'note' => 'simple on/off button',
'tags' => ['css'],
'time' => 1470640652,
'pub' => 0
'pub' => 0,
'icon' => ''
],
$bkm[0]
);
Expand All @@ -221,7 +222,8 @@ public function testParseLegacy()
'note' => '',
'tags' => ['apache'],
'time' => 1469950052,
'pub' => 1
'pub' => 1,
'icon' => ''
],
$bkm[1]
);
Expand Down

0 comments on commit 5b2eb8d

Please sign in to comment.