thingsboard-aplcache

Details

ui/package.json 1(+1 -0)

diff --git a/ui/package.json b/ui/package.json
index 45f2f4b..b4485dc 100644
--- a/ui/package.json
+++ b/ui/package.json
@@ -45,6 +45,7 @@
     "angular-ui-ace": "^0.2.3",
     "angular-ui-router": "^0.3.1",
     "angular-websocket": "^2.0.1",
+    "base64-js": "^1.2.1",
     "brace": "^0.8.0",
     "canvas-gauges": "^2.0.9",
     "clipboard": "^1.5.15",
diff --git a/ui/src/app/common/utf8-support.js b/ui/src/app/common/utf8-support.js
new file mode 100644
index 0000000..464fa40
--- /dev/null
+++ b/ui/src/app/common/utf8-support.js
@@ -0,0 +1,138 @@
+/*
+ * Copyright © 2016-2017 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+export function utf8Encode(str) {
+    var result;
+
+    if (angular.isUndefined(Uint8Array)) { // eslint-disable-line no-undef
+        result = utf8ToBytes(str);
+    } else {
+        result = new Uint8Array(utf8ToBytes(str)); // eslint-disable-line no-undef
+    }
+
+    return result;
+}
+
+export function utf8Decode(bytes) {
+    return utf8Slice(bytes, 0, bytes.length);
+}
+
+function utf8Slice (buf, start, end) {
+    var res = ''
+    var tmp = ''
+    end = Math.min(buf.length, end || Infinity)
+    start = start || 0;
+
+    for (var i = start; i < end; i++) {
+        if (buf[i] <= 0x7F) {
+            res += decodeUtf8Char(tmp) + String.fromCharCode(buf[i])
+            tmp = ''
+        } else {
+            tmp += '%' + buf[i].toString(16)
+        }
+    }
+
+    return res + decodeUtf8Char(tmp)
+}
+
+function decodeUtf8Char (str) {
+    try {
+        return decodeURIComponent(str)
+    } catch (err) {
+        return String.fromCharCode(0xFFFD) // UTF 8 invalid char
+    }
+}
+
+function utf8ToBytes (string, units) {
+    units = units || Infinity
+    var codePoint
+    var length = string.length
+    var leadSurrogate = null
+    var bytes = []
+    var i = 0
+
+    for (; i < length; i++) {
+        codePoint = string.charCodeAt(i)
+
+        // is surrogate component
+        if (codePoint > 0xD7FF && codePoint < 0xE000) {
+            // last char was a lead
+            if (leadSurrogate) {
+                // 2 leads in a row
+                if (codePoint < 0xDC00) {
+                    if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
+                    leadSurrogate = codePoint
+                    continue
+                } else {
+                    // valid surrogate pair
+                    codePoint = leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00 | 0x10000
+                    leadSurrogate = null
+                }
+            } else {
+                // no lead yet
+
+                if (codePoint > 0xDBFF) {
+                    // unexpected trail
+                    if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
+                    continue
+                } else if (i + 1 === length) {
+                    // unpaired lead
+                    if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
+                    continue
+                } else {
+                    // valid lead
+                    leadSurrogate = codePoint
+                    continue
+                }
+            }
+        } else if (leadSurrogate) {
+            // valid bmp char, but last char was a lead
+            if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
+            leadSurrogate = null
+        }
+
+        // encode utf8
+        if (codePoint < 0x80) {
+            if ((units -= 1) < 0) break
+            bytes.push(codePoint)
+        } else if (codePoint < 0x800) {
+            if ((units -= 2) < 0) break
+            bytes.push(
+                codePoint >> 0x6 | 0xC0,
+                codePoint & 0x3F | 0x80
+            )
+        } else if (codePoint < 0x10000) {
+            if ((units -= 3) < 0) break
+            bytes.push(
+                codePoint >> 0xC | 0xE0,
+                codePoint >> 0x6 & 0x3F | 0x80,
+                codePoint & 0x3F | 0x80
+            )
+        } else if (codePoint < 0x200000) {
+            if ((units -= 4) < 0) break
+            bytes.push(
+                codePoint >> 0x12 | 0xF0,
+                codePoint >> 0xC & 0x3F | 0x80,
+                codePoint >> 0x6 & 0x3F | 0x80,
+                codePoint & 0x3F | 0x80
+            )
+        } else {
+            throw new Error('Invalid code point')
+        }
+    }
+
+    return bytes
+}
\ No newline at end of file
diff --git a/ui/src/app/common/utils.service.js b/ui/src/app/common/utils.service.js
index 7c9f97d..61d4d81 100644
--- a/ui/src/app/common/utils.service.js
+++ b/ui/src/app/common/utils.service.js
@@ -20,9 +20,12 @@ import materialIconsCodepoints from 'raw-loader!material-design-icons/iconfont/c
 
 /* eslint-enable import/no-unresolved, import/default */
 
-import tinycolor from "tinycolor2";
-import jsonSchemaDefaults from "json-schema-defaults";
-import thingsboardTypes from "./types.constant";
+import tinycolor from 'tinycolor2';
+import jsonSchemaDefaults from 'json-schema-defaults';
+import base64js from 'base64-js';
+import {utf8Encode, utf8Decode} from './utf8-support';
+
+import thingsboardTypes from './types.constant';
 
 export default angular.module('thingsboard.utils', [thingsboardTypes])
     .factory('utils', Utils)
