nutella_framework 0.4.18 → 0.4.19

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f0734b827e4685a852d4450fdc3c50bd8804acf3
4
- data.tar.gz: 8583c6ca31c9dbe49ac53c7727f3bdb119f0c43f
3
+ metadata.gz: e75030070ab8a779a4d65831ce16b04f0c041253
4
+ data.tar.gz: f435d86a781e34feefe0dbf9e1e14f381c68b52c
5
5
  SHA512:
6
- metadata.gz: 6cd6bc6aaeb4ce404e213d44895f39fae5b62bd9bf84bbd1388b2c499b7c86f583d7dfa33a856289c7db219c4504338410a027ea66a92ccbf857aa0cd86dc263
7
- data.tar.gz: 4dc44527005a1985c8a11618688851ee44a0771cf3b59d2e820dfc6842649ca60348b910b32f1a276eaadfccd67a0a0f037b7e020c1f994664e73f92630b42bf
6
+ metadata.gz: d116c6122ee44805db23486e6c06ce502925169d1b93c207552ad63997e7be2e82cc8d36973f170b3bede3ddfbb03dd59463e339d4ad5aa3d786c5e0c0c266e9
7
+ data.tar.gz: 3ec338710b1ab2260bd86be237ae0950e309d99584b62e5ac24045d72eb9c4e15529ffeac1d4833718a1ffc3f67c7a6d65c4f246a34b72b0c1b05c7cf3464f13
data/Gemfile CHANGED
@@ -9,7 +9,8 @@ gem 'thin', '~>1.6'
9
9
  gem 'nokogiri', '~>1.6'
10
10
  gem 'slop', '~>4.0'
11
11
  gem 'nutella_lib','~>0.4', '>=0.4.12'
12
-
12
+ gem 'activesupport', '~>4.2'
13
+ gem 'mandrill-api', '~>1.0', '>=1.0.53'
13
14
 
14
15
  group :development do
15
16
  gem 'shoulda', '~> 3.0'
