rvnstat 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (271) hide show
  1. checksums.yaml +7 -0
  2. data/._README.md +0 -0
  3. data/._ss.png +0 -0
  4. data/.gitignore +17 -0
  5. data/Gemfile +6 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +34 -0
  8. data/Rakefile +1 -0
  9. data/bin/._rvnstat +0 -0
  10. data/bin/rvnstat +9 -0
  11. data/config.ru +4 -0
  12. data/config.yml +3 -0
  13. data/lib/._app.rb +0 -0
  14. data/lib/._config.rb +0 -0
  15. data/lib/._require.rb +0 -0
  16. data/lib/._rvnstat.rb +0 -0
  17. data/lib/._vnstat.rb +0 -0
  18. data/lib/app.rb +102 -0
  19. data/lib/config.rb +13 -0
  20. data/lib/require.rb +10 -0
  21. data/lib/rvnstat.rb +5 -0
  22. data/lib/rvnstat/._version.rb +0 -0
  23. data/lib/rvnstat/version.rb +3 -0
  24. data/lib/vnstat.rb +74 -0
  25. data/public/CNAME +1 -0
  26. data/public/CONTRIBUTING.md +192 -0
  27. data/public/Gruntfile.js +418 -0
  28. data/public/LICENSE +21 -0
  29. data/public/README.md +173 -0
  30. data/public/_config.yml +35 -0
  31. data/public/bower.json +24 -0
  32. data/public/browserstack.json +44 -0
  33. data/public/composer.json +25 -0
  34. data/public/dist/css/._custom.css +0 -0
  35. data/public/dist/css/bootstrap-theme.css +347 -0
  36. data/public/dist/css/bootstrap-theme.css.map +1 -0
  37. data/public/dist/css/bootstrap-theme.min.css +7 -0
  38. data/public/dist/css/bootstrap.css +5831 -0
  39. data/public/dist/css/bootstrap.css.map +1 -0
  40. data/public/dist/css/bootstrap.min.css +7 -0
  41. data/public/dist/css/custom.css +20 -0
  42. data/public/dist/fonts/glyphicons-halflings-regular.eot +0 -0
  43. data/public/dist/fonts/glyphicons-halflings-regular.svg +229 -0
  44. data/public/dist/fonts/glyphicons-halflings-regular.ttf +0 -0
  45. data/public/dist/fonts/glyphicons-halflings-regular.woff +0 -0
  46. data/public/dist/js/bootstrap.js +1951 -0
  47. data/public/dist/js/bootstrap.min.js +6 -0
  48. data/public/docs/LICENSE +319 -0
  49. data/public/docs/_data/glyphicons.yml +203 -0
  50. data/public/docs/_data/showcase.yml +19 -0
  51. data/public/docs/_includes/ads.html +1 -0
  52. data/public/docs/_includes/customizer-variables.html +1690 -0
  53. data/public/docs/_includes/footer.html +70 -0
  54. data/public/docs/_includes/header.html +42 -0
  55. data/public/docs/_includes/nav-about.html +9 -0
  56. data/public/docs/_includes/nav-components.html +138 -0
  57. data/public/docs/_includes/nav-css.html +127 -0
  58. data/public/docs/_includes/nav-customize.html +46 -0
  59. data/public/docs/_includes/nav-getting-started.html +62 -0
  60. data/public/docs/_includes/nav-javascript.html +89 -0
  61. data/public/docs/_includes/nav-main.html +36 -0
  62. data/public/docs/_includes/nav-migration.html +12 -0
  63. data/public/docs/_includes/social-buttons.html +16 -0
  64. data/public/docs/_layouts/default.html +55 -0
  65. data/public/docs/_layouts/home.html +18 -0
  66. data/public/docs/about.html +149 -0
  67. data/public/docs/assets/css/docs.css +1394 -0
  68. data/public/docs/assets/css/docs.min.css +6 -0
  69. data/public/docs/assets/css/pygments-manni.css +66 -0
  70. data/public/docs/assets/ico/apple-touch-icon-144-precomposed.png +0 -0
  71. data/public/docs/assets/ico/favicon.ico +0 -0
  72. data/public/docs/assets/img/components.png +0 -0
  73. data/public/docs/assets/img/devices.png +0 -0
  74. data/public/docs/assets/img/sass-less.png +0 -0
  75. data/public/docs/assets/js/application.js +101 -0
  76. data/public/docs/assets/js/customize.min.js +49 -0
  77. data/public/docs/assets/js/customizer.js +348 -0
  78. data/public/docs/assets/js/docs.min.js +16 -0
  79. data/public/docs/assets/js/ie8-responsive-file-warning.js +12 -0
  80. data/public/docs/assets/js/raw-files.min.js +8 -0
  81. data/public/docs/assets/js/vendor/blob.js +166 -0
  82. data/public/docs/assets/js/vendor/filesaver.js +236 -0
  83. data/public/docs/assets/js/vendor/holder.js +645 -0
  84. data/public/docs/assets/js/vendor/jszip.js +1474 -0
  85. data/public/docs/assets/js/vendor/less.min.js +16 -0
  86. data/public/docs/assets/js/vendor/uglify.min.js +14 -0
  87. data/public/docs/components.html +3001 -0
  88. data/public/docs/css.html +3346 -0
  89. data/public/docs/customize.html +356 -0
  90. data/public/docs/customizer-nav.jade +15 -0
  91. data/public/docs/customizer-variables.jade +21 -0
  92. data/public/docs/dist/css/bootstrap-theme.css.map +1 -0
  93. data/public/docs/dist/css/bootstrap-theme.min.css +7 -0
  94. data/public/docs/dist/css/bootstrap.css.map +1 -0
  95. data/public/docs/dist/css/bootstrap.min.css +7 -0
  96. data/public/docs/dist/fonts/glyphicons-halflings-regular.eot +0 -0
  97. data/public/docs/dist/fonts/glyphicons-halflings-regular.svg +229 -0
  98. data/public/docs/dist/fonts/glyphicons-halflings-regular.ttf +0 -0
  99. data/public/docs/dist/fonts/glyphicons-halflings-regular.woff +0 -0
  100. data/public/docs/dist/js/bootstrap.min.js +7 -0
  101. data/public/docs/examples/blog/blog.css +168 -0
  102. data/public/docs/examples/blog/index.html +171 -0
  103. data/public/docs/examples/carousel/carousel.css +148 -0
  104. data/public/docs/examples/carousel/index.html +206 -0
  105. data/public/docs/examples/cover/cover.css +161 -0
  106. data/public/docs/examples/cover/index.html +75 -0
  107. data/public/docs/examples/dashboard/dashboard.css +93 -0
  108. data/public/docs/examples/dashboard/index.html +243 -0
  109. data/public/docs/examples/grid/grid.css +28 -0
  110. data/public/docs/examples/grid/index.html +152 -0
  111. data/public/docs/examples/jumbotron-narrow/index.html +82 -0
  112. data/public/docs/examples/jumbotron-narrow/jumbotron-narrow.css +79 -0
  113. data/public/docs/examples/jumbotron/index.html +99 -0
  114. data/public/docs/examples/jumbotron/jumbotron.css +5 -0
  115. data/public/docs/examples/justified-nav/index.html +84 -0
  116. data/public/docs/examples/justified-nav/justified-nav.css +88 -0
  117. data/public/docs/examples/navbar-fixed-top/index.html +91 -0
  118. data/public/docs/examples/navbar-fixed-top/navbar-fixed-top.css +4 -0
  119. data/public/docs/examples/navbar-static-top/index.html +92 -0
  120. data/public/docs/examples/navbar-static-top/navbar-static-top.css +7 -0
  121. data/public/docs/examples/navbar/index.html +90 -0
  122. data/public/docs/examples/navbar/navbar.css +8 -0
  123. data/public/docs/examples/non-responsive/index.html +105 -0
  124. data/public/docs/examples/non-responsive/non-responsive.css +120 -0
  125. data/public/docs/examples/offcanvas/index.html +130 -0
  126. data/public/docs/examples/offcanvas/offcanvas.css +51 -0
  127. data/public/docs/examples/offcanvas/offcanvas.js +5 -0
  128. data/public/docs/examples/screenshots/blog.jpg +0 -0
  129. data/public/docs/examples/screenshots/carousel.jpg +0 -0
  130. data/public/docs/examples/screenshots/cover.jpg +0 -0
  131. data/public/docs/examples/screenshots/dashboard.jpg +0 -0
  132. data/public/docs/examples/screenshots/grid.jpg +0 -0
  133. data/public/docs/examples/screenshots/jumbotron-narrow.jpg +0 -0
  134. data/public/docs/examples/screenshots/jumbotron.jpg +0 -0
  135. data/public/docs/examples/screenshots/justified-nav.jpg +0 -0
  136. data/public/docs/examples/screenshots/navbar-fixed.jpg +0 -0
  137. data/public/docs/examples/screenshots/navbar-static.jpg +0 -0
  138. data/public/docs/examples/screenshots/navbar.jpg +0 -0
  139. data/public/docs/examples/screenshots/non-responsive.jpg +0 -0
  140. data/public/docs/examples/screenshots/offcanvas.jpg +0 -0
  141. data/public/docs/examples/screenshots/sign-in.jpg +0 -0
  142. data/public/docs/examples/screenshots/starter-template.jpg +0 -0
  143. data/public/docs/examples/screenshots/sticky-footer-navbar.jpg +0 -0
  144. data/public/docs/examples/screenshots/sticky-footer.jpg +0 -0
  145. data/public/docs/examples/screenshots/theme.jpg +0 -0
  146. data/public/docs/examples/signin/index.html +50 -0
  147. data/public/docs/examples/signin/signin.css +40 -0
  148. data/public/docs/examples/starter-template/index.html +68 -0
  149. data/public/docs/examples/starter-template/starter-template.css +7 -0
  150. data/public/docs/examples/sticky-footer-navbar/index.html +91 -0
  151. data/public/docs/examples/sticky-footer-navbar/sticky-footer-navbar.css +45 -0
  152. data/public/docs/examples/sticky-footer/index.html +55 -0
  153. data/public/docs/examples/sticky-footer/sticky-footer.css +38 -0
  154. data/public/docs/examples/theme/index.html +384 -0
  155. data/public/docs/examples/theme/theme.css +14 -0
  156. data/public/docs/getting-started.html +773 -0
  157. data/public/docs/grunt/bs-glyphicons-data-generator.js +33 -0
  158. data/public/docs/grunt/bs-lessdoc-parser.js +236 -0
  159. data/public/docs/grunt/bs-raw-files-generator.js +31 -0
  160. data/public/docs/index.html +72 -0
  161. data/public/docs/javascript.html +2141 -0
  162. data/public/docs/migration.html +423 -0
  163. data/public/fonts/glyphicons-halflings-regular.eot +0 -0
  164. data/public/fonts/glyphicons-halflings-regular.svg +229 -0
  165. data/public/fonts/glyphicons-halflings-regular.ttf +0 -0
  166. data/public/fonts/glyphicons-halflings-regular.woff +0 -0
  167. data/public/js/._exporting.js +0 -0
  168. data/public/js/._highcharts-all.js +0 -0
  169. data/public/js/._jquery-min.js +0 -0
  170. data/public/js/.jscs.json +15 -0
  171. data/public/js/.jshintrc +14 -0
  172. data/public/js/affix.js +137 -0
  173. data/public/js/alert.js +88 -0
  174. data/public/js/bootstrap.min.js +6 -0
  175. data/public/js/button.js +107 -0
  176. data/public/js/carousel.js +205 -0
  177. data/public/js/collapse.js +170 -0
  178. data/public/js/dropdown.js +147 -0
  179. data/public/js/highcharts.js +294 -0
  180. data/public/js/jquery-1.11.0.min.js +4 -0
  181. data/public/js/modal.js +243 -0
  182. data/public/js/popover.js +110 -0
  183. data/public/js/scrollspy.js +153 -0
  184. data/public/js/tab.js +125 -0
  185. data/public/js/tests/index.html +54 -0
  186. data/public/js/tests/unit/affix.js +50 -0
  187. data/public/js/tests/unit/alert.js +62 -0
  188. data/public/js/tests/unit/button.js +122 -0
  189. data/public/js/tests/unit/carousel.js +110 -0
  190. data/public/js/tests/unit/collapse.js +164 -0
  191. data/public/js/tests/unit/dropdown.js +218 -0
  192. data/public/js/tests/unit/modal.js +195 -0
  193. data/public/js/tests/unit/phantom.js +69 -0
  194. data/public/js/tests/unit/popover.js +133 -0
  195. data/public/js/tests/unit/scrollspy.js +36 -0
  196. data/public/js/tests/unit/tab.js +86 -0
  197. data/public/js/tests/unit/tooltip.js +432 -0
  198. data/public/js/tests/vendor/jquery.js +6 -0
  199. data/public/js/tests/vendor/qunit.css +245 -0
  200. data/public/js/tests/vendor/qunit.js +2210 -0
  201. data/public/js/tooltip.js +399 -0
  202. data/public/js/transition.js +48 -0
  203. data/public/less/.csscomb.json +297 -0
  204. data/public/less/.csslintrc +19 -0
  205. data/public/less/alerts.less +67 -0
  206. data/public/less/badges.less +55 -0
  207. data/public/less/bootstrap.less +49 -0
  208. data/public/less/breadcrumbs.less +26 -0
  209. data/public/less/button-groups.less +226 -0
  210. data/public/less/buttons.less +155 -0
  211. data/public/less/carousel.less +232 -0
  212. data/public/less/close.less +33 -0
  213. data/public/less/code.less +63 -0
  214. data/public/less/component-animations.less +29 -0
  215. data/public/less/dropdowns.less +213 -0
  216. data/public/less/forms.less +419 -0
  217. data/public/less/glyphicons.less +233 -0
  218. data/public/less/grid.less +100 -0
  219. data/public/less/input-groups.less +157 -0
  220. data/public/less/jumbotron.less +44 -0
  221. data/public/less/labels.less +64 -0
  222. data/public/less/list-group.less +110 -0
  223. data/public/less/media.less +56 -0
  224. data/public/less/mixins.less +926 -0
  225. data/public/less/modals.less +138 -0
  226. data/public/less/navbar.less +616 -0
  227. data/public/less/navs.less +242 -0
  228. data/public/less/normalize.less +423 -0
  229. data/public/less/pager.less +55 -0
  230. data/public/less/pagination.less +88 -0
  231. data/public/less/panels.less +230 -0
  232. data/public/less/popovers.less +133 -0
  233. data/public/less/print.less +101 -0
  234. data/public/less/progress-bars.less +80 -0
  235. data/public/less/responsive-utilities.less +93 -0
  236. data/public/less/scaffolding.less +134 -0
  237. data/public/less/tables.less +233 -0
  238. data/public/less/theme.less +247 -0
  239. data/public/less/thumbnails.less +36 -0
  240. data/public/less/tooltip.less +95 -0
  241. data/public/less/type.less +296 -0
  242. data/public/less/utilities.less +56 -0
  243. data/public/less/variables.less +827 -0
  244. data/public/less/wells.less +29 -0
  245. data/public/package.json +71 -0
  246. data/public/test-infra/README.md +100 -0
  247. data/public/test-infra/npm-shrinkwrap.canonical.json +1 -0
  248. data/public/test-infra/requirements.txt +1 -0
  249. data/public/test-infra/s3_cache.py +107 -0
  250. data/public/test-infra/sauce_browsers.yml +83 -0
  251. data/public/test-infra/shrinkwrap.js +24 -0
  252. data/public/test-infra/uncached-npm-install.sh +4 -0
  253. data/rvnstat.gemspec +26 -0
  254. data/rvnstat.yml +3 -0
  255. data/ss.png +0 -0
  256. data/untitled.txt +0 -0
  257. data/views/._hourly.erb +0 -0
  258. data/views/._index.erb +0 -0
  259. data/views/._live_traffic.erb +0 -0
  260. data/views/._monthly.erb +0 -0
  261. data/views/._top_ten.erb +0 -0
  262. data/views/day_detail.erb +44 -0
  263. data/views/day_total.erb +42 -0
  264. data/views/graph_test.erb +2 -0
  265. data/views/hourly.erb +19 -0
  266. data/views/index.erb +71 -0
  267. data/views/layout.erb +28 -0
  268. data/views/live_traffic.erb +57 -0
  269. data/views/monthly.erb +21 -0
  270. data/views/top_ten.erb +21 -0
  271. metadata +385 -0