@@ -153,7 +156,9 @@ function Utils($mdColorPalette, $rootScope, $window, $translate, $q, $timeout, t
         createKey: createKey,
         createLabelFromDatasource: createLabelFromDatasource,
         insertVariable: insertVariable,
-        customTranslation: customTranslation
+        customTranslation: customTranslation,
+        objToBase64: objToBase64,
+        base64toObj: base64toObj
     }
 
     return service;
@@ -486,4 +491,18 @@ function Utils($mdColorPalette, $rootScope, $window, $translate, $q, $timeout, t
         return result;
     }
 
+    function objToBase64(obj) {
+        var json = angular.toJson(obj);
+        var encoded = utf8Encode(json);
+        var b64Encoded = base64js.fromByteArray(encoded);
+        return b64Encoded;
+    }
+
+    function base64toObj(b64Encoded) {
+        var encoded = base64js.toByteArray(b64Encoded);
+        var json = utf8Decode(encoded);
+        var obj = angular.fromJson(json);
+        return obj;
+    }
+
 }
diff --git a/ui/src/app/components/widget/widget.controller.js b/ui/src/app/components/widget/widget.controller.js
index 4e85718..7ed79ae 100644
--- a/ui/src/app/components/widget/widget.controller.js
+++ b/ui/src/app/components/widget/widget.controller.js
@@ -473,7 +473,7 @@ export default function WidgetController($scope, $state, $timeout, $window, $ele
                 }
                 var stateParams = {
                     dashboardId: targetDashboardId,
-                    state: angular.toJson([ stateObject ])
+                    state: utils.objToBase64([ stateObject ])
                 }
                 $state.go('home.dashboards.dashboard', stateParams);
                 break;
diff --git a/ui/src/app/dashboard/states/default-state-controller.js b/ui/src/app/dashboard/states/default-state-controller.js
index ae92d37..7d810ca 100644
--- a/ui/src/app/dashboard/states/default-state-controller.js
+++ b/ui/src/app/dashboard/states/default-state-controller.js
@@ -121,11 +121,11 @@ export default function DefaultStateController($scope, $location, $state, $state
         return utils.customTranslation(state.name, id);
     }
 
-    function parseState(stateJson) {
+    function parseState(stateBase64) {
         var result;
-        if (stateJson) {
+        if (stateBase64) {
             try {
-                result = angular.fromJson(stateJson);
+                result = utils.base64toObj(stateBase64);
             } catch (e) {
                 result = [ { id: null, params: {} } ];
             }
@@ -205,7 +205,7 @@ export default function DefaultStateController($scope, $location, $state, $state
 
     function updateLocation() {
         if (vm.stateObject[0].id) {
-            $location.search({state : angular.toJson(vm.stateObject)});
+            $location.search({state : utils.objToBase64(vm.stateObject)});
         }
     }
 }
diff --git a/ui/src/app/dashboard/states/entity-state-controller.js b/ui/src/app/dashboard/states/entity-state-controller.js
index cbe91fa..a554adf 100644
--- a/ui/src/app/dashboard/states/entity-state-controller.js
+++ b/ui/src/app/dashboard/states/entity-state-controller.js
@@ -168,11 +168,11 @@ export default function EntityStateController($scope, $location, $state, $stateP
         return deferred.promise;
     }
 
-    function parseState(stateJson) {
+    function parseState(stateBase64) {
         var result;
-        if (stateJson) {
+        if (stateBase64) {
             try {
-                result = angular.fromJson(stateJson);
+                result = utils.base64toObj(stateBase64);
             } catch (e) {
                 result = [ { id: null, params: {} } ];
             }
@@ -278,7 +278,7 @@ export default function EntityStateController($scope, $location, $state, $stateP
 
     function updateLocation() {
         if (vm.stateObject[vm.stateObject.length-1].id) {
-            $location.search({state : angular.toJson(vm.stateObject)});
+            $location.search({state : utils.objToBase64(vm.stateObject)});
         }
     }
 
diff --git a/ui/src/app/entity/attribute/add-widget-to-dashboard-dialog.controller.js b/ui/src/app/entity/attribute/add-widget-to-dashboard-dialog.controller.js
index a133829..64726db 100644
--- a/ui/src/app/entity/attribute/add-widget-to-dashboard-dialog.controller.js
+++ b/ui/src/app/entity/attribute/add-widget-to-dashboard-dialog.controller.js
@@ -23,7 +23,7 @@ import selectTargetLayoutTemplate from '../../dashboard/layouts/select-target-la
 
 /*@ngInject*/
 export default function AddWidgetToDashboardDialogController($scope, $mdDialog, $state, $q, $document, dashboardUtils,
-                                                             types, itembuffer, dashboardService, entityId, entityType, entityName, widget) {
+                                                             utils, types, itembuffer, dashboardService, entityId, entityType, entityName, widget) {
 
     var vm = this;
 
@@ -143,7 +143,7 @@ export default function AddWidgetToDashboardDialogController($scope, $mdDialog, 
                             var stateIds = Object.keys(dashboard.configuration.states);
                             var stateIndex = stateIds.indexOf(targetState);
                             if (stateIndex > 0) {
-                                stateParams.state = angular.toJson([ {id: targetState, params: {}} ]);
+                                stateParams.state = utils.objToBase64([ {id: targetState, params: {}} ]);
                             }
                             $state.go('home.dashboards.dashboard', stateParams);
                         }