1 /*
  2     Copyright 2008,
  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: you can redistribute it and/or modify
 13     it under the terms of the GNU Lesser General Public License as published by
 14     the Free Software Foundation, either version 3 of the License, or
 15     (at your option) any later version.
 16 
 17     JSXGraph is distributed in the hope that it will be useful,
 18     but WITHOUT ANY WARRANTY; without even the implied warranty of
 19     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 20     GNU Lesser General Public License for more details.
 21 
 22     You should have received a copy of the GNU Lesser General Public License
 23     along with JSXGraph.  If not, see <http://www.gnu.org/licenses/>.
 24 */
 25 
 26 JXG.FileReader = new function() {
 27 
 28 this.parseFileContent = function(url, board, format) {
 29     this.request = false;
 30     var e;
 31     try {
 32         //this.request = new ActiveXObject("Msxml2.XMLHTTP");
 33         this.request = new XMLHttpRequest();
 34         if(format.toLowerCase()=='raw')
 35             this.request.overrideMimeType('text/plain; charset=iso-8859-1');
 36         else
 37             this.request.overrideMimeType('text/xml; charset=iso-8859-1');
 38     } catch (e) {
 39         try {
 40             this.request = new ActiveXObject("Msxml2.XMLHTTP");
 41         } catch (e) {
 42             try {
 43                 this.request = new ActiveXObject("Microsoft.XMLHTTP");
 44             } catch (e) {
 45                 this.request = false;
 46             }
 47         }
 48     }
 49     if (!this.request) {
 50         alert("AJAX not activated!");
 51         return;
 52     }
 53     this.request.open("GET", url, true);
 54     if(format.toLowerCase()=='raw') {
 55         this.cbp = function() {
 56             var request = this.request;
 57             if (request.readyState == 4) {
 58                 board(request.responseText);
 59             }
 60         }; //).bind(this);
 61     } else {
 62         this.cbp = function() {
 63             var request = this.request;
 64             if (request.readyState == 4) {
 65                 var text = '';
 66 
 67             if (typeof request.responseStream!='undefined' && 
 68                     (request.responseText.slice(0,2) == "PK"                            // ZIP -> Geogebra
 69                     || JXG.Util.asciiCharCodeAt(request.responseText.slice(0,1),0)==31) // gzip -> Cinderella
 70                    ) {
 71                     //text = (new JXG.Util.Unzip(JXG.Util.Base64.decodeAsArray(BinFileReader(request)))).unzip();
 72                     //text = text[0][0];
 73                     //text = BinFileReader(request);  
 74                     text = JXG.Util.Base64.decode(BinFileReader(request)); // After this, text contains the base64 encoded, zip-compressed string
 75                 } else {
 76                     text = request.responseText;
 77                 }
 78                 this.parseString(text, board, format, false);
 79             }
 80         }; //).bind(this);
 81     }
 82     this.cb = JXG.bind(this.cbp,this);
 83     this.request.onreadystatechange = this.cb;
 84 
 85     try {
 86         this.request.send(null);
 87     } catch (e) {
 88         throw new Error("JSXGraph: problems opening " + url + " !");
 89     }
 90 }; // end: this.parseFileContent
 91 
 92 this.cleanWhitespace = function(el) {
 93     var cur = el.firstChild;
 94     while ( cur != null ) {
 95         if ( cur.nodeType == 3 && ! /\S/.test(cur.nodeValue) ) {
 96             el.removeChild( cur );
 97         } else if ( cur.nodeType == 1 ) {
 98             this.cleanWhitespace( cur );
 99         }
100         cur = cur.nextSibling;
101     }
102 };
103 
104 this.stringToXMLTree = function(fileStr) {
105     // The string "fileStr" is converted into a XML tree.
106     if(typeof DOMParser == "undefined") {
107        // IE workaround, since there is no DOMParser
108        DOMParser = function () {};
109        DOMParser.prototype.parseFromString = function (str, contentType) {
110           if (typeof ActiveXObject != "undefined") {
111              var d = new ActiveXObject("MSXML.DomDocument");
112              d.loadXML(str);
113              return d;
114           }
115        };
116     }
117     var parser=new DOMParser();
118 
119     var tree = parser.parseFromString(fileStr,"text/xml");
120     this.cleanWhitespace(tree);
121     return tree;
122 };
123 
124 this.parseString = function(fileStr, board, format, isString) {
125     var tree, graph;
126 
127     if (format.toLowerCase()=='cdy' || format.toLowerCase()=='cinderella') {
128     	// if isString is true, fileStr is the base64 encoded zip file, otherwise it's just the zip file
129     	if(isString)
130     		fileStr = JXG.Util.Base64.decode(fileStr);
131         fileStr = JXG.CinderellaReader.readCinderella(fileStr, board);
132         board.xmlString = fileStr;
133         return;
134     }
135     if (format.toLowerCase()=='graph') {
136         //if(isString)
137         fileStr = JXG.GraphReader.readGraph(fileStr, board, false);
138         return;
139     }
140     if (format.toLowerCase()=='digraph') {
141         //if(isString)
142         fileStr = JXG.GraphReader.readGraph(fileStr, board, true);
143         return;
144     }    
145 
146     // fileStr is a string containing the XML code of the construction
147     if (format.toLowerCase()=='geonext') {
148         fileStr = JXG.GeonextReader.prepareString(fileStr);
149     }
150     if (format.toLowerCase()=='geogebra') {
151         isString = fileStr.slice(0, 2) !== "PK";
152 
153         // if isString is true, fileStr is a base64 encoded string, otherwise it's the zipped file
154     	fileStr = JXG.GeogebraReader.prepareString(fileStr, isString);
155     }
156     if (format.toLowerCase()=='intergeo') {
157         if(isString)
158             fileStr = JXG.Util.Base64.decode(fileStr);
159     	fileStr = JXG.IntergeoReader.prepareString(fileStr);
160     }
161 
162     board.xmlString = fileStr;
163     tree = this.stringToXMLTree(fileStr);
164     // Now, we can walk through the tree
165     this.readElements(tree, board, format);
166 }; // end this.parse
167 
168 /**
169  * Reading the elements of a geonext or geogebra file
170  * @param {} tree expects the content of the parsed geonext file returned by function parseFromString
171  * @param {Object} board board object
172  */
173 this.readElements = function(tree, board, format) {
174     if (format.toLowerCase()=='geonext') {
175         board.suspendUpdate();
176         if(tree.getElementsByTagName('GEONEXT').length != 0) {
177             JXG.GeonextReader.readGeonext(tree, board);
178         }
179         board.unsuspendUpdate();
180     }
181     else if(tree.getElementsByTagName('geogebra').length != 0) {
182         JXG.GeogebraReader.readGeogebra(tree, board);
183     }
184     else if(format.toLowerCase()=='intergeo') {
185         JXG.IntergeoReader.readIntergeo(tree, board);
186     }
187     // cdy is already parsed in parseString()
188 }; // end: this.readElements()
189 
190 }; // end: FileReader()
191 
192 if(/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent)) {
193 document.write('<script type="text/vbscript">\n\
194 Function Base64Encode(inData)\n\
195   Const Base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"\n\
196   Dim cOut, sOut, I\n\
197   For I = 1 To LenB(inData) Step 3\n\
198     Dim nGroup, pOut, sGroup\n\
199     nGroup = &H10000 * AscB(MidB(inData, I, 1)) + _\n\
200       &H100 * MyASC(MidB(inData, I + 1, 1)) + MyASC(MidB(inData, I + 2, 1))\n\
201     nGroup = Oct(nGroup)\n\
202     nGroup = String(8 - Len(nGroup), "0") & nGroup\n\
203     pOut = Mid(Base64, CLng("&o" & Mid(nGroup, 1, 2)) + 1, 1) + _\n\
204       Mid(Base64, CLng("&o" & Mid(nGroup, 3, 2)) + 1, 1) + _\n\
205       Mid(Base64, CLng("&o" & Mid(nGroup, 5, 2)) + 1, 1) + _\n\
206       Mid(Base64, CLng("&o" & Mid(nGroup, 7, 2)) + 1, 1)\n\
207     sOut = sOut + pOut\n\
208   Next\n\
209   Select Case LenB(inData) Mod 3\n\
210     Case 1: \'8 bit final\n\
211       sOut = Left(sOut, Len(sOut) - 2) + "=="\n\
212     Case 2: \'16 bit final\n\
213       sOut = Left(sOut, Len(sOut) - 1) + "="\n\
214   End Select\n\
215   Base64Encode = sOut\n\
216 End Function\n\
217 \n\
218 Function MyASC(OneChar)\n\
219   If OneChar = "" Then MyASC = 0 Else MyASC = AscB(OneChar)\n\
220 End Function\n\
221 \n\
222 Function BinFileReader(xhr)\n\
223     Dim byteString\n\
224     Dim b64String\n\
225     Dim i\n\
226     byteString = xhr.responseBody\n\
227     ReDim byteArray(LenB(byteString))\n\
228     For i = 1 To LenB(byteString)\n\
229         byteArray(i-1) = AscB(MidB(byteString, i, 1))\n\
230     Next\n\
231     b64String = Base64Encode(byteString)\n\
232     BinFileReader = b64String\n\
233 End Function\n\
234 </script>\n');
235 }
236