diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 3869463..0000000 --- a/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -config.inc.php -*.bak \ No newline at end of file diff --git a/.vscode/sftp.json b/.vscode/sftp.json new file mode 100644 index 0000000..6b1ac8e --- /dev/null +++ b/.vscode/sftp.json @@ -0,0 +1,27 @@ +{ + "name": "Fruchtzwerg", + "host": "192.168.188.4", + "protocol": "sftp", + "port": 22, + "username": "root", + "remotePath": "/media/stick/www/roundcube/plugins/syncmarks", + "uploadOnSave": true, + "agent": "pageant", + "downloadOnOpen": true, + "syncOption":{ "delete": true, + "skipCreate": false, + "ignoreExisting": false, + "update" : true + }, + "remoteTimeOffsetInHours": 1, + "syncMode": "full", + "watcher": { + "files": "**/*", + "autoUpload": true, + "autoDelete": true + }, + "ignore": [ + ".vscode", + ".git" + ] +} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..43f5ea1 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,46 @@ +### v2.2.0 +- Added notifications for pushed links + +### v2.1.2 +- Moved the get_bookmarks function from init to click to speed up inital loading + +### v2.1.1 +- Moved the get_bookmarks function from init to click to speed up inital loading + +### v2.1.0 +- Added support for SyncMarks +- Renamed to Roundcube Sycmarks + +### v2.0.3 +- Added support for Rouncube 1.4 elastic skin + +### v2.0.2 +- changed composer.json + +### v2.0.1 +- Added Chrome Extension + +### v2.0.0 +- The bookmarks saved with DAVMarks AddOn (https://addons.mozilla.org/en-US/firefox/addon/davmarks/) are now supported. Change $config['bookmarks_path'] to the WebDAV url (foldername) to your WebDAV share and $config['bookmarks_filename'] to "bookmarks.json". For the username and password, the Roundcube credentials are used. + +### v1.2.0 +- delete bookmarks with right-click +- retrieve bookmark now via curl instead file_get_contents +- bug fixes + +### v1.1.0 +- Add bookmarks via button +- automatically import bookmarks to Firefox file at Firefox start + +### v1.0.3 + - fix JavaScript for initialization error + - fix css for toolbar button + +### v1.0.2 + - small fix for a error message + +### v1.0.1 + - fixed open links in other tab + +### v1.0.0 + - Initial version \ No newline at end of file diff --git a/bookmarks.png b/bookmarks.png new file mode 100644 index 0000000..f38fa47 Binary files /dev/null and b/bookmarks.png differ diff --git a/composer.json b/composer.json index 35a0a44..516838c 100644 --- a/composer.json +++ b/composer.json @@ -1,25 +1,25 @@ -{ - "name": "offerel/syncmarks", - "description": "Access your Firefox Bookmarks in Roundcube", - "keywords": ["bookmarks","plugin","firefox","roundcube"], - "homepage": "https://github.com/Offerel/roundcube_syncmarks", - "type": "roundcube-plugin", - "license": "AGPL-3.0", - "authors": [ - { - "name": "Offerel", - "homepage": "https://github.com/Offerel", - "role": "Developer" - } - ], - "version": "2.1.1", - "repositories": [ - { - "type": "composer", - "url": "https://plugins.roundcube.net" - } - ], - "require": { - "roundcube/plugin-installer": ">=0.1.6" - } -} +{ + "name": "offerel/syncmarks", + "description": "Access your Firefox Bookmarks in Roundcube", + "keywords": ["bookmarks","plugin","firefox","roundcube"], + "homepage": "https://github.com/Offerel/roundcube_syncmarks", + "type": "roundcube-plugin", + "license": "AGPL-3.0", + "authors": [ + { + "name": "Offerel", + "homepage": "https://github.com/Offerel", + "role": "Developer" + } + ], + "version": "2.2.0", + "repositories": [ + { + "type": "composer", + "url": "https://plugins.roundcube.net" + } + ], + "require": { + "roundcube/plugin-installer": ">=0.1.6" + } +} \ No newline at end of file diff --git a/plugin.min.js b/plugin.min.js deleted file mode 100644 index 38080a9..0000000 --- a/plugin.min.js +++ /dev/null @@ -1 +0,0 @@ -function h_del(t,e){t.preventDefault();var o=rcmail.gettext("bookmarks_del","syncmarks").replace("%b%",e.innerHTML);if(1==confirm(o)){var r=encodeURIComponent(e.href);rcmail.http_post("syncmarks/del_url","_url="+r+"&_format=html")}}function j_del(t,e){t.preventDefault();var o=rcmail.gettext("bookmarks_del","syncmarks").replace("%b%",e.innerHTML);if(1==confirm(o)){var r=encodeURIComponent(e.href);rcmail.http_post("syncmarks/del_url","_url="+r+"&_format=json")}}function bookmarks_cmd(){"300"!=document.getElementById("bookmarkpane").clientWidth?rcmail.http_post("syncmarks/get_bookmarks","_url=2"):document.getElementById("bookmarkpane").style.width="0"}function add_url(){var t=encodeURIComponent(prompt(rcmail.gettext("bookmarks_url","syncmarks")));0li.file{margin-left:29px!important}#bookmarks li{position:relative;margin-left:15px;list-style:none}#bookmarks li.file{margin-left:-1px!important}#bookmarks li.file a{background:url(images/globe.png) no-repeat;background-size:13px;color:#000;padding-left:21px;text-decoration:none;overflow:hidden;text-overflow:ellipsis;font-size:.9em}#bookmarks li input{position:absolute;left:0;margin-left:0;opacity:0;z-index:2;cursor:pointer;height:1em;width:1em;top:0}#bookmarks li input+ol{background:url(images/toggle-small-expand.png) 40px -2px no-repeat;margin:-.938em 0 0 -44px;height:1em;text-overflow:ellipsis}#bookmarks li input+ol>li{display:none;margin-left:-14px!important;padding-left:1px}#bookmarks li label{background:url(images/folder-horizontal.png) 12px 2px no-repeat;cursor:pointer;display:block;padding-left:34px}#bookmarks li input:checked+ol{background:url(images/toggle-small.png) 40px 3px no-repeat;margin:-1.25em 0 0 -44px;padding:1.563em 0 0 80px;height:auto}#bookmarks li input:checked+ol>li{display:block;margin:0 0 .125em}#bookmarks li input:checked+ol>li:last-child{margin:0 0 .063em} \ No newline at end of file +#bmframe{height:100%;border:1px solid #bbb;border-top-left-radius:5px;border-bottom-left-radius:5px;width:100%}#taskbar a.button-bookmarks{background:url(images/bookmark.png) 0 1px/23px no-repeat}#bookmarkpane{position:absolute;transition:1s;top:50px;right:0;bottom:0;margin-bottom:10px;width:0;z-index:100}#add{background:#e1e1e1;bottom:0;position:absolute;height:25px;width:100%;border:thin solid #b2b8bf;right:0;z-index:100;border-bottom-left-radius:5px;border-right:unset;overflow:auto;text-align:center;vertical-align:middle;line-height:25px;cursor:pointer}#add:hover{background:#b7b7b7}#bookmarks{display:block;position:absolute;width:100%;bottom:15px;transition:1s;overflow:auto;top:0;background-color:#eef3fa;padding-top:10px;margin-bottom:10px!important;font-size:1.2em;right:0;border-bottom-left-radius:5px;border-top-left-radius:5px;white-space:nowrap;border:thin solid #b2b8bf;border-right:unset;border-bottom:unset}#bookmarks html{font-family:Verdana,Arial,Helvetica,sans-serif}#bookmarks body,#bookmarks h1,#bookmarks h2,#bookmarks h3,#bookmarks h4,#bookmarks h5,#bookmarks li,#bookmarks p,#bookmarks ul{margin:0;padding:0;background-color:#eef3fa}#bookmarks body{color:#000;margin:0}#bookmarks p{font-size:1em;margin:0 0 1em 0}#bookmarks body{font-size:.8em}#bookmarks ol.tree{padding:0 0 0 20px;width:90%}#bookmarks>li.file{margin-left:29px!important}#bookmarks li{position:relative;margin-left:15px;list-style:none}#bookmarks li.file{margin-left:-1px!important}#bookmarks li.file a{background:url(images/globe.png) 0 0 no-repeat;background-size:13px;color:#000;padding-left:21px;text-decoration:none;display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-size:.9em}#bookmarks li input{position:absolute;left:0;margin-left:0;opacity:0;z-index:2;cursor:pointer;height:1em;width:1em;top:0}#bookmarks li input+ol{background:url(images/toggle-small-expand.png) 40px -2px no-repeat;margin:-.938em 0 0 -44px;height:1em;text-overflow:ellipsis}#bookmarks li input+ol>li{display:none;margin-left:-14px!important;padding-left:1px}#bookmarks li label{background:url(images/folder-horizontal.png) 12px 2px no-repeat;cursor:pointer;display:block;padding-left:34px}#bookmarks li input:checked+ol{background:url(images/toggle-small.png) 40px 3px no-repeat;margin:-1.25em 0 0 -44px;padding:1.563em 0 0 80px;height:auto}#bookmarks li input:checked+ol>li{display:block;margin:0 0 .125em}#bookmarks li input:checked+ol>li:last-child{margin:0 0 .063em} \ No newline at end of file diff --git a/plugin.js b/syncmarks.js similarity index 75% rename from plugin.js rename to syncmarks.js index 74ccc96..ca51072 100644 --- a/plugin.js +++ b/syncmarks.js @@ -1,9 +1,9 @@ /** * Roundcube Bookmarks Plugin * - * @version 2.1.1 + * @version 2.2.0 * @author Offerel - * @copyright Copyright (c) 2019, Offerel + * @copyright Copyright (c) 2020, Offerel * @license GNU General Public License, version 3 */ function h_del(t, o) { @@ -60,8 +60,34 @@ function get_bookmarks(response) { } } +function get_notifications(response) { + let notifications = JSON.parse(response); + notifications.forEach(function(notification){ + show_noti(notification); + }); +} + +function show_noti(noti) { + if (Notification.permission !== 'granted') + Notification.requestPermission(); + else { + let notification = new Notification(noti.title, { + body: noti.url, + icon: './plugins/syncmarks/bookmarks.png', + requireInteraction: true + }); + + notification.onclick = function() { + window.open(noti.url); + rcmail.http_post("syncmarks/del_not", '&_nkey=' + noti.nkey); + }; + } +} + window.rcmail && rcmail.addEventListener("init", function(t) {}), $(document).ready(function() { $("#7f3f3c06-5b85-4e7f-b527-d061478e9446").on("click", bookmarks_cmd), document.getElementById("bookmarkpane").addEventListener("click", function(t) { "A" == t.target.tagName && bookmarks_cmd() }) -}) \ No newline at end of file +}) + +rcmail.addEventListener('plugin.sendNotifications', get_notifications); \ No newline at end of file diff --git a/syncmarks.min.js b/syncmarks.min.js new file mode 100644 index 0000000..18749e8 --- /dev/null +++ b/syncmarks.min.js @@ -0,0 +1,9 @@ +/** + * Roundcube Bookmarks Plugin + * + * @version 2.2.0 + * @author Offerel + * @copyright Copyright (c) 2020, Offerel + * @license GNU General Public License, version 3 + */ +function h_del(t,o){t.preventDefault();var e=rcmail.gettext("bookmarks_del","syncmarks").replace("%b%",o.innerHTML);if(1==confirm(e)){var r=encodeURIComponent(o.href);rcmail.http_post("syncmarks/del_url","_url="+r+"&_format=html")}}function j_del(t,o){t.preventDefault();var e=rcmail.gettext("bookmarks_del","syncmarks").replace("%b%",o.innerHTML);if(1==confirm(e)){var r=encodeURIComponent(o.href);rcmail.http_post("syncmarks/del_url","_url="+r+"&_format=json")}}function bookmarks_cmd(){"300"!=document.getElementById("bookmarkpane").clientWidth?rcmail.http_post("syncmarks/get_bookmarks","_url=2"):document.getElementById("bookmarkpane").style.width="0"}function add_url(){var t=encodeURIComponent(prompt(rcmail.gettext("bookmarks_url","syncmarks")));0add_texts('localization/', true); $this->register_task('syncmarks'); $this->include_stylesheet($this->local_skin_path().'/plugin.min.css'); - //$this->include_script('plugin.min.js'); - $this->include_script('plugin.js'); + $this->include_script('syncmarks.js'); $this->add_button(array( 'label' => 'syncmarks.bookmarks', @@ -31,11 +27,63 @@ public function init() { ), 'taskbar'); $this->add_hook('render_page', array($this, 'add_bookmarks')); + $this->add_hook('refresh', array($this, 'get_notifications')); + $this->add_hook('session_destroy', array($this, 'unset_cookie')); + $this->register_action('add_url', array($this, 'add_url')); $this->register_action('del_url', array($this, 'del_url')); $this->register_action('get_bookmarks', array($this, 'get_bookmarks')); + $this->register_action('del_not', array($this, 'del_not')); + } + + function unset_cookie() { + rcube_utils::setcookie('sycmarks_n', '0', time() - 60); + } + + function get_notifications() { + if($_COOKIE['sycmarks_n'] != '1') { + $rcmail = rcmail::get_instance(); + $this->load_config(); + $path = $rcmail->config->get('bookmarks_path', false); + $filename = $rcmail->config->get('bookmarks_filename', false); + + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $path.$filename.'?gurls=1'); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_REFERER, $_SERVER['REQUEST_URI']); + curl_setopt($ch, CURLOPT_VERBOSE, TRUE); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE); + curl_setopt($ch, CURLOPT_MAXREDIRS, 4); + curl_setopt($ch, CURLOPT_HTTPGET, TRUE); + curl_setopt($ch, CURLOPT_USERPWD, $rcmail->user->get_username().":".$rcmail->get_user_password()); + $data = curl_exec($ch); + $rcmail->output->command('plugin.sendNotifications', $data); + curl_close($ch); + rcube_utils::setcookie('sycmarks_n', '1', 0); + } } + function del_not() { + $rcmail = rcmail::get_instance(); + $this->load_config(); + $path = $rcmail->config->get('bookmarks_path', false); + $filename = $rcmail->config->get('bookmarks_filename', false); + + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $path.$filename.'?durl='.rcube_utils::get_input_value('_nkey', rcube_utils::INPUT_GPC)); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_REFERER, $_SERVER['REQUEST_URI']); + curl_setopt($ch, CURLOPT_VERBOSE, TRUE); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE); + curl_setopt($ch, CURLOPT_MAXREDIRS, 4); + curl_setopt($ch, CURLOPT_HTTPGET, TRUE); + curl_setopt($ch, CURLOPT_USERPWD, $rcmail->user->get_username().":".$rcmail->get_user_password()); + $data = curl_exec($ch); + curl_close($ch); + } + function get_bookmarks() { $rcmail = rcmail::get_instance(); $this->load_config(); @@ -50,9 +98,10 @@ function get_bookmarks() { 'header' => "Authorization: Basic ".base64_encode("$username:$password") ) ); + $context = stream_context_create($opts); $bms = file_get_contents($remote_url, false, $context); - + if($ext === "json") { foreach ($http_response_header as &$value) { if (strpos($value, 'ast-Modified') != 0) { @@ -69,9 +118,8 @@ function get_bookmarks() { $bms = parseHTMLMarks($bms, filemtime($bmfile), $this->gettext('bookmarks_new')); } } - + $rcmail->output->command('syncmarks/get_bookmarks', array('message' => $ext, 'data' => json_encode($bms))); - } function del_url() { @@ -156,6 +204,7 @@ function add_url() { curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE); curl_setopt($ch, CURLOPT_MAXREDIRS, 4); curl_setopt($ch, CURLOPT_HTTPGET, TRUE); + curl_setopt($ch, CURLOPT_USERPWD, $rcmail->user->get_username().":".$rcmail->get_user_password()); $data = curl_exec($ch); curl_close($ch); @@ -235,19 +284,23 @@ function add_url() { } } - function add_bookmarks($args) { + function add_bookmarks() { $rcmail = rcmail::get_instance(); - $this->load_config(); - $filename = $rcmail->config->get('bookmarks_filename', false); - $ext = pathinfo($filename, PATHINFO_EXTENSION); + $exctasks = array("login","logout"); + + if(!in_array($rcmail->task,$exctasks)) { + $this->load_config(); + $filename = $rcmail->config->get('bookmarks_filename', false); + $ext = pathinfo($filename, PATHINFO_EXTENSION); - if($ext === "php") { - $rcmail->output->add_footer("
"); - return $args; - } - else { - $rcmail->output->add_footer("
"); - return $args; + if($ext === "php") { + $rcmail->output->add_footer("
"); + return $args; + } + else { + $rcmail->output->add_footer("
"); + return $args; + } } }