kmz_compressor 1.0.1 → 1.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/app/assets/javascripts/kmz_compressor.js +2 -0
- data/app/assets/javascripts/kmz_compressor/map_layer_manager.js +197 -0
- data/app/assets/javascripts/kmz_compressor/sha2.js +144 -0
- data/lib/kmz_compressor.rb +4 -1
- data/lib/kmz_compressor/engine.rb +4 -0
- data/lib/kmz_compressor/middleware.rb +42 -11
- data/lib/kmz_compressor/railtie.rb +5 -1
- data/lib/kmz_compressor/version.rb +1 -1
- metadata +43 -21
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 251ce4661a596713815ea8aa4c4d1f02bc355dc5
|
4
|
+
data.tar.gz: f8a0fa808a8b9c2b7516bcf8d7e286d5a0da7005
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7619248e41ee3a9abfa21ff714e5b8058f506c0931f25aaef662a70111eb3028568c3b6c0cfb0ac87a53e2615e9576215735e48432ec9c867a650b3b6fed7cfa
|
7
|
+
data.tar.gz: f86124232607e3dcf036fec6e3aa4980c29b143cd4ecf073d7ad18c00fbcac52a6b213fa3473bd41fd837d82549ca56863753db32f3764a5ecea6fb566ff6520
|
@@ -0,0 +1,197 @@
|
|
1
|
+
MapLayerManager = {
|
2
|
+
host: location.protocol + "//" + location.host,
|
3
|
+
layers: [],
|
4
|
+
loadingCount: 0, // How many layers are being loaded
|
5
|
+
requestTimestamps: { },
|
6
|
+
layerLoadingEventName: 'map:layerLoading',
|
7
|
+
layerLoadedEventName: 'map:layerLoaded',
|
8
|
+
|
9
|
+
// Prime the KMZ cache on the server before unleashing google's many tilemills
|
10
|
+
cacheAndLoadKMLLayer: function(map, kmlPath, layerName, options) {
|
11
|
+
var requestTimestamp = new Date;
|
12
|
+
kmlPath = this.sanitizeURI(kmlPath);
|
13
|
+
|
14
|
+
$.ajax(this.host + kmlPath, {type:'head', complete:function(){
|
15
|
+
if (!MapLayerManager.requestTimestamps[layerName] || MapLayerManager.requestTimestamps[layerName] < requestTimestamp){
|
16
|
+
MapLayerManager.requestTimestamps[layerName] = requestTimestamp;
|
17
|
+
MapLayerManager.loadKMLLayer(map, MapLayerManager.cachedKMZPath(kmlPath), layerName, options)
|
18
|
+
}
|
19
|
+
}});
|
20
|
+
},
|
21
|
+
loadKMLLayer: function(map, kmlPath, layerName, options) {
|
22
|
+
// Replace spaces with pluses so we don't have problems with some things turning them into %20s and some not
|
23
|
+
kmlPath = this.sanitizeURI(kmlPath);
|
24
|
+
options = options || {}
|
25
|
+
options.map = map;
|
26
|
+
|
27
|
+
var kmlLayer = new google.maps.KmlLayer(this.host + kmlPath, options);
|
28
|
+
var layer = MapLayerManager.addLayer(layerName, kmlLayer)
|
29
|
+
this.loadingCount++
|
30
|
+
$(window.document).trigger({type: this.layerLoadingEventName, layer:layer})
|
31
|
+
|
32
|
+
// Try and catch the defaultviewport_changed event so we can remove the old layer (sometimes this works, sometimes not)
|
33
|
+
google.maps.event.addListener(kmlLayer, 'defaultviewport_changed', function(){
|
34
|
+
MapLayerManager.sweep();
|
35
|
+
});
|
36
|
+
|
37
|
+
// Add a listener to catch clicks and close all info windows on other layers
|
38
|
+
google.maps.event.addListener(kmlLayer, 'click', function(){
|
39
|
+
MapLayerManager.everyLayer(function(layer){
|
40
|
+
if (layer.kml != kmlLayer){ // Don't close this layer's info window
|
41
|
+
layer.kml.setOptions({suppressInfoWindows:true})
|
42
|
+
layer.kml.setOptions({suppressInfoWindows:false})
|
43
|
+
}
|
44
|
+
})
|
45
|
+
});
|
46
|
+
},
|
47
|
+
// Generates the url of the cached KMZ for the given kmlPath
|
48
|
+
cachedKMZPath: function(kmlPath){
|
49
|
+
return '/kmz/' + hex_sha256(kmlPath) + '.kmz'
|
50
|
+
},
|
51
|
+
centerWhenLoaded: function(map, layerNames){
|
52
|
+
var handler = function(){
|
53
|
+
// If we have no layer names
|
54
|
+
if (!layerNames || layerNames.length == 0){
|
55
|
+
layerNames = MapLayerManager.layerNames()
|
56
|
+
}
|
57
|
+
|
58
|
+
if (MapLayerManager.layersLoaded(layerNames)){
|
59
|
+
$(window.document).unbind(MapLayerManager.layerLoadedEventName, handler)
|
60
|
+
MapLayerManager.centerOnLayers(map, layerNames);
|
61
|
+
}
|
62
|
+
}
|
63
|
+
|
64
|
+
$(window.document).bind(this.layerLoadedEventName, handler)
|
65
|
+
},
|
66
|
+
// Returns the layer names
|
67
|
+
layerNames: function(){
|
68
|
+
return $(this.layers.slice(0)).map(function(){return this.name})
|
69
|
+
},
|
70
|
+
addLayer: function(layerName, kml){
|
71
|
+
this.layers.unshift({name:layerName, kml:kml})
|
72
|
+
return this.layers[0]
|
73
|
+
},
|
74
|
+
getLayer: function(layerName){
|
75
|
+
var desiredLayer
|
76
|
+
this.everyLayer(function(layer, index){
|
77
|
+
if (layer.name == layerName){
|
78
|
+
desiredLayer = layer
|
79
|
+
return false;
|
80
|
+
}
|
81
|
+
})
|
82
|
+
return desiredLayer
|
83
|
+
},
|
84
|
+
// Shows the layer and returns true, returns false if the layer couldn't be hidden
|
85
|
+
hideLayer: function(layerName){
|
86
|
+
var layer = this.getLayer(layerName);
|
87
|
+
if (layer && layer.kml){
|
88
|
+
layer.oldMap = layer.kml.getMap();
|
89
|
+
layer.kml.setMap(null)
|
90
|
+
layer.hidden = true
|
91
|
+
return true
|
92
|
+
} else if (layer) {
|
93
|
+
layer.hidden = true
|
94
|
+
} else {
|
95
|
+
return false
|
96
|
+
}
|
97
|
+
},
|
98
|
+
// Shows the layer and returns true, returns false if the layer couldn't be shown
|
99
|
+
showLayer: function(layerName){
|
100
|
+
var layer = this.getLayer(layerName);
|
101
|
+
if (layer && layer.kml && layer.oldMap){
|
102
|
+
layer.kml.setMap(layer.oldMap);
|
103
|
+
layer.oldMap = null
|
104
|
+
layer.hidden = false
|
105
|
+
return true
|
106
|
+
} else {
|
107
|
+
return false
|
108
|
+
}
|
109
|
+
},
|
110
|
+
layersLoaded: function(layerNames){
|
111
|
+
for (var i = 0; i < layerNames.length; i++){
|
112
|
+
var layer = this.getLayer(layerNames[i]);
|
113
|
+
if (!layer || !layer.loaded){
|
114
|
+
return false;
|
115
|
+
}
|
116
|
+
}
|
117
|
+
return true
|
118
|
+
},
|
119
|
+
centerOnLayers: function(map, layerNames){
|
120
|
+
var bounds;
|
121
|
+
|
122
|
+
for (var i = 0; i < layerNames.length; i++){
|
123
|
+
var layer = this.getLayer(layerNames[i])
|
124
|
+
if (layer.error){
|
125
|
+
continue
|
126
|
+
}
|
127
|
+
|
128
|
+
if (layer.kml.getDefaultViewport().toSpan().toString() != "(180, 360)"){
|
129
|
+
bounds = bounds || layer.kml.getDefaultViewport();
|
130
|
+
bounds.union(layer.kml.getDefaultViewport());
|
131
|
+
}
|
132
|
+
}
|
133
|
+
if (bounds){
|
134
|
+
map.fitBounds(bounds);
|
135
|
+
}
|
136
|
+
},
|
137
|
+
removeLayer: function(layerName){
|
138
|
+
this.everyLayer(function(layer, index){
|
139
|
+
if (layer.name == layerName){
|
140
|
+
layer.kml.setMap(null)
|
141
|
+
MapLayerManager.layers.splice(index, 1);
|
142
|
+
return;
|
143
|
+
}
|
144
|
+
});
|
145
|
+
},
|
146
|
+
removeLayers: function(){
|
147
|
+
this.everyLayer(function(layer){
|
148
|
+
MapLayerManager.removeLayer(layer.name);
|
149
|
+
})
|
150
|
+
},
|
151
|
+
everyLayer: function(fn){
|
152
|
+
// NOTE: We use an iterator instead of a for loop because modifications to this.layers that occur during iteration can mess us up
|
153
|
+
// e.g. if we're responding to an event during the loop and the event adds a layer, we may end up re-iterating on a layer we've already processed
|
154
|
+
$.each(this.layers.slice(0), function(index, layer){
|
155
|
+
fn(layer, index);
|
156
|
+
})
|
157
|
+
},
|
158
|
+
|
159
|
+
// Keep layers synced with their state
|
160
|
+
sweep: function(){
|
161
|
+
var foundLayers = [];
|
162
|
+
this.everyLayer(function(layer, index){
|
163
|
+
var kmlStatus = layer.kml ? layer.kml.getStatus() : null;
|
164
|
+
|
165
|
+
// If the layer just finished loading
|
166
|
+
if (!layer.loaded && kmlStatus) {
|
167
|
+
MapLayerManager.loadingCount--
|
168
|
+
layer.loaded = true
|
169
|
+
layer.error = kmlStatus == 'OK' ? null : kmlStatus // if there were any errors, record them
|
170
|
+
$(window.document).trigger({type: MapLayerManager.layerLoadedEventName, layer:layer})
|
171
|
+
}
|
172
|
+
|
173
|
+
// A layer should be hidden, but the kml is showing, hide it (i.e. correct layers that were hidden before the kml was loaded)
|
174
|
+
if (layer.hidden && layer.loaded && layer.kml.getMap()){
|
175
|
+
MapLayerManager.hideLayer(layer.name)
|
176
|
+
}
|
177
|
+
|
178
|
+
// Remove old layers
|
179
|
+
// Sweep through layers from the newest to oldest, if a layer name is seen more than once, delete all but the newest
|
180
|
+
// Don't delete an instance if we haven't yet seen a version of it with status 'OK'
|
181
|
+
if ($.inArray(layer.name, foundLayers) > -1){
|
182
|
+
layer.kml.setMap(null);
|
183
|
+
MapLayerManager.layers.splice(index, 1);
|
184
|
+
} else if (layer.loaded) {
|
185
|
+
foundLayers.push(layer.name)
|
186
|
+
}
|
187
|
+
})
|
188
|
+
},
|
189
|
+
sanitizeURI: function(uri){
|
190
|
+
// Replace spaces with pluses so we don't have problems with some things turning them into %20s and some not
|
191
|
+
// Matches the middleware process
|
192
|
+
return encodeURI(decodeURI(uri))
|
193
|
+
}
|
194
|
+
};
|
195
|
+
|
196
|
+
// Because google events sometimes get missed, we ensure we're up to date every now and again
|
197
|
+
setInterval(function(){MapLayerManager.sweep()}, 1000)
|
@@ -0,0 +1,144 @@
|
|
1
|
+
/* A JavaScript implementation of the Secure Hash Standard
|
2
|
+
* Version 0.3 Copyright Angel Marin 2003-2004 - http://anmar.eu.org/
|
3
|
+
* Distributed under the BSD License
|
4
|
+
* Some bits taken from Paul Johnston's SHA-1 implementation
|
5
|
+
*/
|
6
|
+
var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */
|
7
|
+
var hexcase = 0;/* hex output format. 0 - lowercase; 1 - uppercase */
|
8
|
+
|
9
|
+
function safe_add (x, y) {
|
10
|
+
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
|
11
|
+
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
|
12
|
+
return (msw << 16) | (lsw & 0xFFFF);
|
13
|
+
}
|
14
|
+
|
15
|
+
function S (X, n) {return ( X >>> n ) | (X << (32 - n));}
|
16
|
+
|
17
|
+
function R (X, n) {return ( X >>> n );}
|
18
|
+
|
19
|
+
function Ch(x, y, z) {return ((x & y) ^ ((~x) & z));}
|
20
|
+
|
21
|
+
function Maj(x, y, z) {return ((x & y) ^ (x & z) ^ (y & z));}
|
22
|
+
|
23
|
+
function Sigma0256(x) {return (S(x, 2) ^ S(x, 13) ^ S(x, 22));}
|
24
|
+
|
25
|
+
function Sigma1256(x) {return (S(x, 6) ^ S(x, 11) ^ S(x, 25));}
|
26
|
+
|
27
|
+
function Gamma0256(x) {return (S(x, 7) ^ S(x, 18) ^ R(x, 3));}
|
28
|
+
|
29
|
+
function Gamma1256(x) {return (S(x, 17) ^ S(x, 19) ^ R(x, 10));}
|
30
|
+
|
31
|
+
function Sigma0512(x) {return (S(x, 28) ^ S(x, 34) ^ S(x, 39));}
|
32
|
+
|
33
|
+
function Sigma1512(x) {return (S(x, 14) ^ S(x, 18) ^ S(x, 41));}
|
34
|
+
|
35
|
+
function Gamma0512(x) {return (S(x, 1) ^ S(x, 8) ^ R(x, 7));}
|
36
|
+
|
37
|
+
function Gamma1512(x) {return (S(x, 19) ^ S(x, 61) ^ R(x, 6));}
|
38
|
+
|
39
|
+
function core_sha256 (m, l) {
|
40
|
+
var K = new Array(0x428A2F98,0x71374491,0xB5C0FBCF,0xE9B5DBA5,0x3956C25B,0x59F111F1,0x923F82A4,0xAB1C5ED5,0xD807AA98,0x12835B01,0x243185BE,0x550C7DC3,0x72BE5D74,0x80DEB1FE,0x9BDC06A7,0xC19BF174,0xE49B69C1,0xEFBE4786,0xFC19DC6,0x240CA1CC,0x2DE92C6F,0x4A7484AA,0x5CB0A9DC,0x76F988DA,0x983E5152,0xA831C66D,0xB00327C8,0xBF597FC7,0xC6E00BF3,0xD5A79147,0x6CA6351,0x14292967,0x27B70A85,0x2E1B2138,0x4D2C6DFC,0x53380D13,0x650A7354,0x766A0ABB,0x81C2C92E,0x92722C85,0xA2BFE8A1,0xA81A664B,0xC24B8B70,0xC76C51A3,0xD192E819,0xD6990624,0xF40E3585,0x106AA070,0x19A4C116,0x1E376C08,0x2748774C,0x34B0BCB5,0x391C0CB3,0x4ED8AA4A,0x5B9CCA4F,0x682E6FF3,0x748F82EE,0x78A5636F,0x84C87814,0x8CC70208,0x90BEFFFA,0xA4506CEB,0xBEF9A3F7,0xC67178F2);
|
41
|
+
var HASH = new Array(0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19);
|
42
|
+
var W = new Array(64);
|
43
|
+
var a, b, c, d, e, f, g, h, i, j;
|
44
|
+
var T1, T2;
|
45
|
+
|
46
|
+
/* append padding */
|
47
|
+
m[l >> 5] |= 0x80 << (24 - l % 32);
|
48
|
+
m[((l + 64 >> 9) << 4) + 15] = l;
|
49
|
+
|
50
|
+
for ( var i = 0; i<m.length; i+=16 ) {
|
51
|
+
a = HASH[0];
|
52
|
+
b = HASH[1];
|
53
|
+
c = HASH[2];
|
54
|
+
d = HASH[3];
|
55
|
+
e = HASH[4];
|
56
|
+
f = HASH[5];
|
57
|
+
g = HASH[6];
|
58
|
+
h = HASH[7];
|
59
|
+
|
60
|
+
for ( var j = 0; j<64; j++) {
|
61
|
+
if (j < 16) W[j] = m[j + i];
|
62
|
+
else W[j] = safe_add(safe_add(safe_add(Gamma1256(W[j - 2]), W[j - 7]), Gamma0256(W[j - 15])), W[j - 16]);
|
63
|
+
|
64
|
+
T1 = safe_add(safe_add(safe_add(safe_add(h, Sigma1256(e)), Ch(e, f, g)), K[j]), W[j]);
|
65
|
+
T2 = safe_add(Sigma0256(a), Maj(a, b, c));
|
66
|
+
|
67
|
+
h = g;
|
68
|
+
g = f;
|
69
|
+
f = e;
|
70
|
+
e = safe_add(d, T1);
|
71
|
+
d = c;
|
72
|
+
c = b;
|
73
|
+
b = a;
|
74
|
+
a = safe_add(T1, T2);
|
75
|
+
}
|
76
|
+
|
77
|
+
HASH[0] = safe_add(a, HASH[0]);
|
78
|
+
HASH[1] = safe_add(b, HASH[1]);
|
79
|
+
HASH[2] = safe_add(c, HASH[2]);
|
80
|
+
HASH[3] = safe_add(d, HASH[3]);
|
81
|
+
HASH[4] = safe_add(e, HASH[4]);
|
82
|
+
HASH[5] = safe_add(f, HASH[5]);
|
83
|
+
HASH[6] = safe_add(g, HASH[6]);
|
84
|
+
HASH[7] = safe_add(h, HASH[7]);
|
85
|
+
}
|
86
|
+
return HASH;
|
87
|
+
}
|
88
|
+
|
89
|
+
function core_sha512 (m, l) {
|
90
|
+
var K = new Array(0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, 0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694, 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, 0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4, 0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70, 0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df, 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b, 0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30, 0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8, 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8, 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, 0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec, 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b, 0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, 0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b, 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c, 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817);
|
91
|
+
var HASH = new Array(0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, 0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179);
|
92
|
+
var W = new Array(80);
|
93
|
+
var a, b, c, d, e, f, g, h, i, j;
|
94
|
+
var T1, T2;
|
95
|
+
|
96
|
+
}
|
97
|
+
|
98
|
+
function str2binb (str) {
|
99
|
+
var bin = Array();
|
100
|
+
var mask = (1 << chrsz) - 1;
|
101
|
+
for(var i = 0; i < str.length * chrsz; i += chrsz)
|
102
|
+
bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (24 - i%32);
|
103
|
+
return bin;
|
104
|
+
}
|
105
|
+
|
106
|
+
function binb2str (bin) {
|
107
|
+
var str = "";
|
108
|
+
var mask = (1 << chrsz) - 1;
|
109
|
+
for(var i = 0; i < bin.length * 32; i += chrsz)
|
110
|
+
str += String.fromCharCode((bin[i>>5] >>> (24 - i%32)) & mask);
|
111
|
+
return str;
|
112
|
+
}
|
113
|
+
|
114
|
+
function binb2hex (binarray) {
|
115
|
+
var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
|
116
|
+
var str = "";
|
117
|
+
for(var i = 0; i < binarray.length * 4; i++)
|
118
|
+
{
|
119
|
+
str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) +
|
120
|
+
hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF);
|
121
|
+
}
|
122
|
+
return str;
|
123
|
+
}
|
124
|
+
|
125
|
+
function binb2b64 (binarray) {
|
126
|
+
var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
127
|
+
var str = "";
|
128
|
+
for(var i = 0; i < binarray.length * 4; i += 3)
|
129
|
+
{
|
130
|
+
var triplet = (((binarray[i >> 2] >> 8 * (3 - i %4)) & 0xFF) << 16)
|
131
|
+
| (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 )
|
132
|
+
| ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF);
|
133
|
+
for(var j = 0; j < 4; j++)
|
134
|
+
{
|
135
|
+
if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
|
136
|
+
else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
|
137
|
+
}
|
138
|
+
}
|
139
|
+
return str;
|
140
|
+
}
|
141
|
+
|
142
|
+
function hex_sha256(s){return binb2hex(core_sha256(str2binb(s),s.length * chrsz));}
|
143
|
+
function b64_sha256(s){return binb2b64(core_sha256(str2binb(s),s.length * chrsz));}
|
144
|
+
function str_sha256(s){return binb2str(core_sha256(str2binb(s),s.length * chrsz));}
|
data/lib/kmz_compressor.rb
CHANGED
@@ -3,23 +3,54 @@ module KMZCompressor
|
|
3
3
|
def initialize(app)
|
4
4
|
@app = app
|
5
5
|
end
|
6
|
-
|
6
|
+
|
7
7
|
def call(env)
|
8
|
-
|
8
|
+
request = Rack::Request.new(env)
|
9
|
+
|
10
|
+
# If the User is asking for a KMZ file
|
11
|
+
if request.path_info.end_with? '.kmz'
|
12
|
+
# HACK: Firefox 'helps' us out by encoding apostrophes as %27 in AJAX requests, However its encodeURI method
|
13
|
+
# does not. This difference causes a mismatch between the browser's cached KMZ path, and the server.
|
14
|
+
# This hack undoes the damage. See https://bugzilla.mozilla.org/show_bug.cgi?id=407172
|
15
|
+
recoded_uri = URI.encode(URI.decode(request.fullpath))
|
16
|
+
|
17
|
+
# HACK: Also encode brackets of nested params because the javascript version does, but the ruby version does not
|
18
|
+
recoded_uri = recoded_uri.gsub('[', '%5B').gsub(']','%5D')
|
19
|
+
|
20
|
+
# Use a hash of the request path (before we gsub it) as the filename we will save on the HD
|
21
|
+
cache_path = "public/kmz/#{Digest::SHA2.hexdigest(recoded_uri)}.kmz"
|
22
|
+
file_exists = File.exists?(cache_path)
|
9
23
|
|
10
|
-
|
11
|
-
|
24
|
+
if file_exists
|
25
|
+
status = 200
|
26
|
+
headers = {'Last-Modified' => File.mtime(cache_path).httpdate}
|
27
|
+
response = File.open(cache_path)
|
28
|
+
else
|
29
|
+
# Ask Rails for KML instead of KMZ
|
30
|
+
request.path_info = request.path_info.gsub(/kmz\Z/, 'kml')
|
31
|
+
status, headers, response = @app.call(env)
|
32
|
+
status = status.to_i
|
33
|
+
end
|
12
34
|
|
13
|
-
|
35
|
+
if status == 200
|
36
|
+
# Set the Content-Type to KMZ
|
37
|
+
headers['Content-Type'] = 'application/vnd.google-earth.kmz'
|
38
|
+
end
|
14
39
|
|
15
|
-
|
40
|
+
if status == 200 && !file_exists
|
41
|
+
# Zip the KML response and save it on the HD
|
42
|
+
FileUtils.mkdir_p(File.dirname(cache_path))
|
43
|
+
response = Zippy.create(cache_path) do |zip|
|
44
|
+
zip['doc.kml'] = response.body
|
45
|
+
end
|
46
|
+
response = [response.data]
|
47
|
+
end
|
48
|
+
|
49
|
+
# Return the response to the next middleware in the chain
|
50
|
+
[status, headers, response]
|
16
51
|
else
|
17
52
|
@app.call(env)
|
18
53
|
end
|
19
54
|
end
|
20
|
-
|
21
|
-
def each(&block)
|
22
|
-
block.call(Zippy.new {|zip| zip['doc.kml'] = @response.body }.data)
|
23
|
-
end
|
24
55
|
end
|
25
|
-
end
|
56
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'digest'
|
1
3
|
require 'zippy'
|
2
4
|
require 'kmz_compressor/middleware'
|
3
5
|
|
@@ -5,6 +7,8 @@ module KMZCompressor
|
|
5
7
|
class Railtie < Rails::Railtie
|
6
8
|
initializer "kmz_compressor.init" do |app|
|
7
9
|
app.config.middleware.use "KMZCompressor::Middleware"
|
10
|
+
|
11
|
+
Mime::Type.register "application/vnd.google-earth.kml+xml", :kml
|
8
12
|
end
|
9
13
|
end
|
10
|
-
end
|
14
|
+
end
|
metadata
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kmz_compressor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
5
|
-
prerelease:
|
4
|
+
version: 1.0.5
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Ryan Wallace
|
@@ -10,30 +9,50 @@ authors:
|
|
10
9
|
autorequire:
|
11
10
|
bindir: bin
|
12
11
|
cert_chain: []
|
13
|
-
date:
|
12
|
+
date: 2014-02-05 00:00:00.000000000 Z
|
14
13
|
dependencies:
|
15
14
|
- !ruby/object:Gem::Dependency
|
16
15
|
name: rails
|
17
|
-
requirement:
|
18
|
-
none: false
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
19
17
|
requirements:
|
20
|
-
- - ~>
|
18
|
+
- - "~>"
|
21
19
|
- !ruby/object:Gem::Version
|
22
|
-
version: 3.1
|
20
|
+
version: '3.1'
|
23
21
|
type: :runtime
|
24
22
|
prerelease: false
|
25
|
-
version_requirements:
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - "~>"
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '3.1'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: rubyzip
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - '='
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: 0.9.9
|
35
|
+
type: :runtime
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - '='
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: 0.9.9
|
26
42
|
- !ruby/object:Gem::Dependency
|
27
43
|
name: zippy
|
28
|
-
requirement:
|
29
|
-
none: false
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
30
45
|
requirements:
|
31
|
-
- - ~>
|
46
|
+
- - "~>"
|
32
47
|
- !ruby/object:Gem::Version
|
33
48
|
version: 0.1.0
|
34
49
|
type: :runtime
|
35
50
|
prerelease: false
|
36
|
-
version_requirements:
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - "~>"
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: 0.1.0
|
37
56
|
description: Rack Middleware which retrieves KML from Rails and produces KMZ for the
|
38
57
|
client.
|
39
58
|
email:
|
@@ -42,34 +61,37 @@ executables: []
|
|
42
61
|
extensions: []
|
43
62
|
extra_rdoc_files: []
|
44
63
|
files:
|
64
|
+
- MIT-LICENSE
|
65
|
+
- README.rdoc
|
66
|
+
- app/assets/javascripts/kmz_compressor.js
|
67
|
+
- app/assets/javascripts/kmz_compressor/map_layer_manager.js
|
68
|
+
- app/assets/javascripts/kmz_compressor/sha2.js
|
69
|
+
- lib/kmz_compressor.rb
|
70
|
+
- lib/kmz_compressor/engine.rb
|
45
71
|
- lib/kmz_compressor/middleware.rb
|
46
72
|
- lib/kmz_compressor/railtie.rb
|
47
73
|
- lib/kmz_compressor/version.rb
|
48
|
-
- lib/kmz_compressor.rb
|
49
|
-
- MIT-LICENSE
|
50
|
-
- README.rdoc
|
51
74
|
homepage: http://github.com/culturecode/kmz_compressor
|
52
75
|
licenses: []
|
76
|
+
metadata: {}
|
53
77
|
post_install_message:
|
54
78
|
rdoc_options: []
|
55
79
|
require_paths:
|
56
80
|
- lib
|
57
81
|
required_ruby_version: !ruby/object:Gem::Requirement
|
58
|
-
none: false
|
59
82
|
requirements:
|
60
|
-
- -
|
83
|
+
- - ">="
|
61
84
|
- !ruby/object:Gem::Version
|
62
85
|
version: '0'
|
63
86
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
64
|
-
none: false
|
65
87
|
requirements:
|
66
|
-
- -
|
88
|
+
- - ">="
|
67
89
|
- !ruby/object:Gem::Version
|
68
90
|
version: '0'
|
69
91
|
requirements: []
|
70
92
|
rubyforge_project:
|
71
|
-
rubygems_version:
|
93
|
+
rubygems_version: 2.2.1
|
72
94
|
signing_key:
|
73
|
-
specification_version:
|
95
|
+
specification_version: 4
|
74
96
|
summary: Rack Middleware which retrieves KML from Rails and produces KMZ for the client.
|
75
97
|
test_files: []
|