data/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  [![Build Status](https://travis-ci.org/nutella-framework/nutella_framework.svg?branch=master)](https://travis-ci.org/nutella-framework/nutella_framework)
4
4
  [![Code Climate](https://codeclimate.com/github/nutella-framework/nutella_framework/badges/gpa.svg)](https://codeclimate.com/github/nutella-framework/nutella_framework)
5
5
 
6
- nutella is a framework to build and run RoomApps. It's still _very_ under development so any help [finding and fixing bugs](https://github.com/nutella-framework/nutella_framework/issues) will be greatly appreciated!
6
+ nutella is a framework to build and run Macroworlds. It's still _very_ under development so any help [finding and fixing bugs](https://github.com/nutella-framework/nutella_framework/issues) will be greatly appreciated!
7
7
 
8
8
  # Installing
9
9
  Nutella is written in ruby but it leverages a bunch of other technologies that need to be installed. You will need:
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.4.18
1
+ 0.4.19
@@ -10,11 +10,16 @@
10
10
  */
11
11
 
12
12
  var nutella_i = require('./nutella_i_browser');
13
+ var nutella_version = require('./version');
13
14
 
14
15
  // Internal reference to this library (used below)
15
16
  var nutella = {};
16
17
 
17
18
 
19
+ // Version number
20
+ nutella.version = nutella_version.version;
21
+
22
+
18
23
  /**
19
24
  * Creates a new instance of nutella
20
25
  * and initialize it. This is a factory method.
@@ -84,12 +89,20 @@ nutella.parseURLParameters = function () {
84
89
  };
85
90
 
86
91
 
87
- nutella.version = '0.4.3';
92
+ /**
93
+ * Utility method that parses the component ID from the URL.
94
+ *
95
+ * @return {String} the componentId of this component
96
+ */
97
+ nutella.parseComponentId = function() {
98
+ return location.pathname.split('/')[4];
99
+ };
100
+
88
101
 
89
102
 
90
103
  // Exports nutella object
91
104
  module.exports = nutella;
92
- },{"./nutella_i_browser":10}],2:[function(require,module,exports){
105
+ },{"./nutella_i_browser":11,"./version":17}],2:[function(require,module,exports){
93
106
  /**********************
94
107
  * Simple MQTT client *
95
108
  **********************/
@@ -97,7 +110,6 @@ module.exports = nutella;
97
110
  "use strict";
98
111
 
99
112
  var mqtt_lib = require('./paho/mqttws31');
100
- //var mqtt_lib = require('./paho/mqttws31-min'); TODO
101
113
 
102
114
 
103
115
  /**
@@ -278,6 +290,23 @@ var publishBrowser = function (client, backlog, channel, message) {
278
290
 
279
291
 
280
292
 
293
+ /**
294
+ * Returns the client host
295
+ *
296
+ * @return {String}
297
+ */
298
+ SimpleMQTTClient.prototype.getHost = function() {
299
+ return this.client._getHost();
300
+ }
301
+
302
+
303
+
304
+ /**
305
+ * Determines if a channel is wildcard or not.
306
+ *
307
+ * @param channel
308
+ * @return {boolean} true if the channel is a wildcard channel, false otherwise
309
+ */
281
310
  SimpleMQTTClient.prototype.isChannelWildcard = function(channel) {
282
311
  return channel.indexOf('#')>-1 || channel.indexOf('+')>-1 ;
283
312
  }
@@ -2517,6 +2546,607 @@ Paho.MQTT = (function (global) {
2517
2546
  })(window);
2518
2547
  module.exports=Paho.MQTT;
2519
2548
  },{}],4:[function(require,module,exports){
2549
+ /*jshint bitwise:false*/
2550
+ /*global unescape*/
2551
+
2552
+ (function (factory) {
2553
+ if (typeof exports === 'object') {
2554
+ // Node/CommonJS
2555
+ module.exports = factory();
2556
+ } else if (typeof define === 'function' && define.amd) {
2557
+ // AMD
2558
+ define(factory);
2559
+ } else {
2560
+ // Browser globals (with support for web workers)
2561
+ var glob;
2562
+ try {
2563
+ glob = window;
2564
+ } catch (e) {
2565
+ glob = self;
2566
+ }
2567
+
2568
+ glob.SparkMD5 = factory();
2569
+ }
2570
+ }(function (undefined) {
2571
+
2572
+ 'use strict';
2573
+
2574
+ ////////////////////////////////////////////////////////////////////////////
2575
+
2576
+ /*
2577
+ * Fastest md5 implementation around (JKM md5)
2578
+ * Credits: Joseph Myers
2579
+ *
2580
+ * @see http://www.myersdaily.org/joseph/javascript/md5-text.html
2581
+ * @see http://jsperf.com/md5-shootout/7
2582
+ */
2583
+
2584
+ /* this function is much faster,
2585
+ so if possible we use it. Some IEs
2586
+ are the only ones I know of that
2587
+ need the idiotic second function,
2588
+ generated by an if clause. */
2589
+ var add32 = function (a, b) {
2590
+ return (a + b) & 0xFFFFFFFF;
2591
+ },
2592
+
2593
+ cmn = function (q, a, b, x, s, t) {
2594
+ a = add32(add32(a, q), add32(x, t));
2595
+ return add32((a << s) | (a >>> (32 - s)), b);
2596
+ },
2597
+
2598
+ ff = function (a, b, c, d, x, s, t) {
2599
+ return cmn((b & c) | ((~b) & d), a, b, x, s, t);
2600
+ },
2601
+
2602
+ gg = function (a, b, c, d, x, s, t) {
2603
+ return cmn((b & d) | (c & (~d)), a, b, x, s, t);
2604
+ },
2605
+
2606
+ hh = function (a, b, c, d, x, s, t) {
2607
+ return cmn(b ^ c ^ d, a, b, x, s, t);
2608
+ },
2609
+
2610
+ ii = function (a, b, c, d, x, s, t) {
2611
+ return cmn(c ^ (b | (~d)), a, b, x, s, t);
2612
+ },
2613
+
2614
+ md5cycle = function (x, k) {
2615
+ var a = x[0],
2616
+ b = x[1],
2617
+ c = x[2],
2618
+ d = x[3];
2619
+
2620
+ a = ff(a, b, c, d, k[0], 7, -680876936);
2621
+ d = ff(d, a, b, c, k[1], 12, -389564586);
2622
+ c = ff(c, d, a, b, k[2], 17, 606105819);
2623
+ b = ff(b, c, d, a, k[3], 22, -1044525330);
2624
+ a = ff(a, b, c, d, k[4], 7, -176418897);
2625
+ d = ff(d, a, b, c, k[5], 12, 1200080426);
2626
+ c = ff(c, d, a, b, k[6], 17, -1473231341);
2627
+ b = ff(b, c, d, a, k[7], 22, -45705983);
2628
+ a = ff(a, b, c, d, k[8], 7, 1770035416);
2629
+ d = ff(d, a, b, c, k[9], 12, -1958414417);
2630
+ c = ff(c, d, a, b, k[10], 17, -42063);
2631
+ b = ff(b, c, d, a, k[11], 22, -1990404162);
2632
+ a = ff(a, b, c, d, k[12], 7, 1804603682);
2633
+ d = ff(d, a, b, c, k[13], 12, -40341101);
2634
+ c = ff(c, d, a, b, k[14], 17, -1502002290);
2635
+ b = ff(b, c, d, a, k[15], 22, 1236535329);
2636
+
2637
+ a = gg(a, b, c, d, k[1], 5, -165796510);
2638
+ d = gg(d, a, b, c, k[6], 9, -1069501632);
2639
+ c = gg(c, d, a, b, k[11], 14, 643717713);
2640
+ b = gg(b, c, d, a, k[0], 20, -373897302);
2641
+ a = gg(a, b, c, d, k[5], 5, -701558691);
2642
+ d = gg(d, a, b, c, k[10], 9, 38016083);
2643
+ c = gg(c, d, a, b, k[15], 14, -660478335);
2644
+ b = gg(b, c, d, a, k[4], 20, -405537848);
2645
+ a = gg(a, b, c, d, k[9], 5, 568446438);
2646
+ d = gg(d, a, b, c, k[14], 9, -1019803690);
2647
+ c = gg(c, d, a, b, k[3], 14, -187363961);
2648
+ b = gg(b, c, d, a, k[8], 20, 1163531501);
2649
+ a = gg(a, b, c, d, k[13], 5, -1444681467);
2650
+ d = gg(d, a, b, c, k[2], 9, -51403784);
2651
+ c = gg(c, d, a, b, k[7], 14, 1735328473);
2652
+ b = gg(b, c, d, a, k[12], 20, -1926607734);
2653
+
2654
+ a = hh(a, b, c, d, k[5], 4, -378558);
2655
+ d = hh(d, a, b, c, k[8], 11, -2022574463);
2656
+ c = hh(c, d, a, b, k[11], 16, 1839030562);
2657
+ b = hh(b, c, d, a, k[14], 23, -35309556);
2658
+ a = hh(a, b, c, d, k[1], 4, -1530992060);
2659
+ d = hh(d, a, b, c, k[4], 11, 1272893353);
2660
+ c = hh(c, d, a, b, k[7], 16, -155497632);
2661
+ b = hh(b, c, d, a, k[10], 23, -1094730640);
2662
+ a = hh(a, b, c, d, k[13], 4, 681279174);
2663
+ d = hh(d, a, b, c, k[0], 11, -358537222);
2664
+ c = hh(c, d, a, b, k[3], 16, -722521979);
2665
+ b = hh(b, c, d, a, k[6], 23, 76029189);
2666
+ a = hh(a, b, c, d, k[9], 4, -640364487);
2667
+ d = hh(d, a, b, c, k[12], 11, -421815835);
2668
+ c = hh(c, d, a, b, k[15], 16, 530742520);
2669
+ b = hh(b, c, d, a, k[2], 23, -995338651);
2670
+
2671
+ a = ii(a, b, c, d, k[0], 6, -198630844);
2672
+ d = ii(d, a, b, c, k[7], 10, 1126891415);
2673
+ c = ii(c, d, a, b, k[14], 15, -1416354905);
2674
+ b = ii(b, c, d, a, k[5], 21, -57434055);
2675
+ a = ii(a, b, c, d, k[12], 6, 1700485571);
2676
+ d = ii(d, a, b, c, k[3], 10, -1894986606);
2677
+ c = ii(c, d, a, b, k[10], 15, -1051523);
2678
+ b = ii(b, c, d, a, k[1], 21, -2054922799);
2679
+ a = ii(a, b, c, d, k[8], 6, 1873313359);
2680
+ d = ii(d, a, b, c, k[15], 10, -30611744);
2681
+ c = ii(c, d, a, b, k[6], 15, -1560198380);
2682
+ b = ii(b, c, d, a, k[13], 21, 1309151649);
2683
+ a = ii(a, b, c, d, k[4], 6, -145523070);
2684
+ d = ii(d, a, b, c, k[11], 10, -1120210379);
2685
+ c = ii(c, d, a, b, k[2], 15, 718787259);
2686
+ b = ii(b, c, d, a, k[9], 21, -343485551);
2687
+
2688
+ x[0] = add32(a, x[0]);
2689
+ x[1] = add32(b, x[1]);
2690
+ x[2] = add32(c, x[2]);
2691
+ x[3] = add32(d, x[3]);
2692
+ },
2693
+
2694
+ /* there needs to be support for Unicode here,
2695
+ * unless we pretend that we can redefine the MD-5
2696
+ * algorithm for multi-byte characters (perhaps
2697
+ * by adding every four 16-bit characters and
2698
+ * shortening the sum to 32 bits). Otherwise
2699
+ * I suggest performing MD-5 as if every character
2700
+ * was two bytes--e.g., 0040 0025 = @%--but then
2701
+ * how will an ordinary MD-5 sum be matched?
2702
+ * There is no way to standardize text to something
2703
+ * like UTF-8 before transformation; speed cost is
2704
+ * utterly prohibitive. The JavaScript standard
2705
+ * itself needs to look at this: it should start
2706
+ * providing access to strings as preformed UTF-8
2707
+ * 8-bit unsigned value arrays.
2708
+ */
2709
+ md5blk = function (s) {
2710
+ var md5blks = [],
2711
+ i; /* Andy King said do it this way. */
2712
+
2713
+ for (i = 0; i < 64; i += 4) {
2714
+ md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24);
2715
+ }
2716
+ return md5blks;
2717
+ },
2718
+
2719
+ md5blk_array = function (a) {
2720
+ var md5blks = [],
2721
+ i; /* Andy King said do it this way. */
2722
+
2723
+ for (i = 0; i < 64; i += 4) {
2724
+ md5blks[i >> 2] = a[i] + (a[i + 1] << 8) + (a[i + 2] << 16) + (a[i + 3] << 24);
2725
+ }
2726
+ return md5blks;
2727
+ },
2728
+
2729
+ md51 = function (s) {
2730
+ var n = s.length,
2731
+ state = [1732584193, -271733879, -1732584194, 271733878],
2732
+ i,
2733
+ length,
2734
+ tail,
2735
+ tmp,
2736
+ lo,
2737
+ hi;
2738
+
2739
+ for (i = 64; i <= n; i += 64) {
2740
+ md5cycle(state, md5blk(s.substring(i - 64, i)));
2741
+ }
2742
+ s = s.substring(i - 64);
2743
+ length = s.length;
2744
+ tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
2745
+ for (i = 0; i < length; i += 1) {
2746
+ tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3);
2747
+ }
2748
+ tail[i >> 2] |= 0x80 << ((i % 4) << 3);
2749
+ if (i > 55) {
2750
+ md5cycle(state, tail);
2751
+ for (i = 0; i < 16; i += 1) {
2752
+ tail[i] = 0;
2753
+ }
2754
+ }
2755
+
2756
+ // Beware that the final length might not fit in 32 bits so we take care of that
2757
+ tmp = n * 8;
2758
+ tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
2759
+ lo = parseInt(tmp[2], 16);
2760
+ hi = parseInt(tmp[1], 16) || 0;
2761
+
2762
+ tail[14] = lo;
2763
+ tail[15] = hi;
2764
+
2765
+ md5cycle(state, tail);
2766
+ return state;
2767
+ },
2768
+
2769
+ md51_array = function (a) {
2770
+ var n = a.length,
2771
+ state = [1732584193, -271733879, -1732584194, 271733878],
2772
+ i,
2773
+ length,
2774
+ tail,
2775
+ tmp,
2776
+ lo,
2777
+ hi;
2778
+
2779
+ for (i = 64; i <= n; i += 64) {
2780
+ md5cycle(state, md5blk_array(a.subarray(i - 64, i)));
2781
+ }
2782
+
2783
+ // Not sure if it is a bug, however IE10 will always produce a sub array of length 1
2784
+ // containing the last element of the parent array if the sub array specified starts
2785
+ // beyond the length of the parent array - weird.
2786
+ // https://connect.microsoft.com/IE/feedback/details/771452/typed-array-subarray-issue
2787
+ a = (i - 64) < n ? a.subarray(i - 64) : new Uint8Array(0);
2788
+
2789
+ length = a.length;
2790
+ tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
2791
+ for (i = 0; i < length; i += 1) {
2792
+ tail[i >> 2] |= a[i] << ((i % 4) << 3);
2793
+ }
2794
+
2795
+ tail[i >> 2] |= 0x80 << ((i % 4) << 3);
2796
+ if (i > 55) {
2797
+ md5cycle(state, tail);
2798
+ for (i = 0; i < 16; i += 1) {
2799
+ tail[i] = 0;
2800
+ }
2801
+ }
2802
+
2803
+ // Beware that the final length might not fit in 32 bits so we take care of that
2804
+ tmp = n * 8;
2805
+ tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
2806
+ lo = parseInt(tmp[2], 16);
2807
+ hi = parseInt(tmp[1], 16) || 0;
2808
+
2809
+ tail[14] = lo;
2810
+ tail[15] = hi;
2811
+
2812
+ md5cycle(state, tail);
2813
+
2814
+ return state;
2815
+ },
2816
+
2817
+ hex_chr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'],
2818
+
2819
+ rhex = function (n) {
2820
+ var s = '',
2821
+ j;
2822
+ for (j = 0; j < 4; j += 1) {
2823
+ s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F];
2824
+ }
2825
+ return s;
2826
+ },
2827
+
2828
+ hex = function (x) {
2829
+ var i;
2830
+ for (i = 0; i < x.length; i += 1) {
2831
+ x[i] = rhex(x[i]);
2832
+ }
2833
+ return x.join('');
2834
+ },
2835
+
2836
+ md5 = function (s) {
2837
+ return hex(md51(s));
2838
+ },
2839
+
2840
+
2841
+
2842
+ ////////////////////////////////////////////////////////////////////////////
2843
+
2844
+ /**
2845
+ * SparkMD5 OOP implementation.
2846
+ *
2847
+ * Use this class to perform an incremental md5, otherwise use the
2848
+ * static methods instead.
2849
+ */
2850
+ SparkMD5 = function () {
2851
+ // call reset to init the instance
2852
+ this.reset();
2853
+ };
2854
+
2855
+
2856
+ // In some cases the fast add32 function cannot be used..
2857
+ if (md5('hello') !== '5d41402abc4b2a76b9719d911017c592') {
2858
+ add32 = function (x, y) {
2859
+ var lsw = (x & 0xFFFF) + (y & 0xFFFF),
2860
+ msw = (x >> 16) + (y >> 16) + (lsw >> 16);
2861
+ return (msw << 16) | (lsw & 0xFFFF);
2862
+ };
2863
+ }
2864
+
2865
+
2866
+ /**
2867
+ * Appends a string.
2868
+ * A conversion will be applied if an utf8 string is detected.
2869
+ *
2870
+ * @param {String} str The string to be appended
2871
+ *
2872
+ * @return {SparkMD5} The instance itself
2873
+ */
2874
+ SparkMD5.prototype.append = function (str) {
2875
+ // converts the string to utf8 bytes if necessary
2876
+ if (/[\u0080-\uFFFF]/.test(str)) {
2877
+ str = unescape(encodeURIComponent(str));
2878
+ }
2879
+
2880
+ // then append as binary
2881
+ this.appendBinary(str);
2882
+
2883
+ return this;
2884
+ };
2885
+
2886
+ /**
2887
+ * Appends a binary string.
2888
+ *
2889
+ * @param {String} contents The binary string to be appended
2890
+ *
2891
+ * @return {SparkMD5} The instance itself
2892
+ */
2893
+ SparkMD5.prototype.appendBinary = function (contents) {
2894
+ this._buff += contents;
2895
+ this._length += contents.length;
2896
+
2897
+ var length = this._buff.length,
2898
+ i;
2899
+
2900
+ for (i = 64; i <= length; i += 64) {
2901
+ md5cycle(this._state, md5blk(this._buff.substring(i - 64, i)));
2902
+ }
2903
+
2904
+ this._buff = this._buff.substr(i - 64);
2905
+
2906
+ return this;
2907
+ };
2908
+
2909
+ /**
2910
+ * Finishes the incremental computation, reseting the internal state and
2911
+ * returning the result.
2912
+ * Use the raw parameter to obtain the raw result instead of the hex one.
2913
+ *
2914
+ * @param {Boolean} raw True to get the raw result, false to get the hex result
2915
+ *
2916
+ * @return {String|Array} The result
2917
+ */
2918
+ SparkMD5.prototype.end = function (raw) {
2919
+ var buff = this._buff,
2920
+ length = buff.length,
2921
+ i,
2922
+ tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
2923
+ ret;
2924
+
2925
+ for (i = 0; i < length; i += 1) {
2926
+ tail[i >> 2] |= buff.charCodeAt(i) << ((i % 4) << 3);
2927
+ }
2928
+
2929
+ this._finish(tail, length);
2930
+ ret = !!raw ? this._state : hex(this._state);
2931
+
2932
+ this.reset();
2933
+
2934
+ return ret;
2935
+ };
2936
+
2937
+ /**
2938
+ * Finish the final calculation based on the tail.
2939
+ *
2940
+ * @param {Array} tail The tail (will be modified)
2941
+ * @param {Number} length The length of the remaining buffer
2942
+ */
2943
+ SparkMD5.prototype._finish = function (tail, length) {
2944
+ var i = length,
2945
+ tmp,
2946
+ lo,
2947
+ hi;
2948
+
2949
+ tail[i >> 2] |= 0x80 << ((i % 4) << 3);
2950
+ if (i > 55) {
2951
+ md5cycle(this._state, tail);
2952
+ for (i = 0; i < 16; i += 1) {
2953
+ tail[i] = 0;
2954
+ }
2955
+ }
2956
+
2957
+ // Do the final computation based on the tail and length
2958
+ // Beware that the final length may not fit in 32 bits so we take care of that
2959
+ tmp = this._length * 8;
2960
+ tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
2961
+ lo = parseInt(tmp[2], 16);
2962
+ hi = parseInt(tmp[1], 16) || 0;
2963
+
2964
+ tail[14] = lo;
2965
+ tail[15] = hi;
2966
+ md5cycle(this._state, tail);
2967
+ };
2968
+
2969
+ /**
2970
+ * Resets the internal state of the computation.
2971
+ *
2972
+ * @return {SparkMD5} The instance itself
2973
+ */
2974
+ SparkMD5.prototype.reset = function () {
2975
+ this._buff = "";
2976
+ this._length = 0;
2977
+ this._state = [1732584193, -271733879, -1732584194, 271733878];
2978
+
2979
+ return this;
2980
+ };
2981
+
2982
+ /**
2983
+ * Releases memory used by the incremental buffer and other aditional
2984
+ * resources. If you plan to use the instance again, use reset instead.
2985
+ */
2986
+ SparkMD5.prototype.destroy = function () {
2987
+ delete this._state;
2988
+ delete this._buff;
2989
+ delete this._length;
2990
+ };
2991
+
2992
+
2993
+ /**
2994
+ * Performs the md5 hash on a string.
2995
+ * A conversion will be applied if utf8 string is detected.
2996
+ *
2997
+ * @param {String} str The string
2998
+ * @param {Boolean} raw True to get the raw result, false to get the hex result
2999
+ *
3000
+ * @return {String|Array} The result
3001
+ */
3002
+ SparkMD5.hash = function (str, raw) {
3003
+ // converts the string to utf8 bytes if necessary
3004
+ if (/[\u0080-\uFFFF]/.test(str)) {
3005
+ str = unescape(encodeURIComponent(str));
3006
+ }
3007
+
3008
+ var hash = md51(str);
3009
+
3010
+ return !!raw ? hash : hex(hash);
3011
+ };
3012
+
3013
+ /**
3014
+ * Performs the md5 hash on a binary string.
3015
+ *
3016
+ * @param {String} content The binary string
3017
+ * @param {Boolean} raw True to get the raw result, false to get the hex result
3018
+ *
3019
+ * @return {String|Array} The result
3020
+ */
3021
+ SparkMD5.hashBinary = function (content, raw) {
3022
+ var hash = md51(content);
3023
+
3024
+ return !!raw ? hash : hex(hash);
3025
+ };
3026
+
3027
+ /**
3028
+ * SparkMD5 OOP implementation for array buffers.
3029
+ *
3030
+ * Use this class to perform an incremental md5 ONLY for array buffers.
3031
+ */
3032
+ SparkMD5.ArrayBuffer = function () {
3033
+ // call reset to init the instance
3034
+ this.reset();
3035
+ };
3036
+
3037
+ ////////////////////////////////////////////////////////////////////////////
3038
+
3039
+ /**
3040
+ * Appends an array buffer.
3041
+ *
3042
+ * @param {ArrayBuffer} arr The array to be appended
3043
+ *
3044
+ * @return {SparkMD5.ArrayBuffer} The instance itself
3045
+ */
3046
+ SparkMD5.ArrayBuffer.prototype.append = function (arr) {
3047
+ // TODO: we could avoid the concatenation here but the algorithm would be more complex
3048
+ // if you find yourself needing extra performance, please make a PR.
3049
+ var buff = this._concatArrayBuffer(this._buff, arr),
3050
+ length = buff.length,
3051
+ i;
3052
+
3053
+ this._length += arr.byteLength;
3054
+
3055
+ for (i = 64; i <= length; i += 64) {
3056
+ md5cycle(this._state, md5blk_array(buff.subarray(i - 64, i)));
3057
+ }
3058
+
3059
+ // Avoids IE10 weirdness (documented above)
3060
+ this._buff = (i - 64) < length ? buff.subarray(i - 64) : new Uint8Array(0);
3061
+
3062
+ return this;
3063
+ };
3064
+
3065
+ /**
3066
+ * Finishes the incremental computation, reseting the internal state and
3067
+ * returning the result.
3068
+ * Use the raw parameter to obtain the raw result instead of the hex one.
3069
+ *
3070
+ * @param {Boolean} raw True to get the raw result, false to get the hex result
3071
+ *
3072
+ * @return {String|Array} The result
3073
+ */
3074
+ SparkMD5.ArrayBuffer.prototype.end = function (raw) {
3075
+ var buff = this._buff,
3076
+ length = buff.length,
3077
+ tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
3078
+ i,
3079
+ ret;
3080
+
3081
+ for (i = 0; i < length; i += 1) {
3082
+ tail[i >> 2] |= buff[i] << ((i % 4) << 3);
3083
+ }
3084
+
3085
+ this._finish(tail, length);
3086
+ ret = !!raw ? this._state : hex(this._state);
3087
+
3088
+ this.reset();
3089
+
3090
+ return ret;
3091
+ };
3092
+
3093
+ SparkMD5.ArrayBuffer.prototype._finish = SparkMD5.prototype._finish;
3094
+
3095
+ /**
3096
+ * Resets the internal state of the computation.
3097
+ *
3098
+ * @return {SparkMD5.ArrayBuffer} The instance itself
3099
+ */
3100
+ SparkMD5.ArrayBuffer.prototype.reset = function () {
3101
+ this._buff = new Uint8Array(0);
3102
+ this._length = 0;
3103
+ this._state = [1732584193, -271733879, -1732584194, 271733878];
3104
+
3105
+ return this;
3106
+ };
3107
+
3108
+ /**
3109
+ * Releases memory used by the incremental buffer and other aditional
3110
+ * resources. If you plan to use the instance again, use reset instead.
3111
+ */
3112
+ SparkMD5.ArrayBuffer.prototype.destroy = SparkMD5.prototype.destroy;
3113
+
3114
+ /**
3115
+ * Concats two array buffers, returning a new one.
3116
+ *
3117
+ * @param {ArrayBuffer} first The first array buffer
3118
+ * @param {ArrayBuffer} second The second array buffer
3119
+ *
3120
+ * @return {ArrayBuffer} The new array buffer
3121
+ */
3122
+ SparkMD5.ArrayBuffer.prototype._concatArrayBuffer = function (first, second) {
3123
+ var firstLength = first.length,
3124
+ result = new Uint8Array(firstLength + second.byteLength);
3125
+
3126
+ result.set(first);
3127
+ result.set(new Uint8Array(second), firstLength);
3128
+
3129
+ return result;
3130
+ };
3131
+
3132
+ /**
3133
+ * Performs the md5 hash on an array buffer.
3134
+ *
3135
+ * @param {ArrayBuffer} arr The array buffer
3136
+ * @param {Boolean} raw True to get the raw result, false to get the hex result
3137
+ *
3138
+ * @return {String|Array} The result
3139
+ */
3140
+ SparkMD5.ArrayBuffer.hash = function (arr, raw) {
3141
+ var hash = md51_array(new Uint8Array(arr));
3142
+
3143
+ return !!raw ? hash : hex(hash);
3144
+ };
3145
+
3146
+ return SparkMD5;
3147
+ }));
3148
+
3149
+ },{}],5:[function(require,module,exports){
2520
3150
  /**
2521
3151
  * Application-level APIs for nutella, browser version
2522
3152
  */
@@ -2534,7 +3164,7 @@ var AppSubModule = function(main_nutella) {
2534
3164
 
2535
3165
 
2536
3166
  module.exports = AppSubModule;
2537
- },{"./app_log":5,"./app_net":6}],5:[function(require,module,exports){
3167
+ },{"./app_log":6,"./app_net":7}],6:[function(require,module,exports){
2538
3168
  /**
2539
3169
  * App-level log APIs for nutella
2540
3170
  */
@@ -2586,7 +3216,7 @@ function logToJson( message, code, level) {
2586
3216
 
2587
3217
  module.exports = AppLogSubModule;
2588
3218
 
2589
- },{"./app_net":6}],6:[function(require,module,exports){
3219
+ },{"./app_net":7}],7:[function(require,module,exports){
2590
3220
  /**
2591
3221
  * App-level Networking APIs for nutella
2592
3222
  */
@@ -2867,7 +3497,7 @@ function extractRunId(app_id, mqtt_channel) {
2867
3497
 
2868
3498
  module.exports = AppNetSubModule;
2869
3499
 
2870
- },{"./util/net":13}],7:[function(require,module,exports){
3500
+ },{"./util/net":16}],8:[function(require,module,exports){
2871
3501
  /**
2872
3502
  * Framework-level APIs for nutella, browser version
2873
3503
  */
@@ -2885,7 +3515,7 @@ var FrSubModule = function(main_nutella) {
2885
3515
 
2886
3516
 
2887
3517
  module.exports = FrSubModule;
2888
- },{"./fr_log":8,"./fr_net":9}],8:[function(require,module,exports){
3518
+ },{"./fr_log":9,"./fr_net":10}],9:[function(require,module,exports){
2889
3519
  /**
2890
3520
  * Framework-level log APIs for nutella
2891
3521
  */
@@ -2937,7 +3567,7 @@ function logToJson( message, code, level) {
2937
3567
 
2938
3568
  module.exports = FrLogSubModule;
2939
3569
 
2940
- },{"./app_net":6}],9:[function(require,module,exports){
3570
+ },{"./app_net":7}],10:[function(require,module,exports){
2941
3571
  /**
2942
3572
  * Framework-level Networking APIs for nutella
2943
3573
  */
@@ -3438,7 +4068,7 @@ function extractAppId(mqtt_channel) {
3438
4068
 
3439
4069
  module.exports = FRNetSubModule;
3440
4070
 
3441
- },{"./util/net":13}],10:[function(require,module,exports){
4071
+ },{"./util/net":16}],11:[function(require,module,exports){
3442
4072
  /**
3443
4073
  * Run-level and App-level Nutella instances for the browser
3444
4074
  */
@@ -3450,6 +4080,7 @@ var AppSubModule = require('./app_core_browser');
3450
4080
  var FrSubModule = require('./fr_core_browser');
3451
4081
  var NetSubModule = require('./run_net');
3452
4082
  var LogSubModule = require('./run_log');
4083
+ var LocationSubModule = require('./run_location');
3453
4084
 
3454
4085
 
3455
4086
  /**
@@ -3469,6 +4100,7 @@ var RunNutellaInstance = function (broker_hostname, app_id, run_id, component_id
3469
4100
  // Initialized the various sub-modules
3470
4101
  this.net = new NetSubModule(this);
3471
4102
  this.log = new LogSubModule(this);
4103
+ this.location = new LocationSubModule(this);
3472
4104
  // Start pinging
3473
4105
  setInterval(function(){
3474
4106
  this.net.publish('pings', 'ping');
@@ -3569,7 +4201,291 @@ module.exports = {
3569
4201
  AppNutellaInstance : AppNutellaInstance,
3570
4202
  FrNutellaInstance : FrNutellaInstance
3571
4203
  };
3572
- },{"./app_core_browser":4,"./fr_core_browser":7,"./run_log":11,"./run_net":12,"simple-mqtt-client":2}],11:[function(require,module,exports){
4204
+ },{"./app_core_browser":5,"./fr_core_browser":8,"./run_location":12,"./run_log":13,"./run_net":14,"simple-mqtt-client":2}],12:[function(require,module,exports){
4205
+ var LocationSubModule = function(main_nutella) {
4206
+ this.nutella = main_nutella;
4207
+
4208
+ this._resources = {};
4209
+ this._room = undefined;
4210
+
4211
+ this._resourcesReady = false;
4212
+ this._roomReady = false;
4213
+
4214
+ var self = this;
4215
+
4216
+ // Download all resources
4217
+ this.nutella.net.request("location/resources", {}, function(reply) {
4218
+ reply.resources.forEach(function(resource) {
4219
+ self._resources[resource.rid] = resource;
4220
+ });
4221
+ self._resourcesReady = true;
4222
+
4223
+ if(self._roomReady == true && readyCallback != undefined) {
4224
+ readyCallback();
4225
+ }
4226
+ });
4227
+
4228
+ // Update resources
4229
+ this.nutella.net.subscribe("location/resources/updated", function(message) {
4230
+ var resources = message.resources;
4231
+ resources.forEach(function(resource) {
4232
+ self._resources[resource.rid] = resource;
4233
+ });
4234
+ });
4235
+
4236
+ // Add resources
4237
+ this.nutella.net.subscribe("location/resources/added", function(message) {
4238
+ var resources = message.resources;
4239
+ resources.forEach(function(resource) {
4240
+ self._resources[resource.rid] = resource;
4241
+ });
4242
+ });
4243
+
4244
+ // Remove resources
4245
+ this.nutella.net.subscribe("location/resources/removed", function(message) {
4246
+ var resources = message.resources;
4247
+ resources.forEach(function(resource) {
4248
+ delete self._resources[resource.rid];
4249
+ });
4250
+ });
4251
+
4252
+ // Download the room dimension
4253
+ this.nutella.net.request("location/room", {}, function(reply) {
4254
+ self._room = reply;
4255
+ self._roomReady = true;
4256
+
4257
+ if(self._resourcesReady == true && readyCallback != undefined) {
4258
+ readyCallback();
4259
+ }
4260
+ });
4261
+
4262
+ // Update room dimension
4263
+ this.nutella.net.subscribe("location/room/updated", function(message) {
4264
+ self._room = message;
4265
+ });
4266
+ };
4267
+
4268
+ // Resource list for notify the update
4269
+ updateResources = [];
4270
+ enterResources = [];
4271
+ exitResources = [];
4272
+
4273
+ // Enter and exit callbacks
4274
+ enterCallback = undefined;
4275
+ exitCallback = undefined;
4276
+
4277
+ // Ready callback
4278
+ readyCallback = undefined;
4279
+
4280
+
4281
+ Object.defineProperty(LocationSubModule.prototype, 'resources', {
4282
+ get: function() {
4283
+ var self = this;
4284
+
4285
+ var resources = [];
4286
+
4287
+ Object.keys(this._resources).forEach(function(key) {
4288
+ resources.push(self._resources[key]);
4289
+ });
4290
+ return resources;
4291
+ }
4292
+ });
4293
+
4294
+ Object.defineProperty(LocationSubModule.prototype, 'resource', {
4295
+ get: function() {
4296
+ var self = this;
4297
+
4298
+ var resource = {};
4299
+
4300
+ // Create a virtual resource for every resource
4301
+ Object.keys(this._resources).forEach(function(key) {
4302
+ var r = self._resources[key];
4303
+ Object.defineProperty(resource, r.rid, {
4304
+ get: function() {
4305
+ var virtualResource = generateVirtualResource(r);
4306
+ return virtualResource;
4307
+ }
4308
+ });
4309
+ });
4310
+ return resource;
4311
+ }
4312
+ });
4313
+
4314
+ Object.defineProperty(LocationSubModule.prototype, 'room', {
4315
+ get: function() {
4316
+ return this._room;
4317
+ }
4318
+ });
4319
+
4320
+ function updateResource(resource) {
4321
+ var newResource = {};
4322
+ newResource.rid = resource.rid;
4323
+ if(resource.continuous != undefined) newResource.continuous = resource.continuous;
4324
+ if(resource.discrete != undefined) newResource.discrete = resource.discrete;
4325
+
4326
+ newResource.parameters = [];
4327
+
4328
+ for(p in resource.parameters) {
4329
+ newResource.parameters.push({key: p, value: resource.parameters[p]});
4330
+ }
4331
+
4332
+ nutella.net.publish("location/resource/update", newResource);
4333
+ }
4334
+
4335
+ function generateVirtualResource(resource) {
4336
+ var virtualResource = {};
4337
+ Object.defineProperty(virtualResource, 'rid', {
4338
+ get: function() {
4339
+ return resource.rid;
4340
+ }
4341
+ });
4342
+ virtualResource.continuous = {
4343
+ get x() { return resource.continuous.x; },
4344
+ set x(value) { resource.continuous.x = value; updateResource(resource); },
4345
+
4346
+ get y() { return resource.continuous.y; },
4347
+ set y(value) { resource.continuous.y = value; updateResource(resource); }
4348
+ };
4349
+ virtualResource.discrete = {
4350
+ get x() { return resource.discrete.x; },
4351
+ set x(value) { resource.discrete.x = value; updateResource(resource); },
4352
+
4353
+ get y() { return resource.discrete.y; },
4354
+ set y(value) { resource.discrete.y = value; updateResource(resource); }
4355
+ };
4356
+ virtualResource.proximity = {
4357
+ get rid() { return resource.proximity.rid; },
4358
+ get continuous() {
4359
+ return {x: resource.proximity.continuous.x, y: resource.proximity.continuous.y};
4360
+ },
4361
+ get discrete() {
4362
+ return {x: resource.proximity.discrete.x, y: resource.proximity.discrete.y};
4363
+ }
4364
+ };
4365
+
4366
+ Object.defineProperty(virtualResource, 'notifyUpdate', {
4367
+ get: function () {
4368
+ return updateResources.indexOf(virtualResource.rid) != -1;
4369
+ },
4370
+ set: function (condition) {
4371
+ if(condition == true) {
4372
+ if (updateResources.indexOf(virtualResource.rid) == -1) {
4373
+ updateResources.push(virtualResource.rid);
4374
+ }
4375
+ }
4376
+ else {
4377
+ if (updateResources.indexOf(virtualResource.rid) != -1) {
4378
+ updateResources.remove(updateResources.indexOf(virtualResource.rid));
4379
+ }
4380
+ }
4381
+ }
4382
+ });
4383
+
4384
+
4385
+ Object.defineProperty(virtualResource, 'notifyEnter', {
4386
+ get: function () {
4387
+ return enterResources.indexOf(virtualResource.rid) != -1;
4388
+ },
4389
+ set: function (condition) {
4390
+ if(condition == true) {
4391
+ if (enterResources.indexOf(virtualResource.rid) == -1) {
4392
+ enterResources.push(virtualResource.rid);
4393
+ nutella.net.subscribe("location/resource/static/" + virtualResource.rid + "/enter", function(message) {
4394
+ message.resources.forEach(function(dynamicResource) {
4395
+ var staticVirtualResource = virtualResource;
4396
+ var dynamicVirtualResource = generateVirtualResource(dynamicResource);
4397
+ if(enterCallback != undefined) {
4398
+ enterCallback(dynamicVirtualResource, staticVirtualResource);
4399
+ }
4400
+ });
4401
+ });
4402
+ }
4403
+ }
4404
+ else {
4405
+ if (enterResources.indexOf(virtualResource.rid) != -1) {
4406
+ enterResources.splice(enterResources.indexOf(virtualResource.rid), 1);
4407
+ nutella.net.unsubscribe("location/resource/static/" + virtualResource.rid + "/enter");
4408
+ }
4409
+ }
4410
+ }
4411
+ });
4412
+
4413
+ Object.defineProperty(virtualResource, 'notifyExit', {
4414
+ get: function () {
4415
+ return exitResources.indexOf(virtualResource.rid) != -1;
4416
+ },
4417
+ set: function (condition) {
4418
+ if(condition == true) {
4419
+ if (exitResources.indexOf(virtualResource.rid) == -1) {
4420
+ exitResources.push(virtualResource.rid);
4421
+ nutella.net.subscribe("location/resource/static/" + virtualResource.rid + "/exit", function(message) {
4422
+ message.resources.forEach(function(dynamicResource) {
4423
+ var staticVirtualResource = virtualResource;
4424
+ var dynamicVirtualResource = generateVirtualResource(dynamicResource);
4425
+ if(exitCallback != undefined) {
4426
+ exitCallback(dynamicVirtualResource, staticVirtualResource);
4427
+ }
4428
+ });
4429
+ });
4430
+ }
4431
+ }
4432
+ else {
4433
+ if (exitResources.indexOf(virtualResource.rid) != -1) {
4434
+ exitResources.splice(exitResources.indexOf(virtualResource.rid), 1);
4435
+ nutella.net.unsubscribe("location/resource/static/" + virtualResource.rid + "/exit");
4436
+ }
4437
+ }
4438
+ }
4439
+ });
4440
+
4441
+ virtualResource.parameter = {};
4442
+
4443
+ var parameters = [];
4444
+ for(p in resource.parameters) {
4445
+ parameters.push({value: resource.parameters[p], key: p});
4446
+ }
4447
+ parameters.forEach(function(p) {
4448
+ Object.defineProperty(virtualResource.parameter, p.key, {
4449
+ get: function() {
4450
+ return p.value;
4451
+ },
4452
+ set: function(value) {
4453
+ resource.parameters[p.key] = value;
4454
+ updateResource(resource);
4455
+ }
4456
+ });
4457
+ });
4458
+
4459
+ return virtualResource;
4460
+ }
4461
+
4462
+ LocationSubModule.prototype.resourceUpdated = function(callback) {
4463
+ nutella.net.subscribe("location/resources/updated", function(message) {
4464
+ message.resources.forEach(function(resource) {
4465
+ var virtualResource = generateVirtualResource(resource);
4466
+ if(updateResources.indexOf(resource.rid) != -1) {
4467
+ callback(virtualResource);
4468
+ }
4469
+ });
4470
+ });
4471
+ };
4472
+
4473
+ // /location/resource/static/<rid>/enter
4474
+ LocationSubModule.prototype.resourceEntered = function(callback) {
4475
+ enterCallback = callback;
4476
+ };
4477
+
4478
+ LocationSubModule.prototype.resourceExited = function(callback) {
4479
+ exitCallback = callback;
4480
+ };
4481
+
4482
+ LocationSubModule.prototype.ready = function(callback) {
4483
+ readyCallback = callback;
4484
+ };
4485
+
4486
+ module.exports = LocationSubModule;
4487
+
4488
+ },{}],13:[function(require,module,exports){
3573
4489
  /**
3574
4490
  * Run-level Logging APIs for nutella
3575
4491
  */
@@ -3621,13 +4537,14 @@ function logToJson( message, code, level) {
3621
4537
 
3622
4538
 
3623
4539
  module.exports = LogSubModule;
3624
- },{"./run_net":12}],12:[function(require,module,exports){
4540
+ },{"./run_net":14}],14:[function(require,module,exports){
3625
4541
  /**
3626
4542
  * Run-level Network APIs for nutella
3627
4543
  */
3628
4544
 
3629
4545
 
3630
4546
  var AbstractNet = require('./util/net');
4547
+ var BinNet = require('./run_net_bin');
3631
4548
 
3632
4549
 
3633
4550
  /**
@@ -3639,6 +4556,8 @@ var NetSubModule = function(main_nutella) {
3639
4556
  // Store a reference to the main module
3640
4557
  this.nutella = main_nutella;
3641
4558
  this.net = new AbstractNet(main_nutella);
4559
+ // Binary net sub module
4560
+ this.bin = new BinNet(main_nutella, this);
3642
4561
  };
3643
4562
 
3644
4563
 
@@ -3707,7 +4626,168 @@ NetSubModule.prototype.handle_requests = function(channel, callback, done_callba
3707
4626
 
3708
4627
  module.exports = NetSubModule;
3709
4628
 
3710
- },{"./util/net":13}],13:[function(require,module,exports){
4629
+ },{"./run_net_bin":15,"./util/net":16}],15:[function(require,module,exports){
4630
+ /**
4631
+ * Run-level binary network APIs for nutella
4632
+ */
4633
+
4634
+
4635
+ var SparkMD5 = require('spark-md5');
4636
+
4637
+
4638
+ /**
4639
+ * Run-level binary network APIs for nutella
4640
+ * @param main_nutella
4641
+ * @constructor
4642
+ */
4643
+ var BinNetSubModule = function(main_nutella, net_sub_module) {
4644
+ // Store a reference to the main module
4645
+ this.nutella = main_nutella;
4646
+ this.net = net_sub_module;
4647
+ this.file_mngr_url = 'http://' + main_nutella.mqtt_client.getHost() + ':57882';
4648
+ };
4649
+
4650
+
4651
+
4652
+ /**
4653
+ * Uploads a file to the nutella file server
4654
+ * @param {File} file - the file we are uploading
4655
+ * @param cb - the callback fired whenever a file is correctly uploaded
4656
+ */
4657
+ BinNetSubModule.prototype.uploadFile = function(file, cb) {
4658
+ var file_mngr_url = this.file_mngr_url;
4659
+ var reader = new FileReader();
4660
+ reader.onload = function(event) {
4661
+ // 2. calculate md5 hash
4662
+ var hexHash = SparkMD5.ArrayBuffer.hash(event.target.result );
4663
+ var extension = getFileExtension(file);
4664
+ var filename = hexHash + '.' + extension;
4665
+ // 3. check if the file is already stored and, if so, get the url
4666
+ isAlreadyUploaded(file_mngr_url, filename, function(fileURL) {
4667
+ // 4a. if it does, execute callback and pass the file url
4668
+ cb(fileURL);
4669
+ }, function() {
4670
+ // 4b. if it doesn't, upload
4671
+ upload(file_mngr_url, file, filename, function(fileURL) {
4672
+ // 5. execute callback and pass the file url
4673
+ cb(fileURL);
4674
+ });
4675
+ });
4676
+ };
4677
+ // 1. read file
4678
+ reader.readAsArrayBuffer(file);
4679
+ };
4680
+
4681
+
4682
+ //
4683
+ // Helper function
4684
+ // Extracts the extension from a file object
4685
+ //
4686
+ function getFileExtension(file) {
4687
+ return file.name.substring(file.name.lastIndexOf('.')+1, file.name.length).toLowerCase()
4688
+ }
4689
+
4690
+
4691
+ //
4692
+ // Helper function
4693
+ // This function checks if a particular filename already exists.
4694
+ // If so it executes the first callback that is passed,
4695
+ // otherwise the second one
4696
+ //
4697
+ function isAlreadyUploaded(file_mngr_url, filename, file_exists_cb, file_absent_cb) {
4698
+ var req = new XMLHttpRequest();
4699
+ req.open("GET", file_mngr_url + "/test/" + filename);
4700
+ req.onload = function(e) {
4701
+ var url = JSON.parse(req.response).url;
4702
+ if (url === undefined)
4703
+ file_absent_cb();
4704
+ else
4705
+ file_exists_cb(url);
4706
+ };
4707
+ req.send();
4708
+ }
4709
+
4710
+
4711
+ //
4712
+ // Helper function
4713
+ // This function uploads a file with a certain file name.
4714
+ // If the upload is successful the first callback is executed,
4715
+ // otherwise the second one is.
4716
+ function upload(file_mngr_url, file, filename, success, error) {
4717
+ // Assemble data
4718
+ var fd = new FormData();
4719
+ fd.append("filename", filename);
4720
+ fd.append("file", file);
4721
+ var req = new XMLHttpRequest();
4722
+ req.open("POST", file_mngr_url + "/upload");
4723
+ req.onload = function(e) {
4724
+ var url = JSON.parse(req.response).url;
4725
+ if (url === undefined)
4726
+ error();
4727
+ else
4728
+ success(url);
4729
+ };
4730
+ req.send(fd);
4731
+ }
4732
+
4733
+
4734
+
4735
+ /**
4736
+ * Subscribes to a channel for binary files uptes.
4737
+ *
4738
+ * @param channel this can only be a simple channel not
4739
+ * @param cb it takes two parameters, file and metadata
4740
+ * @param done_callback
4741
+ */
4742
+ BinNetSubModule.prototype.subscribe = function(channel, cb, done_callback) {
4743
+ this.net.subscribe(channel, function(message, from) {
4744
+ // Discard non-bin message
4745
+ if (!message.bin) return;
4746
+ // Execute callback
4747
+ cb(message.url, message.metadata);
4748
+ }, done_callback);
4749
+ };
4750
+
4751
+
4752
+
4753
+ /**
4754
+ * Unsubscribes from a channel
4755
+ *
4756
+ * @param channel
4757
+ * @param done_callback
4758
+ */
4759
+ BinNetSubModule.prototype.unsubscribe = function(channel, done_callback) {
4760
+ this.net.unsubscribe(channel, done_callback);
4761
+ };
4762
+
4763
+
4764
+
4765
+ /**
4766
+ * Publishes a binary file to a certain channel.
4767
+ *
4768
+ * @param channel
4769
+ * @param file File object https://developer.mozilla.org/en-US/docs/Web/API/File
4770
+ * @param done_callback
4771
+ */
4772
+ BinNetSubModule.prototype.publish = function(channel, file, metadata, done_callback) {
4773
+ var net_mod = this.net;
4774
+ this.uploadFile(file, function(url) {
4775
+ net_mod.publish(channel, {bin: true, url: url, metadata: metadata});
4776
+ // Execute optional done callback
4777
+ if (done_callback!==undefined) done_callback();
4778
+ });
4779
+ };
4780
+
4781
+
4782
+
4783
+
4784
+
4785
+
4786
+
4787
+
4788
+
4789
+ module.exports = BinNetSubModule;
4790
+ },{"spark-md5":4}],16:[function(require,module,exports){
3711
4791
  /**
3712
4792
  * Network APIs abstraction
3713
4793
  */
@@ -3796,7 +4876,7 @@ AbstractNet.prototype.subscribe_to = function(channel, callback, appId, runId, d
3796
4876
  */
3797
4877
  AbstractNet.prototype.unsubscribe_from = function(channel, appId, runId, done_callback ) {
3798
4878
  // Pad channel
3799
- var padded_channel = this.pad_channel(channel, appId, run_id);
4879
+ var padded_channel = this.pad_channel(channel, appId, runId);
3800
4880
  var idx = this.subscriptions.indexOf(padded_channel);
3801
4881
  // If we are not subscribed to this channel, return (no error is given)
3802
4882
  if(idx===-1) return;
@@ -4035,5 +5115,7 @@ AbstractNet.prototype.prepare_message_for_response = function (response, id) {
4035
5115
 
4036
5116
  // Export module
4037
5117
  module.exports = AbstractNet;
5118
+ },{}],17:[function(require,module,exports){
5119
+ module.exports.version = '0.5.4';
4038
5120
  },{}]},{},[1])(1)
4039
5121
  });