1 /****************************************************************************
  2  Copyright (c) 2010-2012 cocos2d-x.org
  3  Copyright (c) 2008-2010 Ricardo Quesada
  4  Copyright (c) 2011      Zynga Inc.
  5 
  6  http://www.cocos2d-x.org
  7 
  8  Permission is hereby granted, free of charge, to any person obtaining a copy
  9  of this software and associated documentation files (the "Software"), to deal
 10  in the Software without restriction, including without limitation the rights
 11  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 12  copies of the Software, and to permit persons to whom the Software is
 13  furnished to do so, subject to the following conditions:
 14 
 15  The above copyright notice and this permission notice shall be included in
 16  all copies or substantial portions of the Software.
 17 
 18  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 19  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 20  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 21  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 22  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 23  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 24  THE SOFTWARE.
 25  ****************************************************************************/
 26 
 27 /**
 28  * @constant
 29  * @type Number
 30  */
 31 cc.SAX_NONE = 0;
 32 
 33 /**
 34  * @constant
 35  * @type Number
 36  */
 37 cc.SAX_KEY = 1;
 38 
 39 /**
 40  * @constant
 41  * @type Number
 42  */
 43 cc.SAX_DICT = 2;
 44 
 45 /**
 46  * @constant
 47  * @type Number
 48  */
 49 cc.SAX_INT = 3;
 50 
 51 /**
 52  * @constant
 53  * @type Number
 54  */
 55 cc.SAX_REAL = 4;
 56 
 57 /**
 58  * @constant
 59  * @type Number
 60  */
 61 cc.SAX_STRING = 5;
 62 
 63 /**
 64  * @constant
 65  * @type Number
 66  */
 67 cc.SAX_ARRAY = 6;
 68 
 69 //Compatibility with IE9
 70 var Uint8Array = Uint8Array || Array;
 71 
 72 if (/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent)) {
 73     var IEBinaryToArray_ByteStr_Script =
 74         "<!-- IEBinaryToArray_ByteStr -->\r\n" +
 75             //"<script type='text/vbscript'>\r\n" +
 76             "Function IEBinaryToArray_ByteStr(Binary)\r\n" +
 77             "   IEBinaryToArray_ByteStr = CStr(Binary)\r\n" +
 78             "End Function\r\n" +
 79             "Function IEBinaryToArray_ByteStr_Last(Binary)\r\n" +
 80             "   Dim lastIndex\r\n" +
 81             "   lastIndex = LenB(Binary)\r\n" +
 82             "   if lastIndex mod 2 Then\r\n" +
 83             "       IEBinaryToArray_ByteStr_Last = Chr( AscB( MidB( Binary, lastIndex, 1 ) ) )\r\n" +
 84             "   Else\r\n" +
 85             "       IEBinaryToArray_ByteStr_Last = " + '""' + "\r\n" +
 86             "   End If\r\n" +
 87             "End Function\r\n";// +
 88             //"</script>\r\n";
 89 
 90     // inject VBScript
 91     //document.write(IEBinaryToArray_ByteStr_Script);
 92     var myVBScript = document.createElement('script');
 93     myVBScript.type = "text/vbscript";
 94     myVBScript.textContent = IEBinaryToArray_ByteStr_Script;
 95     document.body.appendChild(myVBScript);
 96 
 97     // helper to convert from responseBody to a "responseText" like thing
 98     cc._convertResponseBodyToText = function (binary) {
 99         var byteMapping = {};
100         for (var i = 0; i < 256; i++) {
101             for (var j = 0; j < 256; j++) {
102                 byteMapping[ String.fromCharCode(i + j * 256) ] =
103                     String.fromCharCode(i) + String.fromCharCode(j);
104             }
105         }
106         var rawBytes = IEBinaryToArray_ByteStr(binary);
107         var lastChr = IEBinaryToArray_ByteStr_Last(binary);
108         return rawBytes.replace(/[\s\S]/g,
109             function (match) {
110                 return byteMapping[match];
111             }) + lastChr;
112     };
113 }
114 
115 /**
116  * @namespace
117  */
118 cc.FileUtils = cc.Class.extend({
119     _fileDataCache:null,
120 
121     ctor:function () {
122         this._fileDataCache = {};
123     },
124     /**
125      * Get resource file data
126      * @function
127      * @param {String} fileName The resource file name which contain the path
128      * @param {String} mode mode The read mode of the file
129      * @param {Number} size If get the file data succeed the it will be the data size,or it will be 0
130      * @warning If you get the file data succeed,you must delete it after used.
131      */
132     getFileData:function (fileName, mode, size) {
133         if (this._fileDataCache.hasOwnProperty(fileName))
134             return this._fileDataCache[fileName];
135 
136         return this._loadBinaryFileData(fileName);
137     },
138 
139     _getXMLHttpRequest:function () {
140         if (window.XMLHttpRequest) {
141             return new window.XMLHttpRequest();
142         } else {
143             return new ActiveXObject("MSXML2.XMLHTTP");
144         }
145     },
146 
147     preloadBinaryFileData:function (fileUrl) {
148         fileUrl = this.fullPathFromRelativePath(fileUrl);
149         var selfPointer = this;
150 
151         var xhr = this._getXMLHttpRequest();
152         xhr.open("GET", fileUrl, true);
153         if (/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent)) {
154             // IE-specific logic here
155             xhr.setRequestHeader("Accept-Charset", "x-user-defined");
156             xhr.onreadystatechange = function (event) {
157                 if (xhr.readyState == 4) {
158                     if (xhr.status == 200) {
159                         var fileContents = cc._convertResponseBodyToText(xhr.responseBody);
160                         if (fileContents)
161                             selfPointer._fileDataCache[fileUrl] = selfPointer._stringConvertToArray(fileContents);
162                     }
163                     cc.Loader.getInstance().onResLoaded();
164                 }
165             };
166         } else {
167             if (xhr.overrideMimeType)
168                 xhr.overrideMimeType("text\/plain; charset=x-user-defined");
169             xhr.onload = function (e) {
170                 var arrayStr = xhr.responseText;
171                 if (arrayStr) {
172                     cc.Loader.getInstance().onResLoaded();
173                     selfPointer._fileDataCache[fileUrl] = selfPointer._stringConvertToArray(arrayStr);
174                 }
175             };
176         }
177         xhr.send(null);
178     },
179 
180     _loadBinaryFileData:function (fileUrl) {
181         var req = this._getXMLHttpRequest();
182         req.open('GET', fileUrl, false);
183         var arrayInfo = null;
184         if (/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent)) {
185             req.setRequestHeader("Accept-Charset", "x-user-defined");
186             req.send(null);
187             if (req.status != 200)
188                 return null;
189 
190             var fileContents = cc._convertResponseBodyToText(req.responseBody);
191             if(fileContents){
192                 arrayInfo = this._stringConvertToArray(req.responseText);
193                 this._fileDataCache[fileUrl] = arrayInfo;
194             }
195         } else {
196             if (req.overrideMimeType)
197                 req.overrideMimeType('text\/plain; charset=x-user-defined');
198             req.send(null);
199             if (req.status != 200)
200                 return null;
201 
202             arrayInfo = this._stringConvertToArray(req.responseText);
203             this._fileDataCache[fileUrl] = arrayInfo;
204         }
205         return arrayInfo;
206     },
207 
208     _stringConvertToArray:function (strData) {
209         if (!strData)
210             return null;
211 
212         var arrData = new Uint8Array(strData.length);
213         for (var i = 0; i < strData.length; i++) {
214             arrData[i] = strData.charCodeAt(i) & 0xff;
215         }
216         return arrData;
217     },
218 
219     /**
220      * Get resource file data from zip file
221      * @function
222      * @param {String} pszZipFilePath
223      * @param {String} fileName fileName The resource file name which contain the relative path of zip file
224      * @param {Number} size size If get the file data succeed the it will be the data size,or it will be 0
225      * @warning If you get the file data succeed,you must delete it after used.
226      * @deprecated
227      */
228     getFileDataFromZip:function (pszZipFilePath, fileName, size) {
229     },
230 
231     /**
232      * removes the HD suffix from a path
233      * @function
234      * @param {String} path
235      * @deprecated
236      */
237     removeSuffixFromFile:function (path) {
238     },
239 
240 //////////////////////////////////////////////////////////////////////////
241 // Notification support when getFileData from invalid file path.
242 //////////////////////////////////////////////////////////////////////////
243     /**
244      * Notification support when getFileData from invalid file path.
245      * @function
246      * @type {Boolean}
247      */
248     popupNotify:true,
249 
250     /**
251      * Generate the absolute path of the file.
252      * @function
253      * @param {String} pszRelativePath
254      * @return {String} The absolute path of the file.
255      * @warning We only add the ResourcePath before the relative path of the file. <br/>
256      * If you have not set the ResourcePath,the function add "/NEWPLUS/TDA_DATA/UserData/" as default.<br/>
257      * You can set ResourcePath by function void setResourcePath(const char *resourcePath);
258      */
259     fullPathFromRelativePath:function (pszRelativePath) {
260         return pszRelativePath;
261     },
262 
263     /**
264      * Generate the relative path of the file.
265      * @function
266      * @param {String} filename
267      * @param {String} relativeFile
268      * @return {String}
269      */
270     fullPathFromRelativeFile:function (filename, relativeFile) {
271         var tmpPath;
272         if (filename) {
273             tmpPath = relativeFile.substring(0, relativeFile.lastIndexOf("/") + 1);
274             return tmpPath + filename;
275         }
276         else {
277             tmpPath = relativeFile.substring(0, relativeFile.lastIndexOf("."));
278             tmpPath = tmpPath + ".png";
279             return tmpPath;
280         }
281     },
282 
283     /**
284      * Set the ResourcePath,we will find resource in this path
285      * @function
286      * @param {String} resourcePath The absolute resource path
287      * @warning Don't call this function in android and iOS, it has not effect.<br/>
288      * In android, if you want to read file other than apk, you shoud use invoke getFileData(), and pass the<br/>
289      * absolute path.
290      * @deprecated
291      */
292     setResourcePath:function (resourcePath) {
293     },
294 
295     /**
296      * Generate an Dictionary of object by file
297      * @function
298      * @param fileName The file name of *.plist file
299      * @return {object} The Dictionary of object generated from the file
300      */
301     dictionaryWithContentsOfFile:function (fileName) {
302         var parser = cc.SAXParser.getInstance();
303         this.rootDict = parser.parse(fileName);
304         return this.rootDict;
305     },
306 
307     /**
308      * The same meaning as dictionaryWithContentsOfFile(), but it doesn't call autorelease, so the invoker should call release().
309      * @function
310      * @param {String} fileName
311      * @return {object} The Dictionary of object generated from the file
312      */
313     dictionaryWithContentsOfFileThreadSafe:function (fileName) {
314         var tMaker = new cc.DictMaker();
315         return tMaker.dictionaryWithContentsOfFile(fileName);
316     },
317 
318     /**
319      * Get the writeable path
320      * @function
321      * @return  The path that can write/read file
322      * @deprecated
323      */
324     getWriteablePath:function () {
325     },
326 
327     /**
328      * Set whether pop-up a message box when the image load failed
329      * @function
330      * @param {Boolean} notify
331      */
332     setPopupNotify:function (notify) {
333         cc.popupNotify = notify;
334     },
335 
336     /**
337      * Get whether pop-up a message box when the image load failed
338      * @function
339      * @return {Boolean}
340      */
341     isPopupNotify:function () {
342         return cc.popupNotify;
343     }
344 });
345 
346 cc.s_SharedFileUtils = null;
347 cc.FileUtils.getInstance = function () {
348     if (cc.s_SharedFileUtils == null) {
349         cc.s_SharedFileUtils = new cc.FileUtils();
350     }
351     return cc.s_SharedFileUtils;
352 };
353 
354 /**
355  * plist Dictionary Maker
356  * @class
357  * @extends cc.Class
358  * @example
359  * //create a DictMaker
360  * var tMaker = new cc.DictMaker();
361  * tMaker.dictionaryWithContentsOfFile(fileName);
362  */
363 cc.DictMaker = cc.Class.extend(/** @lends cc.DictMaker# */{
364     rootDict:[],
365     /**
366      * Generate dictionary with contents of file
367      * @param {String} fileName
368      * @return {Array}
369      */
370     dictionaryWithContentsOfFile:function (fileName) {
371         var parser = cc.SAXParser.getInstance();
372         this.rootDict = parser.parse(fileName);
373         return this.rootDict;
374     }
375 });
376