Просмотр исходного кода

initial work to add IndexedDB support, including npm module to mock its API in unit tests

El RIDO 6 лет назад
Родитель
Сommit
ac32826009
5 измененных файлов с 74 добавлено и 10 удалено
  1. 1 0
      js/common.js
  2. 3 2
      js/package.json
  3. 68 6
      js/privatebin.js
  4. 1 1
      tpl/bootstrap.php
  5. 1 1
      tpl/page.php

+ 1 - 0
js/common.js

@@ -8,6 +8,7 @@ global.cleanup = global.jsdom();
 global.URL = require('jsdom-url').URL;
 global.fs = require('fs');
 global.WebCrypto = require('@peculiar/webcrypto').Crypto;
+require('fake-indexeddb/auto');
 
 // application libraries to test
 global.$ = global.jQuery = require('./jquery-3.4.1');

+ 3 - 2
js/package.json

@@ -8,11 +8,12 @@
   },
   "dependencies": {},
   "devDependencies": {
+    "@peculiar/webcrypto": "^1.1.1",
+    "fake-indexeddb": "^3.0.2",
     "jsdom": "^9.12.0",
     "jsdom-global": "^2.1.1",
     "jsdom-url": "^2.2.1",
-    "jsverify": "^0.8.3",
-    "@peculiar/webcrypto": "^1.1.1"
+    "jsverify": "^0.8.3"
   },
   "scripts": {
     "test": "mocha"

+ 68 - 6
js/privatebin.js

@@ -4362,10 +4362,30 @@ jQuery.PrivateBin = (function($, RawDeflate) {
      * @name   Memory
      * @class
      */
-    const Memory = (function (document) {
+    const Memory = (function (document, window) {
         const me = {};
 
-        let urls = [];
+        let urls = [],
+            db;
+
+        /**
+         * called after successfully connecting to the indexedDB
+         *
+         * @name   Memory.updateCacheFromDb
+         * @private
+         * @function
+         */
+        function updateCacheFromDb()
+        {
+            const memory = db.transaction('pastes').objectStore('pastes');
+            memory.openCursor().onsuccess = function(e) {
+                let cursor = e.target.result;
+                if (cursor) {
+                    urls.push(cursor.value.url);
+                    cursor.continue();
+                }
+            };
+        }
 
         /**
          * adds a paste URL to the memory
@@ -4378,6 +4398,20 @@ jQuery.PrivateBin = (function($, RawDeflate) {
         me.add = function(pasteUrl)
         {
             urls.push(pasteUrl);
+            if (!window.indexedDB || !db) {
+                return false;
+            }
+            const url = new URL(pasteUrl);
+            const memory = db.transaction('pastes', 'readwrite').objectStore('pastes');
+            memory.add({
+                'https': url.protocol == 'https:',
+                'service': url.hostname + url.pathname,
+                'pasteid': url.search.replace(/^\?+/, ''),
+                'key': url.hash.replace(/^#+/, ''),
+                // we store the full URL as it may contain additonal information
+                // required to open the paste, like port, username and password
+                'url': pasteUrl
+            });
             return true;
         };
 
@@ -4411,15 +4445,43 @@ jQuery.PrivateBin = (function($, RawDeflate) {
         me.init = function()
         {
             urls = [];
-            $("#menu-toggle").on('click', function(e) {
+            if (!window.indexedDB) {
+                $('#menu-toggle').hide();
+                return;
+            }
+            const request = window.indexedDB.open('privatebin', 1);
+            request.onerror = function(e) {
+                Alert.showWarning('Unable to open indexedDB, memory will not be available in this session.');
+                $('#menu-toggle').hide();
+            };
+            request.onupgradeneeded = function(event) { 
+                const newDb = event.target.result;
+                const objectStore = newDb.createObjectStore('pastes', {keyPath: 'pasteid'});
+                objectStore.createIndex('https', 'https', {unique: false});
+                objectStore.createIndex('service', 'service', {unique: false});
+                objectStore.createIndex('pasteid', 'pasteid', {unique: true});
+                objectStore.transaction.oncomplete = function(e) {
+                    db = newDb;
+                    updateCacheFromDb();
+                };
+            };
+            request.onsuccess = function(e) {
+                db = request.result;
+                db.onerror = function(e) {
+                    Alert.showError(e);
+                }
+                updateCacheFromDb();
+            };
+
+            $('#menu-toggle').on('click', function(e) {
                 e.preventDefault();
-                $("main").toggleClass("toggled");
-                $("#menu-toggle .glyphicon").toggleClass("glyphicon glyphicon-menu-down glyphicon glyphicon-menu-up")
+                $('main').toggleClass('toggled');
+                $('#menu-toggle .glyphicon').toggleClass('glyphicon glyphicon-menu-down glyphicon glyphicon-menu-up')
             });
         };
 
         return me;
-    })(document);
+    })(document, window);
 
     /**
      * Responsible for AJAX requests, transparently handles encryption…

+ 1 - 1
tpl/bootstrap.php

@@ -72,7 +72,7 @@ endif;
 ?>
 		<script type="text/javascript" data-cfasync="false" src="js/purify-2.0.8.js" integrity="sha512-QwcEKGuEmKtMguCO9pqNtUtZqq9b/tJ8gNr5qhY8hykq3zKTlDOvpZAmf6Rs8yH35Bz1ZdctUjj2qEWxT5aXCg==" crossorigin="anonymous"></script>
 		<script type="text/javascript" data-cfasync="false" src="js/legacy.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-LYos+qXHIRqFf5ZPNphvtTB0cgzHUizu2wwcOwcwz/VIpRv9lpcBgPYz4uq6jx0INwCAj6Fbnl5HoKiLufS2jg==" crossorigin="anonymous"></script>
-		<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-Ney+hSdITdWT9OPVLg0O3HLbaHKVO64fV/M+cUmKBOsMibv9Dsrug5jQRk17lebetk3jOPL0LyvBy+nAkAcFbw==" crossorigin="anonymous"></script>
+		<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-2B/LnmR6+LLKTWo6vvJ4ncMShPAa2at+tC1jiuZQtux6PfnERz+rrZNfl+srWfWr8xF4DtZBDiIZbDPiQHIGLQ==" crossorigin="anonymous"></script>
 		<!-- icon -->
 		<link rel="apple-touch-icon" href="img/apple-touch-icon.png?<?php echo rawurlencode($VERSION); ?>" sizes="180x180" />
 		<link rel="icon" type="image/png" href="img/favicon-32x32.png?<?php echo rawurlencode($VERSION); ?>" sizes="32x32" />

+ 1 - 1
tpl/page.php

@@ -50,7 +50,7 @@ endif;
 ?>
 		<script type="text/javascript" data-cfasync="false" src="js/purify-2.0.8.js" integrity="sha512-QwcEKGuEmKtMguCO9pqNtUtZqq9b/tJ8gNr5qhY8hykq3zKTlDOvpZAmf6Rs8yH35Bz1ZdctUjj2qEWxT5aXCg==" crossorigin="anonymous"></script>
 		<script type="text/javascript" data-cfasync="false" src="js/legacy.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-LYos+qXHIRqFf5ZPNphvtTB0cgzHUizu2wwcOwcwz/VIpRv9lpcBgPYz4uq6jx0INwCAj6Fbnl5HoKiLufS2jg==" crossorigin="anonymous"></script>
-		<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-Ney+hSdITdWT9OPVLg0O3HLbaHKVO64fV/M+cUmKBOsMibv9Dsrug5jQRk17lebetk3jOPL0LyvBy+nAkAcFbw==" crossorigin="anonymous"></script>
+		<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-2B/LnmR6+LLKTWo6vvJ4ncMShPAa2at+tC1jiuZQtux6PfnERz+rrZNfl+srWfWr8xF4DtZBDiIZbDPiQHIGLQ==" crossorigin="anonymous"></script>
 		<!-- icon -->
 		<link rel="apple-touch-icon" href="img/apple-touch-icon.png?<?php echo rawurlencode($VERSION); ?>" sizes="180x180" />
 		<link rel="icon" type="image/png" href="img/favicon-32x32.png?<?php echo rawurlencode($VERSION); ?>" sizes="32x32" />