1 /* 2 Copyright 2008-2013 3 Matthias Ehmann, 4 Michael Gerhaeuser, 5 Carsten Miller, 6 Bianca Valentin, 7 Alfred Wassermann, 8 Peter Wilfahrt 9 10 This file is part of JSXGraph. 11 12 JSXGraph is free software dual licensed under the GNU LGPL or MIT License. 13 14 You can redistribute it and/or modify it under the terms of the 15 16 * GNU Lesser General Public License as published by 17 the Free Software Foundation, either version 3 of the License, or 18 (at your option) any later version 19 OR 20 * MIT License: https://github.com/jsxgraph/jsxgraph/blob/master/LICENSE.MIT 21 22 JSXGraph is distributed in the hope that it will be useful, 23 but WITHOUT ANY WARRANTY; without even the implied warranty of 24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 GNU Lesser General Public License for more details. 26 27 You should have received a copy of the GNU Lesser General Public License and 28 the MIT License along with JSXGraph. If not, see <http://www.gnu.org/licenses/> 29 and <http://opensource.org/licenses/MIT/>. 30 */ 31 32 33 /*global JXG:true, define: true, ActiveXObject:true, jxgBinFileReader:true, DOMParser:true, XMLHttpRequest:true, document:true, navigator:true*/ 34 /*jslint nomen: true, plusplus: true*/ 35 36 /* depends: 37 jxg 38 utils/env 39 utils/type 40 utils/encoding 41 utils/base64 42 */ 43 44 define([ 45 'jxg', 'utils/env', 'utils/type', 'utils/encoding', 'utils/base64' 46 ], function (JXG, Env, Type, Encoding, Base64) { 47 48 "use strict"; 49 50 /** 51 * The FileReader object bundles the file input capabilities of JSXGraph. 52 */ 53 JXG.FileReader = { 54 55 /** 56 * Opens a file using the given URL and passes the contents to {@link JXG.FileReader#parseString} 57 * @param {String} url 58 * @param {JXG.Board|function} board Either a board or in case <tt>format</tt> equals 'raw' this has to be a callback function. 59 * @param {String} format The expected file format. Possible values are <dl> 60 * <dt>raw</dt><dd>Raw text file. In this case <tt>board</tt> has to be a callback function.</dd> 61 * <dt>geonext</dt><dd>Geonext File <a href="http://www.geonext.de">http://www.geonext.de</a></dd> 62 * <dt>intergeo</dt><dd>Intergeo file format <a href="http://www.i2geo.net">http://www.i2geo.net</a></dd> 63 * <dt>tracenpoche</dt><dd>Tracenpoche construction <a href="http://www.tracenpoche.net">http://www.tracenpoche.net</a></dd> 64 * <dt>graph</dt><dd>Graph file</dd> 65 * <dt>digraph</dt><dd>DiGraph file</dd> 66 * <dt>geogebra</dt><dd>Geogebra File <a href="http://www.geogebra.org">http://www.geogebra.org</a></dd> 67 * <dl><dt>cdy or cinderella</dt><dd>Cinderella (<a href="http://www.cinderella.de/">http://www.cinderella.de</a></dd> 68 * </dl> 69 * @param {Boolean} async Call ajax asynchonously. 70 * @param {function} callback A function that is run when the board is ready. 71 */ 72 parseFileContent: function (url, board, format, async, callback) { 73 var request = false; 74 75 if (!Type.exists(async)) { 76 async = true; 77 } 78 79 //this.request = false; 80 81 try { 82 request = new XMLHttpRequest(); 83 if (format.toLowerCase() === 'raw') { 84 request.overrideMimeType('text/plain; charset=iso-8859-1'); 85 } else { 86 request.overrideMimeType('text/xml; charset=iso-8859-1'); 87 } 88 } catch (e) { 89 try { 90 request = new ActiveXObject("Msxml2.XMLHTTP"); 91 } catch (ex) { 92 try { 93 request = new ActiveXObject("Microsoft.XMLHTTP"); 94 } catch (exc) { 95 request = false; 96 } 97 } 98 } 99 100 if (!request) { 101 JXG.debug("AJAX not activated!"); 102 return; 103 } 104 105 request.open("GET", url, async); 106 107 if (format.toLowerCase() === 'raw') { 108 this.cbp = function () { 109 var req = request; 110 if (req.readyState === 4) { 111 board(req.responseText); 112 } 113 }; 114 } else { 115 this.cbp = function () { 116 var req = request, 117 text = ''; 118 119 if (req.readyState === 4) { 120 if (Type.exists(req.responseStream) && 121 // PK: zip, geogebra 122 // 31: gzip, cinderella 123 (req.responseText.slice(0, 2) === "PK" || 124 Encoding.asciiCharCodeAt(req.responseText.slice(0, 1), 0) === 31)) { 125 126 // After this, text contains the base64 encoded, zip-compressed string 127 text = Base64.decode(jxgBinFileReader(req)); 128 } else { 129 text = req.responseText; 130 } 131 this.parseString(text, board, format, callback); 132 } 133 }; 134 } 135 136 this.cb = Type.bind(this.cbp, this); 137 request.onreadystatechange = this.cb; 138 139 try { 140 request.send(null); 141 } catch (ex2) { 142 throw new Error("JSXGraph: A problem occurred while trying to read '" + url + "'."); 143 } 144 }, 145 146 /** 147 * Parses a given string according to the file format given in format. 148 * @param {String} str Contents of the file. 149 * @param {JXG.Board} board The board the construction in the file should be loaded in. 150 * @param {String} format Possible values are <dl> 151 * <dt>raw</dt><dd>Raw text file. In this case <tt>board</tt> has to be a callback function.</dd> 152 * <dt>geonext</dt><dd>Geonext File <a href="http://www.geonext.de">http://www.geonext.de</a></dd> 153 * <dt>intergeo</dt><dd>Intergeo file format <a href="http://www.i2geo.net">http://www.i2geo.net</a></dd> 154 * <dt>tracenpoche</dt><dd>Tracenpoche construction <a href="http://www.tracenpoche.net">http://www.tracenpoche.net</a></dd> 155 * <dt>graph</dt><dd>Graph file</dd> 156 * <dt>digraph</dt><dd>DiGraph file</dd> 157 * <dt>geogebra</dt><dd>Geogebra File <a href="http://www.geogebra.org">http://www.geogebra.org</a></dd> 158 * <dl><dt>cdy or cinderella</dt><dd>Cinderella (<a href="http://www.cinderella.de/">http://www.cinderella.de</a></dd> 159 * </dl> 160 * @param {function} callback 161 */ 162 parseString: function (str, board, format, callback) { 163 var Reader, 164 read; 165 166 format = format.toLowerCase(); 167 168 Reader = JXG.readers[format]; 169 170 if (Type.exists(Reader)) { 171 read = new Reader(board, str); 172 read.read(); 173 } else { 174 throw new Error('JSXGraph: There is no reader available for \'' + format + '\'.'); 175 } 176 177 if (typeof callback === 'function') { 178 callback(board); 179 } 180 } 181 }; 182 183 // The following code is vbscript. This is a workaround to enable binary data downloads via AJAX in 184 // Microsoft Internet Explorer. 185 186 /*jslint evil:true, es5:true, white:true*/ 187 /*jshint multistr:true*/ 188 if (!Env.isMetroApp() && Env.isBrowser && typeof navigator === 'object' && /msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent) && document && document.write) { 189 document.write('<script type="text/vbscript">\n\ 190 Function Base64Encode(inData)\n\ 191 Const Base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"\n\ 192 Dim cOut, sOut, I\n\ 193 For I = 1 To LenB(inData) Step 3\n\ 194 Dim nGroup, pOut, sGroup\n\ 195 nGroup = &H10000 * AscB(MidB(inData, I, 1)) + _\n\ 196 &H100 * MyASC(MidB(inData, I + 1, 1)) + MyASC(MidB(inData, I + 2, 1))\n\ 197 nGroup = Oct(nGroup)\n\ 198 nGroup = String(8 - Len(nGroup), "0") & nGroup\n\ 199 pOut = Mid(Base64, CLng("&o" & Mid(nGroup, 1, 2)) + 1, 1) + _\n\ 200 Mid(Base64, CLng("&o" & Mid(nGroup, 3, 2)) + 1, 1) + _\n\ 201 Mid(Base64, CLng("&o" & Mid(nGroup, 5, 2)) + 1, 1) + _\n\ 202 Mid(Base64, CLng("&o" & Mid(nGroup, 7, 2)) + 1, 1)\n\ 203 sOut = sOut + pOut\n\ 204 Next\n\ 205 Select Case LenB(inData) Mod 3\n\ 206 Case 1: \'8 bit final\n\ 207 sOut = Left(sOut, Len(sOut) - 2) + "=="\n\ 208 Case 2: \'16 bit final\n\ 209 sOut = Left(sOut, Len(sOut) - 1) + "="\n\ 210 End Select\n\ 211 Base64Encode = sOut\n\ 212 End Function\n\ 213 \n\ 214 Function MyASC(OneChar)\n\ 215 If OneChar = "" Then MyASC = 0 Else MyASC = AscB(OneChar)\n\ 216 End Function\n\ 217 \n\ 218 Function jxgBinFileReader(xhr)\n\ 219 Dim byteString\n\ 220 Dim b64String\n\ 221 Dim i\n\ 222 byteString = xhr.responseBody\n\ 223 ReDim byteArray(LenB(byteString))\n\ 224 For i = 1 To LenB(byteString)\n\ 225 byteArray(i-1) = AscB(MidB(byteString, i, 1))\n\ 226 Next\n\ 227 b64String = Base64Encode(byteString)\n\ 228 jxgBinFileReader = b64String\n\ 229 End Function\n\ 230 </script>\n'); 231 } 232 233 return JXG.FileReader; 234 }); 235