@@ -0,0 +1,1474 @@
1
+ /*!
2
+ JSZip - A Javascript class for generating and reading zip files
3
+ <http://stuartk.com/jszip>
4
+
5
+ (c) 2009-2012 Stuart Knightley <stuart [at] stuartk.com>
6
+ Dual licenced under the MIT license or GPLv3. See LICENSE.markdown.
7
+ */
8
+ /**
9
+ Usage:
10
+ zip = new JSZip();
11
+ zip.file("hello.txt", "Hello, World!").file("tempfile", "nothing");
12
+ zip.folder("images").file("smile.gif", base64Data, {base64: true});
13
+ zip.file("Xmas.txt", "Ho ho ho !", {date : new Date("December 25, 2007 00:00:01")});
14
+ zip.remove("tempfile");
15
+
16
+ base64zip = zip.generate();
17
+
18
+ **/
19
+ // We use strict, but it should not be placed outside of a function because
20
+ // the environment is shared inside the browser.
21
+ // "use strict";
22
+
23
+ /**
24
+ * Representation a of zip file in js
25
+ * @constructor
26
+ * @param {String=|ArrayBuffer=|Uint8Array=|Buffer=} data the data to load, if any (optional).
27
+ * @param {Object=} options the options for creating this objects (optional).
28
+ */
29
+ var JSZip = function(data, options) {
30
+ // object containing the files :
31
+ // {
32
+ // "folder/" : {...},
33
+ // "folder/data.txt" : {...}
34
+ // }
35
+ this.files = {};
36
+
37
+ // Where we are in the hierarchy
38
+ this.root = "";
39
+
40
+ if (data) {
41
+ this.load(data, options);
42
+ }
43
+ };
44
+
45
+ JSZip.signature = {
46
+ LOCAL_FILE_HEADER : "\x50\x4b\x03\x04",
47
+ CENTRAL_FILE_HEADER : "\x50\x4b\x01\x02",
48
+ CENTRAL_DIRECTORY_END : "\x50\x4b\x05\x06",
49
+ ZIP64_CENTRAL_DIRECTORY_LOCATOR : "\x50\x4b\x06\x07",
50
+ ZIP64_CENTRAL_DIRECTORY_END : "\x50\x4b\x06\x06",
51
+ DATA_DESCRIPTOR : "\x50\x4b\x07\x08"
52
+ };
53
+
54
+ // Default properties for a new file
55
+ JSZip.defaults = {
56
+ base64: false,
57
+ binary: false,
58
+ dir: false,
59
+ date: null,
60
+ compression: null
61
+ };
62
+
63
+ /*
64
+ * List features that require a modern browser, and if the current browser support them.
65
+ */
66
+ JSZip.support = {
67
+ // contains true if JSZip can read/generate ArrayBuffer, false otherwise.
68
+ arraybuffer : (function(){
69
+ return typeof ArrayBuffer !== "undefined" && typeof Uint8Array !== "undefined";
70
+ })(),
71
+ // contains true if JSZip can read/generate nodejs Buffer, false otherwise.
72
+ nodebuffer : (function(){
73
+ return typeof Buffer !== "undefined";
74
+ })(),
75
+ // contains true if JSZip can read/generate Uint8Array, false otherwise.
76
+ uint8array : (function(){
77
+ return typeof Uint8Array !== "undefined";
78
+ })(),
79
+ // contains true if JSZip can read/generate Blob, false otherwise.
80
+ blob : (function(){
81
+ // the spec started with BlobBuilder then replaced it with a construtor for Blob.
82
+ // Result : we have browsers that :
83
+ // * know the BlobBuilder (but with prefix)
84
+ // * know the Blob constructor
85
+ // * know about Blob but not about how to build them
86
+ // About the "=== 0" test : if given the wrong type, it may be converted to a string.
87
+ // Instead of an empty content, we will get "[object Uint8Array]" for example.
88
+ if (typeof ArrayBuffer === "undefined") {
89
+ return false;
90
+ }
91
+ var buffer = new ArrayBuffer(0);
92
+ try {
93
+ return new Blob([buffer], { type: "application/zip" }).size === 0;
94
+ }
95
+ catch(e) {}
96
+
97
+ try {
98
+ var BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder;
99
+ var builder = new BlobBuilder();
100
+ builder.append(buffer);
101
+ return builder.getBlob('application/zip').size === 0;
102
+ }
103
+ catch(e) {}
104
+
105
+ return false;
106
+ })()
107
+ };
108
+
109
+ JSZip.prototype = (function () {
110
+ var textEncoder, textDecoder;
111
+ if (
112
+ JSZip.support.uint8array &&
113
+ typeof TextEncoder === "function" &&
114
+ typeof TextDecoder === "function"
115
+ ) {
116
+ textEncoder = new TextEncoder("utf-8");
117
+ textDecoder = new TextDecoder("utf-8");
118
+ }
119
+
120
+ /**
121
+ * Returns the raw data of a ZipObject, decompress the content if necessary.
122
+ * @param {ZipObject} file the file to use.
123
+ * @return {String|ArrayBuffer|Uint8Array|Buffer} the data.
124
+ */
125
+ var getRawData = function (file) {
126
+ if (file._data instanceof JSZip.CompressedObject) {
127
+ file._data = file._data.getContent();
128
+ file.options.binary = true;
129
+ file.options.base64 = false;
130
+
131
+ if (JSZip.utils.getTypeOf(file._data) === "uint8array") {
132
+ var copy = file._data;
133
+ // when reading an arraybuffer, the CompressedObject mechanism will keep it and subarray() a Uint8Array.
134
+ // if we request a file in the same format, we might get the same Uint8Array or its ArrayBuffer (the original zip file).
135
+ file._data = new Uint8Array(copy.length);
136
+ // with an empty Uint8Array, Opera fails with a "Offset larger than array size"
137
+ if (copy.length !== 0) {
138
+ file._data.set(copy, 0);
139
+ }
140
+ }
141
+ }
142
+ return file._data;
143
+ };
144
+
145
+ /**
146
+ * Returns the data of a ZipObject in a binary form. If the content is an unicode string, encode it.
147
+ * @param {ZipObject} file the file to use.
148
+ * @return {String|ArrayBuffer|Uint8Array|Buffer} the data.
149
+ */
150
+ var getBinaryData = function (file) {
151
+ var result = getRawData(file), type = JSZip.utils.getTypeOf(result);
152
+ if (type === "string") {
153
+ if (!file.options.binary) {
154
+ // unicode text !
155
+ // unicode string => binary string is a painful process, check if we can avoid it.
156
+ if (textEncoder) {
157
+ return textEncoder.encode(result);
158
+ }
159
+ if (JSZip.support.nodebuffer) {
160
+ return new Buffer(result, "utf-8");
161
+ }
162
+ }
163
+ return file.asBinary();
164
+ }
165
+ return result;
166
+ };
167
+
168
+ /**
169
+ * Transform this._data into a string.
170
+ * @param {function} filter a function String -> String, applied if not null on the result.
171
+ * @return {String} the string representing this._data.
172
+ */
173
+ var dataToString = function (asUTF8) {
174
+ var result = getRawData(this);
175
+ if (result === null || typeof result === "undefined") {
176
+ return "";
177
+ }
178
+ // if the data is a base64 string, we decode it before checking the encoding !
179
+ if (this.options.base64) {
180
+ result = JSZip.base64.decode(result);
181
+ }
182
+ if (asUTF8 && this.options.binary) {
183
+ // JSZip.prototype.utf8decode supports arrays as input
184
+ // skip to array => string step, utf8decode will do it.
185
+ result = JSZip.prototype.utf8decode(result);
186
+ } else {
187
+ // no utf8 transformation, do the array => string step.
188
+ result = JSZip.utils.transformTo("string", result);
189
+ }
190
+
191
+ if (!asUTF8 && !this.options.binary) {
192
+ result = JSZip.prototype.utf8encode(result);
193
+ }
194
+ return result;
195
+ };
196
+ /**
197
+ * A simple object representing a file in the zip file.
198
+ * @constructor
199
+ * @param {string} name the name of the file
200
+ * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data
201
+ * @param {Object} options the options of the file
202
+ */
203
+ var ZipObject = function (name, data, options) {
204
+ this.name = name;
205
+ this._data = data;
206
+ this.options = options;
207
+ };
208
+
209
+ ZipObject.prototype = {
210
+ /**
211
+ * Return the content as UTF8 string.
212
+ * @return {string} the UTF8 string.
213
+ */
214
+ asText : function () {
215
+ return dataToString.call(this, true);
216
+ },
217
+ /**
218
+ * Returns the binary content.
219
+ * @return {string} the content as binary.
220
+ */
221
+ asBinary : function () {
222
+ return dataToString.call(this, false);
223
+ },
224
+ /**
225
+ * Returns the content as a nodejs Buffer.
226
+ * @return {Buffer} the content as a Buffer.
227
+ */
228
+ asNodeBuffer : function () {
229
+ var result = getBinaryData(this);
230
+ return JSZip.utils.transformTo("nodebuffer", result);
231
+ },
232
+ /**
233
+ * Returns the content as an Uint8Array.
234
+ * @return {Uint8Array} the content as an Uint8Array.
235
+ */
236
+ asUint8Array : function () {
237
+ var result = getBinaryData(this);
238
+ return JSZip.utils.transformTo("uint8array", result);
239
+ },
240
+ /**
241
+ * Returns the content as an ArrayBuffer.
242
+ * @return {ArrayBuffer} the content as an ArrayBufer.
243
+ */
244
+ asArrayBuffer : function () {
245
+ return this.asUint8Array().buffer;
246
+ }
247
+ };
248
+
249
+ /**
250
+ * Transform an integer into a string in hexadecimal.
251
+ * @private
252
+ * @param {number} dec the number to convert.
253
+ * @param {number} bytes the number of bytes to generate.
254
+ * @returns {string} the result.
255
+ */
256
+ var decToHex = function(dec, bytes) {
257
+ var hex = "", i;
258
+ for(i = 0; i < bytes; i++) {
259
+ hex += String.fromCharCode(dec&0xff);
260
+ dec=dec>>>8;
261
+ }
262
+ return hex;
263
+ };
264
+
265
+ /**
266
+ * Merge the objects passed as parameters into a new one.
267
+ * @private
268
+ * @param {...Object} var_args All objects to merge.
269
+ * @return {Object} a new object with the data of the others.
270
+ */
271
+ var extend = function () {
272
+ var result = {}, i, attr;
273
+ for (i = 0; i < arguments.length; i++) { // arguments is not enumerable in some browsers
274
+ for (attr in arguments[i]) {
275
+ if (arguments[i].hasOwnProperty(attr) && typeof result[attr] === "undefined") {
276
+ result[attr] = arguments[i][attr];
277
+ }
278
+ }
279
+ }
280
+ return result;
281
+ };
282
+
283
+ /**
284
+ * Transforms the (incomplete) options from the user into the complete
285
+ * set of options to create a file.
286
+ * @private
287
+ * @param {Object} o the options from the user.
288
+ * @return {Object} the complete set of options.
289
+ */
290
+ var prepareFileAttrs = function (o) {
291
+ o = o || {};
292
+ /*jshint -W041 */
293
+ if (o.base64 === true && o.binary == null) {
294
+ o.binary = true;
295
+ }
296
+ /*jshint +W041 */
297
+ o = extend(o, JSZip.defaults);
298
+ o.date = o.date || new Date();
299
+ if (o.compression !== null) o.compression = o.compression.toUpperCase();
300
+
301
+ return o;
302
+ };
303
+
304
+ /**
305
+ * Add a file in the current folder.
306
+ * @private
307
+ * @param {string} name the name of the file
308
+ * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data of the file
309
+ * @param {Object} o the options of the file
310
+ * @return {Object} the new file.
311
+ */
312
+ var fileAdd = function (name, data, o) {
313
+ // be sure sub folders exist
314
+ var parent = parentFolder(name), dataType = JSZip.utils.getTypeOf(data);
315
+ if (parent) {
316
+ folderAdd.call(this, parent);
317
+ }
318
+
319
+ o = prepareFileAttrs(o);
320
+
321
+ if (o.dir || data === null || typeof data === "undefined") {
322
+ o.base64 = false;
323
+ o.binary = false;
324
+ data = null;
325
+ } else if (dataType === "string") {
326
+ if (o.binary && !o.base64) {
327
+ // optimizedBinaryString == true means that the file has already been filtered with a 0xFF mask
328
+ if (o.optimizedBinaryString !== true) {
329
+ // this is a string, not in a base64 format.
330
+ // Be sure that this is a correct "binary string"
331
+ data = JSZip.utils.string2binary(data);
332
+ }
333
+ }
334
+ } else { // arraybuffer, uint8array, ...
335
+ o.base64 = false;
336
+ o.binary = true;
337
+
338
+ if (!dataType && !(data instanceof JSZip.CompressedObject)) {
339
+ throw new Error("The data of '" + name + "' is in an unsupported format !");
340
+ }
341
+
342
+ // special case : it's way easier to work with Uint8Array than with ArrayBuffer
343
+ if (dataType === "arraybuffer") {
344
+ data = JSZip.utils.transformTo("uint8array", data);
345
+ }
346
+ }
347
+
348
+ var object = new ZipObject(name, data, o);
349
+ this.files[name] = object;
350
+ return object;
351
+ };
352
+
353
+
354
+ /**
355
+ * Find the parent folder of the path.
356
+ * @private
357
+ * @param {string} path the path to use
358
+ * @return {string} the parent folder, or ""
359
+ */
360
+ var parentFolder = function (path) {
361
+ if (path.slice(-1) == '/') {
362
+ path = path.substring(0, path.length - 1);
363
+ }
364
+ var lastSlash = path.lastIndexOf('/');
365
+ return (lastSlash > 0) ? path.substring(0, lastSlash) : "";
366
+ };
367
+
368
+ /**
369
+ * Add a (sub) folder in the current folder.
370
+ * @private
371
+ * @param {string} name the folder's name
372
+ * @return {Object} the new folder.
373
+ */
374
+ var folderAdd = function (name) {
375
+ // Check the name ends with a /
376
+ if (name.slice(-1) != "/") {
377
+ name += "/"; // IE doesn't like substr(-1)
378
+ }
379
+
380
+ // Does this folder already exist?
381
+ if (!this.files[name]) {
382
+ fileAdd.call(this, name, null, {dir:true});
383
+ }
384
+ return this.files[name];
385
+ };
386
+
387
+ /**
388
+ * Generate a JSZip.CompressedObject for a given zipOject.
389
+ * @param {ZipObject} file the object to read.
390
+ * @param {JSZip.compression} compression the compression to use.
391
+ * @return {JSZip.CompressedObject} the compressed result.
392
+ */
393
+ var generateCompressedObjectFrom = function (file, compression) {
394
+ var result = new JSZip.CompressedObject(), content;
395
+
396
+ // the data has not been decompressed, we might reuse things !
397
+ if (file._data instanceof JSZip.CompressedObject) {
398
+ result.uncompressedSize = file._data.uncompressedSize;
399
+ result.crc32 = file._data.crc32;
400
+
401
+ if (result.uncompressedSize === 0 || file.options.dir) {
402
+ compression = JSZip.compressions['STORE'];
403
+ result.compressedContent = "";
404
+ result.crc32 = 0;
405
+ } else if (file._data.compressionMethod === compression.magic) {
406
+ result.compressedContent = file._data.getCompressedContent();
407
+ } else {
408
+ content = file._data.getContent();
409
+ // need to decompress / recompress
410
+ result.compressedContent = compression.compress(JSZip.utils.transformTo(compression.compressInputType, content));
411
+ }
412
+ } else {
413
+ // have uncompressed data
414
+ content = getBinaryData(file);
415
+ if (!content || content.length === 0 || file.options.dir) {
416
+ compression = JSZip.compressions['STORE'];
417
+ content = "";
418
+ }
419
+ result.uncompressedSize = content.length;
420
+ result.crc32 = this.crc32(content);
421
+ result.compressedContent = compression.compress(JSZip.utils.transformTo(compression.compressInputType, content));
422
+ }
423
+
424
+ result.compressedSize = result.compressedContent.length;
425
+ result.compressionMethod = compression.magic;
426
+
427
+ return result;
428
+ };
429
+
430
+ /**
431
+ * Generate the various parts used in the construction of the final zip file.
432
+ * @param {string} name the file name.
433
+ * @param {ZipObject} file the file content.
434
+ * @param {JSZip.CompressedObject} compressedObject the compressed object.
435
+ * @param {number} offset the current offset from the start of the zip file.
436
+ * @return {object} the zip parts.
437
+ */
438
+ var generateZipParts = function(name, file, compressedObject, offset) {
439
+ var data = compressedObject.compressedContent,
440
+ utfEncodedFileName = this.utf8encode(file.name),
441
+ useUTF8 = utfEncodedFileName !== file.name,
442
+ o = file.options,
443
+ dosTime,
444
+ dosDate;
445
+
446
+ // date
447
+ // @see http://www.delorie.com/djgpp/doc/rbinter/it/52/13.html
448
+ // @see http://www.delorie.com/djgpp/doc/rbinter/it/65/16.html
449
+ // @see http://www.delorie.com/djgpp/doc/rbinter/it/66/16.html
450
+
451
+ dosTime = o.date.getHours();
452
+ dosTime = dosTime << 6;
453
+ dosTime = dosTime | o.date.getMinutes();
454
+ dosTime = dosTime << 5;
455
+ dosTime = dosTime | o.date.getSeconds() / 2;
456
+
457
+ dosDate = o.date.getFullYear() - 1980;
458
+ dosDate = dosDate << 4;
459
+ dosDate = dosDate | (o.date.getMonth() + 1);
460
+ dosDate = dosDate << 5;
461
+ dosDate = dosDate | o.date.getDate();
462
+
463
+
464
+ var header = "";
465
+
466
+ // version needed to extract
467
+ header += "\x0A\x00";
468
+ // general purpose bit flag
469
+ // set bit 11 if utf8
470
+ header += useUTF8 ? "\x00\x08" : "\x00\x00";
471
+ // compression method
472
+ header += compressedObject.compressionMethod;
473
+ // last mod file time
474
+ header += decToHex(dosTime, 2);
475
+ // last mod file date
476
+ header += decToHex(dosDate, 2);
477
+ // crc-32
478
+ header += decToHex(compressedObject.crc32, 4);
479
+ // compressed size
480
+ header += decToHex(compressedObject.compressedSize, 4);
481
+ // uncompressed size
482
+ header += decToHex(compressedObject.uncompressedSize, 4);
483
+ // file name length
484
+ header += decToHex(utfEncodedFileName.length, 2);
485
+ // extra field length
486
+ header += "\x00\x00";
487
+
488
+
489
+ var fileRecord = JSZip.signature.LOCAL_FILE_HEADER + header + utfEncodedFileName;
490
+
491
+ var dirRecord = JSZip.signature.CENTRAL_FILE_HEADER +
492
+ // version made by (00: DOS)
493
+ "\x14\x00" +
494
+ // file header (common to file and central directory)
495
+ header +
496
+ // file comment length
497
+ "\x00\x00" +
498
+ // disk number start
499
+ "\x00\x00" +
500
+ // internal file attributes TODO
501
+ "\x00\x00" +
502
+ // external file attributes
503
+ (file.options.dir===true?"\x10\x00\x00\x00":"\x00\x00\x00\x00")+
504
+ // relative offset of local header
505
+ decToHex(offset, 4) +
506
+ // file name
507
+ utfEncodedFileName;
508
+
509
+
510
+ return {
511
+ fileRecord : fileRecord,
512
+ dirRecord : dirRecord,
513
+ compressedObject : compressedObject
514
+ };
515
+ };
516
+
517
+ /**
518
+ * An object to write any content to a string.
519
+ * @constructor
520
+ */
521
+ var StringWriter = function () {
522
+ this.data = [];
523
+ };
524
+ StringWriter.prototype = {
525
+ /**
526
+ * Append any content to the current string.
527
+ * @param {Object} input the content to add.
528
+ */
529
+ append : function (input) {
530
+ input = JSZip.utils.transformTo("string", input);
531
+ this.data.push(input);
532
+ },
533
+ /**
534
+ * Finalize the construction an return the result.
535
+ * @return {string} the generated string.
536
+ */
537
+ finalize : function () {
538
+ return this.data.join("");
539
+ }
540
+ };
541
+ /**
542
+ * An object to write any content to an Uint8Array.
543
+ * @constructor
544
+ * @param {number} length The length of the array.
545
+ */
546
+ var Uint8ArrayWriter = function (length) {
547
+ this.data = new Uint8Array(length);
548
+ this.index = 0;
549
+ };
550
+ Uint8ArrayWriter.prototype = {
551
+ /**
552
+ * Append any content to the current array.
553
+ * @param {Object} input the content to add.
554
+ */
555
+ append : function (input) {
556
+ if (input.length !== 0) {
557
+ // with an empty Uint8Array, Opera fails with a "Offset larger than array size"
558
+ input = JSZip.utils.transformTo("uint8array", input);
559
+ this.data.set(input, this.index);
560
+ this.index += input.length;
561
+ }
562
+ },
563
+ /**
564
+ * Finalize the construction an return the result.
565
+ * @return {Uint8Array} the generated array.
566
+ */
567
+ finalize : function () {
568
+ return this.data;
569
+ }
570
+ };
571
+
572
+ // return the actual prototype of JSZip
573
+ return {
574
+ /**
575
+ * Read an existing zip and merge the data in the current JSZip object.
576
+ * The implementation is in jszip-load.js, don't forget to include it.
577
+ * @param {String|ArrayBuffer|Uint8Array|Buffer} stream The stream to load
578
+ * @param {Object} options Options for loading the stream.
579
+ * options.base64 : is the stream in base64 ? default : false
580
+ * @return {JSZip} the current JSZip object
581
+ */
582
+ load : function (stream, options) {
583
+ throw new Error("Load method is not defined. Is the file jszip-load.js included ?");
584
+ },
585
+
586
+ /**
587
+ * Filter nested files/folders with the specified function.
588
+ * @param {Function} search the predicate to use :
589
+ * function (relativePath, file) {...}
590
+ * It takes 2 arguments : the relative path and the file.
591
+ * @return {Array} An array of matching elements.
592
+ */
593
+ filter : function (search) {
594
+ var result = [], filename, relativePath, file, fileClone;
595
+ for (filename in this.files) {
596
+ if ( !this.files.hasOwnProperty(filename) ) { continue; }
597
+ file = this.files[filename];
598
+ // return a new object, don't let the user mess with our internal objects :)
599
+ fileClone = new ZipObject(file.name, file._data, extend(file.options));
600
+ relativePath = filename.slice(this.root.length, filename.length);
601
+ if (filename.slice(0, this.root.length) === this.root && // the file is in the current root
602
+ search(relativePath, fileClone)) { // and the file matches the function
603
+ result.push(fileClone);
604
+ }
605
+ }
606
+ return result;
607
+ },
608
+
609
+ /**
610
+ * Add a file to the zip file, or search a file.
611
+ * @param {string|RegExp} name The name of the file to add (if data is defined),
612
+ * the name of the file to find (if no data) or a regex to match files.
613
+ * @param {String|ArrayBuffer|Uint8Array|Buffer} data The file data, either raw or base64 encoded
614
+ * @param {Object} o File options
615
+ * @return {JSZip|Object|Array} this JSZip object (when adding a file),
616
+ * a file (when searching by string) or an array of files (when searching by regex).
617
+ */
618
+ file : function(name, data, o) {
619
+ if (arguments.length === 1) {
620
+ if (JSZip.utils.isRegExp(name)) {
621
+ var regexp = name;
622
+ return this.filter(function(relativePath, file) {
623
+ return !file.options.dir && regexp.test(relativePath);
624
+ });
625
+ } else { // text
626
+ return this.filter(function (relativePath, file) {
627
+ return !file.options.dir && relativePath === name;
628
+ })[0]||null;
629
+ }
630
+ } else { // more than one argument : we have data !
631
+ name = this.root+name;
632
+ fileAdd.call(this, name, data, o);
633
+ }
634
+ return this;
635
+ },
636
+
637
+ /**
638
+ * Add a directory to the zip file, or search.
639
+ * @param {String|RegExp} arg The name of the directory to add, or a regex to search folders.
640
+ * @return {JSZip} an object with the new directory as the root, or an array containing matching folders.
641
+ */
642
+ folder : function(arg) {
643
+ if (!arg) {
644
+ return this;
645
+ }
646
+
647
+ if (JSZip.utils.isRegExp(arg)) {
648
+ return this.filter(function(relativePath, file) {
649
+ return file.options.dir && arg.test(relativePath);
650
+ });
651
+ }
652
+
653
+ // else, name is a new folder
654
+ var name = this.root + arg;
655
+ var newFolder = folderAdd.call(this, name);
656
+
657
+ // Allow chaining by returning a new object with this folder as the root
658
+ var ret = this.clone();
659
+ ret.root = newFolder.name;
660
+ return ret;
661
+ },
662
+
663
+ /**
664
+ * Delete a file, or a directory and all sub-files, from the zip
665
+ * @param {string} name the name of the file to delete
666
+ * @return {JSZip} this JSZip object
667
+ */
668
+ remove : function(name) {
669
+ name = this.root + name;
670
+ var file = this.files[name];
671
+ if (!file) {
672
+ // Look for any folders
673
+ if (name.slice(-1) != "/") {
674
+ name += "/";
675
+ }
676
+ file = this.files[name];
677
+ }
678
+
679
+ if (file) {
680
+ if (!file.options.dir) {
681
+ // file
682
+ delete this.files[name];
683
+ } else {
684
+ // folder
685
+ var kids = this.filter(function (relativePath, file) {
686
+ return file.name.slice(0, name.length) === name;
687
+ });
688
+ for (var i = 0; i < kids.length; i++) {
689
+ delete this.files[kids[i].name];
690
+ }
691
+ }
692
+ }
693
+
694
+ return this;
695
+ },
696
+
697
+ /**
698
+ * Generate the complete zip file
699
+ * @param {Object} options the options to generate the zip file :
700
+ * - base64, (deprecated, use type instead) true to generate base64.
701
+ * - compression, "STORE" by default.
702
+ * - type, "base64" by default. Values are : string, base64, uint8array, arraybuffer, blob.
703
+ * @return {String|Uint8Array|ArrayBuffer|Buffer|Blob} the zip file
704
+ */
705
+ generate : function(options) {
706
+ options = extend(options || {}, {
707
+ base64 : true,
708
+ compression : "STORE",
709
+ type : "base64"
710
+ });
711
+
712
+ JSZip.utils.checkSupport(options.type);
713
+
714
+ var zipData = [], localDirLength = 0, centralDirLength = 0, writer, i;
715
+
716
+
717
+ // first, generate all the zip parts.
718
+ for (var name in this.files) {
719
+ if ( !this.files.hasOwnProperty(name) ) { continue; }
720
+ var file = this.files[name];
721
+
722
+ var compressionName = file.options.compression || options.compression.toUpperCase();
723
+ var compression = JSZip.compressions[compressionName];
724
+ if (!compression) {
725
+ throw new Error(compressionName + " is not a valid compression method !");
726
+ }
727
+
728
+ var compressedObject = generateCompressedObjectFrom.call(this, file, compression);
729
+
730
+ var zipPart = generateZipParts.call(this, name, file, compressedObject, localDirLength);
731
+ localDirLength += zipPart.fileRecord.length + compressedObject.compressedSize;
732
+ centralDirLength += zipPart.dirRecord.length;
733
+ zipData.push(zipPart);
734
+ }
735
+
736
+ var dirEnd = "";
737
+
738
+ // end of central dir signature
739
+ dirEnd = JSZip.signature.CENTRAL_DIRECTORY_END +
740
+ // number of this disk
741
+ "\x00\x00" +
742
+ // number of the disk with the start of the central directory
743
+ "\x00\x00" +
744
+ // total number of entries in the central directory on this disk
745
+ decToHex(zipData.length, 2) +
746
+ // total number of entries in the central directory
747
+ decToHex(zipData.length, 2) +
748
+ // size of the central directory 4 bytes
749
+ decToHex(centralDirLength, 4) +
750
+ // offset of start of central directory with respect to the starting disk number
751
+ decToHex(localDirLength, 4) +
752
+ // .ZIP file comment length
753
+ "\x00\x00";
754
+
755
+
756
+ // we have all the parts (and the total length)
757
+ // time to create a writer !
758
+ switch(options.type.toLowerCase()) {
759
+ case "uint8array" :
760
+ case "arraybuffer" :
761
+ case "blob" :
762
+ case "nodebuffer" :
763
+ writer = new Uint8ArrayWriter(localDirLength + centralDirLength + dirEnd.length);
764
+ break;
765
+ // case "base64" :
766
+ // case "string" :
767
+ default :
768
+ writer = new StringWriter(localDirLength + centralDirLength + dirEnd.length);
769
+ break;
770
+ }
771
+
772
+ for (i = 0; i < zipData.length; i++) {
773
+ writer.append(zipData[i].fileRecord);
774
+ writer.append(zipData[i].compressedObject.compressedContent);
775
+ }
776
+ for (i = 0; i < zipData.length; i++) {
777
+ writer.append(zipData[i].dirRecord);
778
+ }
779
+
780
+ writer.append(dirEnd);
781
+
782
+ var zip = writer.finalize();
783
+
784
+
785
+
786
+ switch(options.type.toLowerCase()) {
787
+ // case "zip is an Uint8Array"
788
+ case "uint8array" :
789
+ case "arraybuffer" :
790
+ case "nodebuffer" :
791
+ return JSZip.utils.transformTo(options.type.toLowerCase(), zip);
792
+ case "blob" :
793
+ return JSZip.utils.arrayBuffer2Blob(JSZip.utils.transformTo("arraybuffer", zip));
794
+
795
+ // case "zip is a string"
796
+ case "base64" :
797
+ return (options.base64) ? JSZip.base64.encode(zip) : zip;
798
+ default : // case "string" :
799
+ return zip;
800
+ }
801
+ },
802
+
803
+ /**
804
+ *
805
+ * Javascript crc32
806
+ * http://www.webtoolkit.info/
807
+ *
808
+ */
809
+ crc32 : function crc32(input, crc) {
810
+ if (typeof input === "undefined" || !input.length) {
811
+ return 0;
812
+ }
813
+
814
+ var isArray = JSZip.utils.getTypeOf(input) !== "string";
815
+
816
+ var table = [
817
+ 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
818
+ 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
819
+ 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
820
+ 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
821
+ 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
822
+ 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
823
+ 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
824
+ 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
825
+ 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
826
+ 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
827
+ 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
828
+ 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
829
+ 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
830
+ 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
831
+ 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
832
+ 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
833
+ 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
834
+ 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
835
+ 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
836
+ 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
837
+ 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
838
+ 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
839
+ 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
840
+ 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
841
+ 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
842
+ 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
843
+ 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
844
+ 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
845
+ 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
846
+ 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
847
+ 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
848
+ 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
849
+ 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
850
+ 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
851
+ 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
852
+ 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
853
+ 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
854
+ 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
855
+ 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
856
+ 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
857
+ 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
858
+ 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
859
+ 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
860
+ 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
861
+ 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
862
+ 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
863
+ 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
864
+ 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
865
+ 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
866
+ 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
867
+ 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
868
+ 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
869
+ 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
870
+ 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
871
+ 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
872
+ 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
873
+ 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
874
+ 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
875
+ 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
876
+ 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
877
+ 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
878
+ 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
879
+ 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
880
+ 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
881
+ ];
882
+
883
+ if (typeof(crc) == "undefined") { crc = 0; }
884
+ var x = 0;
885
+ var y = 0;
886
+ var byte = 0;
887
+
888
+ crc = crc ^ (-1);
889
+ for( var i = 0, iTop = input.length; i < iTop; i++ ) {
890
+ byte = isArray ? input[i] : input.charCodeAt(i);
891
+ y = ( crc ^ byte ) & 0xFF;
892
+ x = table[y];
893
+ crc = ( crc >>> 8 ) ^ x;
894
+ }
895
+
896
+ return crc ^ (-1);
897
+ },
898
+
899
+ // Inspired by http://my.opera.com/GreyWyvern/blog/show.dml/1725165
900
+ clone : function() {
901
+ var newObj = new JSZip();
902
+ for (var i in this) {
903
+ if (typeof this[i] !== "function") {
904
+ newObj[i] = this[i];
905
+ }
906
+ }
907
+ return newObj;
908
+ },
909
+
910
+
911
+ /**
912
+ * http://www.webtoolkit.info/javascript-utf8.html
913
+ */
914
+ utf8encode : function (string) {
915
+ // TextEncoder + Uint8Array to binary string is faster than checking every bytes on long strings.
916
+ // http://jsperf.com/utf8encode-vs-textencoder
917
+ // On short strings (file names for example), the TextEncoder API is (currently) slower.
918
+ if (textEncoder) {
919
+ var u8 = textEncoder.encode(string);
920
+ return JSZip.utils.transformTo("string", u8);
921
+ }
922
+ if (JSZip.support.nodebuffer) {
923
+ return JSZip.utils.transformTo("string", new Buffer(string, "utf-8"));
924
+ }
925
+
926
+ // array.join may be slower than string concatenation but generates less objects (less time spent garbage collecting).
927
+ // See also http://jsperf.com/array-direct-assignment-vs-push/31
928
+ var result = [], resIndex = 0;
929
+
930
+ for (var n = 0; n < string.length; n++) {
931
+
932
+ var c = string.charCodeAt(n);
933
+
934
+ if (c < 128) {
935
+ result[resIndex++] = String.fromCharCode(c);
936
+ } else if ((c > 127) && (c < 2048)) {
937
+ result[resIndex++] = String.fromCharCode((c >> 6) | 192);
938
+ result[resIndex++] = String.fromCharCode((c & 63) | 128);
939
+ } else {
940
+ result[resIndex++] = String.fromCharCode((c >> 12) | 224);
941
+ result[resIndex++] = String.fromCharCode(((c >> 6) & 63) | 128);
942
+ result[resIndex++] = String.fromCharCode((c & 63) | 128);
943
+ }
944
+
945
+ }
946
+
947
+ return result.join("");
948
+ },
949
+
950
+ /**
951
+ * http://www.webtoolkit.info/javascript-utf8.html
952
+ */
953
+ utf8decode : function (input) {
954
+ var result = [], resIndex = 0;
955
+ var type = JSZip.utils.getTypeOf(input);
956
+ var isArray = type !== "string";
957
+ var i = 0;
958
+ var c = 0, c1 = 0, c2 = 0, c3 = 0;
959
+
960
+ // check if we can use the TextDecoder API
961
+ // see http://encoding.spec.whatwg.org/#api
962
+ if (textDecoder) {
963
+ return textDecoder.decode(
964
+ JSZip.utils.transformTo("uint8array", input)
965
+ );
966
+ }
967
+ if (JSZip.support.nodebuffer) {
968
+ return JSZip.utils.transformTo("nodebuffer", input).toString("utf-8");
969
+ }
970
+
971
+ while ( i < input.length ) {
972
+
973
+ c = isArray ? input[i] : input.charCodeAt(i);
974
+
975
+ if (c < 128) {
976
+ result[resIndex++] = String.fromCharCode(c);
977
+ i++;
978
+ } else if ((c > 191) && (c < 224)) {
979
+ c2 = isArray ? input[i+1] : input.charCodeAt(i+1);
980
+ result[resIndex++] = String.fromCharCode(((c & 31) << 6) | (c2 & 63));
981
+ i += 2;
982
+ } else {
983
+ c2 = isArray ? input[i+1] : input.charCodeAt(i+1);
984
+ c3 = isArray ? input[i+2] : input.charCodeAt(i+2);
985
+ result[resIndex++] = String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
986
+ i += 3;
987
+ }
988
+
989
+ }
990
+
991
+ return result.join("");
992
+ }
993
+ };
994
+ }());
995
+
996
+ /*
997
+ * Compression methods
998
+ * This object is filled in as follow :
999
+ * name : {
1000
+ * magic // the 2 bytes indentifying the compression method
1001
+ * compress // function, take the uncompressed content and return it compressed.
1002
+ * uncompress // function, take the compressed content and return it uncompressed.
1003
+ * compressInputType // string, the type accepted by the compress method. null to accept everything.
1004
+ * uncompressInputType // string, the type accepted by the uncompress method. null to accept everything.
1005
+ * }
1006
+ *
1007
+ * STORE is the default compression method, so it's included in this file.
1008
+ * Other methods should go to separated files : the user wants modularity.
1009
+ */
1010
+ JSZip.compressions = {
1011
+ "STORE" : {
1012
+ magic : "\x00\x00",
1013
+ compress : function (content) {
1014
+ return content; // no compression
1015
+ },
1016
+ uncompress : function (content) {
1017
+ return content; // no compression
1018
+ },
1019
+ compressInputType : null,
1020
+ uncompressInputType : null
1021
+ }
1022
+ };
1023
+
1024
+ (function () {
1025
+ JSZip.utils = {
1026
+ /**
1027
+ * Convert a string to a "binary string" : a string containing only char codes between 0 and 255.
1028
+ * @param {string} str the string to transform.
1029
+ * @return {String} the binary string.
1030
+ */
1031
+ string2binary : function (str) {
1032
+ var result = "";
1033
+ for (var i = 0; i < str.length; i++) {
1034
+ result += String.fromCharCode(str.charCodeAt(i) & 0xff);
1035
+ }
1036
+ return result;
1037
+ },
1038
+ /**
1039
+ * Create a Uint8Array from the string.
1040
+ * @param {string} str the string to transform.
1041
+ * @return {Uint8Array} the typed array.
1042
+ * @throws {Error} an Error if the browser doesn't support the requested feature.
1043
+ * @deprecated : use JSZip.utils.transformTo instead.
1044
+ */
1045
+ string2Uint8Array : function (str) {
1046
+ return JSZip.utils.transformTo("uint8array", str);
1047
+ },
1048
+
1049
+ /**
1050
+ * Create a string from the Uint8Array.
1051
+ * @param {Uint8Array} array the array to transform.
1052
+ * @return {string} the string.
1053
+ * @throws {Error} an Error if the browser doesn't support the requested feature.
1054
+ * @deprecated : use JSZip.utils.transformTo instead.
1055
+ */
1056
+ uint8Array2String : function (array) {
1057
+ return JSZip.utils.transformTo("string", array);
1058
+ },
1059
+ /**
1060
+ * Create a blob from the given ArrayBuffer.
1061
+ * @param {ArrayBuffer} buffer the buffer to transform.
1062
+ * @return {Blob} the result.
1063
+ * @throws {Error} an Error if the browser doesn't support the requested feature.
1064
+ */
1065
+ arrayBuffer2Blob : function (buffer) {
1066
+ JSZip.utils.checkSupport("blob");
1067
+
1068
+ try {
1069
+ // Blob constructor
1070
+ return new Blob([buffer], { type: "application/zip" });
1071
+ }
1072
+ catch(e) {}
1073
+
1074
+ try {
1075
+ // deprecated, browser only, old way
1076
+ var BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder;
1077
+ var builder = new BlobBuilder();
1078
+ builder.append(buffer);
1079
+ return builder.getBlob('application/zip');
1080
+ }
1081
+ catch(e) {}
1082
+
1083
+ // well, fuck ?!
1084
+ throw new Error("Bug : can't construct the Blob.");
1085
+ },
1086
+ /**
1087
+ * Create a blob from the given string.
1088
+ * @param {string} str the string to transform.
1089
+ * @return {Blob} the result.
1090
+ * @throws {Error} an Error if the browser doesn't support the requested feature.
1091
+ */
1092
+ string2Blob : function (str) {
1093
+ var buffer = JSZip.utils.transformTo("arraybuffer", str);
1094
+ return JSZip.utils.arrayBuffer2Blob(buffer);
1095
+ }
1096
+ };
1097
+
1098
+ /**
1099
+ * The identity function.
1100
+ * @param {Object} input the input.
1101
+ * @return {Object} the same input.
1102
+ */
1103
+ function identity(input) {
1104
+ return input;
1105
+ }
1106
+
1107
+ /**
1108
+ * Fill in an array with a string.
1109
+ * @param {String} str the string to use.
1110
+ * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to fill in (will be mutated).
1111
+ * @return {Array|ArrayBuffer|Uint8Array|Buffer} the updated array.
1112
+ */
1113
+ function stringToArrayLike(str, array) {
1114
+ for (var i = 0; i < str.length; ++i) {
1115
+ array[i] = str.charCodeAt(i) & 0xFF;
1116
+ }
1117
+ return array;
1118
+ }
1119
+
1120
+ /**
1121
+ * Transform an array-like object to a string.
1122
+ * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to transform.
1123
+ * @return {String} the result.
1124
+ */
1125
+ function arrayLikeToString(array) {
1126
+ // Performances notes :
1127
+ // --------------------
1128
+ // String.fromCharCode.apply(null, array) is the fastest, see
1129
+ // see http://jsperf.com/converting-a-uint8array-to-a-string/2
1130
+ // but the stack is limited (and we can get huge arrays !).
1131
+ //
1132
+ // result += String.fromCharCode(array[i]); generate too many strings !
1133
+ //
1134
+ // This code is inspired by http://jsperf.com/arraybuffer-to-string-apply-performance/2
1135
+ var chunk = 65536;
1136
+ var result = [], len = array.length, type = JSZip.utils.getTypeOf(array), k = 0;
1137
+
1138
+ var canUseApply = true;
1139
+ try {
1140
+ switch(type) {
1141
+ case "uint8array":
1142
+ String.fromCharCode.apply(null, new Uint8Array(0));
1143
+ break;
1144
+ case "nodebuffer":
1145
+ String.fromCharCode.apply(null, new Buffer(0));
1146
+ break;
1147
+ }
1148
+ } catch(e) {
1149
+ canUseApply = false;
1150
+ }
1151
+
1152
+ // no apply : slow and painful algorithm
1153
+ // default browser on android 4.*
1154
+ if (!canUseApply) {
1155
+ var resultStr = "";
1156
+ for(var i = 0; i < array.length;i++) {
1157
+ resultStr += String.fromCharCode(array[i]);
1158
+ }
1159
+ return resultStr;
1160
+ }
1161
+
1162
+ while (k < len && chunk > 1) {
1163
+ try {
1164
+ if (type === "array" || type === "nodebuffer") {
1165
+ result.push(String.fromCharCode.apply(null, array.slice(k, Math.min(k + chunk, len))));
1166
+ } else {
1167
+ result.push(String.fromCharCode.apply(null, array.subarray(k, Math.min(k + chunk, len))));
1168
+ }
1169
+ k += chunk;
1170
+ } catch (e) {
1171
+ chunk = Math.floor(chunk / 2);
1172
+ }
1173
+ }
1174
+ return result.join("");
1175
+ }
1176
+
1177
+ /**
1178
+ * Copy the data from an array-like to an other array-like.
1179
+ * @param {Array|ArrayBuffer|Uint8Array|Buffer} arrayFrom the origin array.
1180
+ * @param {Array|ArrayBuffer|Uint8Array|Buffer} arrayTo the destination array which will be mutated.
1181
+ * @return {Array|ArrayBuffer|Uint8Array|Buffer} the updated destination array.
1182
+ */
1183
+ function arrayLikeToArrayLike(arrayFrom, arrayTo) {
1184
+ for(var i = 0; i < arrayFrom.length; i++) {
1185
+ arrayTo[i] = arrayFrom[i];
1186
+ }
1187
+ return arrayTo;
1188
+ }
1189
+
1190
+ // a matrix containing functions to transform everything into everything.
1191
+ var transform = {};
1192
+
1193
+ // string to ?
1194
+ transform["string"] = {
1195
+ "string" : identity,
1196
+ "array" : function (input) {
1197
+ return stringToArrayLike(input, new Array(input.length));
1198
+ },
1199
+ "arraybuffer" : function (input) {
1200
+ return transform["string"]["uint8array"](input).buffer;
1201
+ },
1202
+ "uint8array" : function (input) {
1203
+ return stringToArrayLike(input, new Uint8Array(input.length));
1204
+ },
1205
+ "nodebuffer" : function (input) {
1206
+ return stringToArrayLike(input, new Buffer(input.length));
1207
+ }
1208
+ };
1209
+
1210
+ // array to ?
1211
+ transform["array"] = {
1212
+ "string" : arrayLikeToString,
1213
+ "array" : identity,
1214
+ "arraybuffer" : function (input) {
1215
+ return (new Uint8Array(input)).buffer;
1216
+ },
1217
+ "uint8array" : function (input) {
1218
+ return new Uint8Array(input);
1219
+ },
1220
+ "nodebuffer" : function (input) {
1221
+ return new Buffer(input);
1222
+ }
1223
+ };
1224
+
1225
+ // arraybuffer to ?
1226
+ transform["arraybuffer"] = {
1227
+ "string" : function (input) {
1228
+ return arrayLikeToString(new Uint8Array(input));
1229
+ },
1230
+ "array" : function (input) {
1231
+ return arrayLikeToArrayLike(new Uint8Array(input), new Array(input.byteLength));
1232
+ },
1233
+ "arraybuffer" : identity,
1234
+ "uint8array" : function (input) {
1235
+ return new Uint8Array(input);
1236
+ },
1237
+ "nodebuffer" : function (input) {
1238
+ return new Buffer(new Uint8Array(input));
1239
+ }
1240
+ };
1241
+
1242
+ // uint8array to ?
1243
+ transform["uint8array"] = {
1244
+ "string" : arrayLikeToString,
1245
+ "array" : function (input) {
1246
+ return arrayLikeToArrayLike(input, new Array(input.length));
1247
+ },
1248
+ "arraybuffer" : function (input) {
1249
+ return input.buffer;
1250
+ },
1251
+ "uint8array" : identity,
1252
+ "nodebuffer" : function(input) {
1253
+ return new Buffer(input);
1254
+ }
1255
+ };
1256
+
1257
+ // nodebuffer to ?
1258
+ transform["nodebuffer"] = {
1259
+ "string" : arrayLikeToString,
1260
+ "array" : function (input) {
1261
+ return arrayLikeToArrayLike(input, new Array(input.length));
1262
+ },
1263
+ "arraybuffer" : function (input) {
1264
+ return transform["nodebuffer"]["uint8array"](input).buffer;
1265
+ },
1266
+ "uint8array" : function (input) {
1267
+ return arrayLikeToArrayLike(input, new Uint8Array(input.length));
1268
+ },
1269
+ "nodebuffer" : identity
1270
+ };
1271
+
1272
+ /**
1273
+ * Transform an input into any type.
1274
+ * The supported output type are : string, array, uint8array, arraybuffer, nodebuffer.
1275
+ * If no output type is specified, the unmodified input will be returned.
1276
+ * @param {String} outputType the output type.
1277
+ * @param {String|Array|ArrayBuffer|Uint8Array|Buffer} input the input to convert.
1278
+ * @throws {Error} an Error if the browser doesn't support the requested output type.
1279
+ */
1280
+ JSZip.utils.transformTo = function (outputType, input) {
1281
+ if (!input) {
1282
+ // undefined, null, etc
1283
+ // an empty string won't harm.
1284
+ input = "";
1285
+ }
1286
+ if (!outputType) {
1287
+ return input;
1288
+ }
1289
+ JSZip.utils.checkSupport(outputType);
1290
+ var inputType = JSZip.utils.getTypeOf(input);
1291
+ var result = transform[inputType][outputType](input);
1292
+ return result;
1293
+ };
1294
+
1295
+ /**
1296
+ * Return the type of the input.
1297
+ * The type will be in a format valid for JSZip.utils.transformTo : string, array, uint8array, arraybuffer.
1298
+ * @param {Object} input the input to identify.
1299
+ * @return {String} the (lowercase) type of the input.
1300
+ */
1301
+ JSZip.utils.getTypeOf = function (input) {
1302
+ if (typeof input === "string") {
1303
+ return "string";
1304
+ }
1305
+ if (Object.prototype.toString.call(input) === "[object Array]") {
1306
+ return "array";
1307
+ }
1308
+ if (JSZip.support.nodebuffer && Buffer.isBuffer(input)) {
1309
+ return "nodebuffer";
1310
+ }
1311
+ if (JSZip.support.uint8array && input instanceof Uint8Array) {
1312
+ return "uint8array";
1313
+ }
1314
+ if (JSZip.support.arraybuffer && input instanceof ArrayBuffer) {
1315
+ return "arraybuffer";
1316
+ }
1317
+ };
1318
+
1319
+ /**
1320
+ * Cross-window, cross-Node-context regular expression detection
1321
+ * @param {Object} object Anything
1322
+ * @return {Boolean} true if the object is a regular expression,
1323
+ * false otherwise
1324
+ */
1325
+ JSZip.utils.isRegExp = function (object) {
1326
+ return Object.prototype.toString.call(object) === "[object RegExp]";
1327
+ };
1328
+
1329
+ /**
1330
+ * Throw an exception if the type is not supported.
1331
+ * @param {String} type the type to check.
1332
+ * @throws {Error} an Error if the browser doesn't support the requested type.
1333
+ */
1334
+ JSZip.utils.checkSupport = function (type) {
1335
+ var supported = true;
1336
+ switch (type.toLowerCase()) {
1337
+ case "uint8array":
1338
+ supported = JSZip.support.uint8array;
1339
+ break;
1340
+ case "arraybuffer":
1341
+ supported = JSZip.support.arraybuffer;
1342
+ break;
1343
+ case "nodebuffer":
1344
+ supported = JSZip.support.nodebuffer;
1345
+ break;
1346
+ case "blob":
1347
+ supported = JSZip.support.blob;
1348
+ break;
1349
+ }
1350
+ if (!supported) {
1351
+ throw new Error(type + " is not supported by this browser");
1352
+ }
1353
+ };
1354
+
1355
+
1356
+ })();
1357
+
1358
+ (function (){
1359
+ /**
1360
+ * Represents an entry in the zip.
1361
+ * The content may or may not be compressed.
1362
+ * @constructor
1363
+ */
1364
+ JSZip.CompressedObject = function () {
1365
+ this.compressedSize = 0;
1366
+ this.uncompressedSize = 0;
1367
+ this.crc32 = 0;
1368
+ this.compressionMethod = null;
1369
+ this.compressedContent = null;
1370
+ };
1371
+
1372
+ JSZip.CompressedObject.prototype = {
1373
+ /**
1374
+ * Return the decompressed content in an unspecified format.
1375
+ * The format will depend on the decompressor.
1376
+ * @return {Object} the decompressed content.
1377
+ */
1378
+ getContent : function () {
1379
+ return null; // see implementation
1380
+ },
1381
+ /**
1382
+ * Return the compressed content in an unspecified format.
1383
+ * The format will depend on the compressed conten source.
1384
+ * @return {Object} the compressed content.
1385
+ */
1386
+ getCompressedContent : function () {
1387
+ return null; // see implementation
1388
+ }
1389
+ };
1390
+ })();
1391
+
1392
+ /**
1393
+ *
1394
+ * Base64 encode / decode
1395
+ * http://www.webtoolkit.info/
1396
+ *
1397
+ * Hacked so that it doesn't utf8 en/decode everything
1398
+ **/
1399
+ JSZip.base64 = (function() {
1400
+ // private property
1401
+ var _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
1402
+
1403
+ return {
1404
+ // public method for encoding
1405
+ encode : function(input, utf8) {
1406
+ var output = "";
1407
+ var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
1408
+ var i = 0;
1409
+
1410
+ while (i < input.length) {
1411
+
1412
+ chr1 = input.charCodeAt(i++);
1413
+ chr2 = input.charCodeAt(i++);
1414
+ chr3 = input.charCodeAt(i++);
1415
+
1416
+ enc1 = chr1 >> 2;
1417
+ enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
1418
+ enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
1419
+ enc4 = chr3 & 63;
1420
+
1421
+ if (isNaN(chr2)) {
1422
+ enc3 = enc4 = 64;
1423
+ } else if (isNaN(chr3)) {
1424
+ enc4 = 64;
1425
+ }
1426
+
1427
+ output = output +
1428
+ _keyStr.charAt(enc1) + _keyStr.charAt(enc2) +
1429
+ _keyStr.charAt(enc3) + _keyStr.charAt(enc4);
1430
+
1431
+ }
1432
+
1433
+ return output;
1434
+ },
1435
+
1436
+ // public method for decoding
1437
+ decode : function(input, utf8) {
1438
+ var output = "";
1439
+ var chr1, chr2, chr3;
1440
+ var enc1, enc2, enc3, enc4;
1441
+ var i = 0;
1442
+
1443
+ input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
1444
+
1445
+ while (i < input.length) {
1446
+
1447
+ enc1 = _keyStr.indexOf(input.charAt(i++));
1448
+ enc2 = _keyStr.indexOf(input.charAt(i++));
1449
+ enc3 = _keyStr.indexOf(input.charAt(i++));
1450
+ enc4 = _keyStr.indexOf(input.charAt(i++));
1451
+
1452
+ chr1 = (enc1 << 2) | (enc2 >> 4);
1453
+ chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
1454
+ chr3 = ((enc3 & 3) << 6) | enc4;
1455
+
1456
+ output = output + String.fromCharCode(chr1);
1457
+
1458
+ if (enc3 != 64) {
1459
+ output = output + String.fromCharCode(chr2);
1460
+ }
1461
+ if (enc4 != 64) {
1462
+ output = output + String.fromCharCode(chr3);
1463
+ }
1464
+
1465
+ }
1466
+
1467
+ return output;
1468
+
1469
+ }
1470
+ };
1471
+ }());
1472
+
1473
+ // enforcing Stuk's coding style
1474
+ // vim: set shiftwidth=3 softtabstop=3: