nutella_framework 0.4.18 → 0.4.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
  });