nakarte

Source code of https://map.sikmir.ru (fork)
git clone git://git.sikmir.ru/nakarte
Log | Files | Refs | LICENSE

commit b7c6cbfadcc72c9ee1d5048087c840398422a72c
parent 863de76fb6cb97d6b908a63d57f956c2da13fa0f
Author: Sergej Orlov <wladimirych@gmail.com>
Date:   Fri, 16 Dec 2016 18:17:19 +0300

[tracks] read binary text from xhr using arraybuffer instead of overriding mime-type; strip Byte Order Mark when parsing gpx and kml

Chrome always overrides encoding when file contains BOM

Diffstat:
Msrc/lib/leaflet.control.track-list/lib/geo_file_formats.js | 3+++
Msrc/lib/leaflet.control.track-list/track-list.js | 2+-
Asrc/lib/stripBom/index.js | 6++++++
Msrc/lib/xhr-promise/index.js | 21+++++++++++++++++++--
4 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/src/lib/leaflet.control.track-list/lib/geo_file_formats.js b/src/lib/leaflet.control.track-list/lib/geo_file_formats.js @@ -1,5 +1,6 @@ import JSUnzip from 'vendored/github.com/augustl/js-unzip/js-unzip'; import RawDeflate from 'vendored/github.com/dankogai/js-deflate/rawinflate'; +import stripBom from 'lib/stripBom'; import {decode as utf8_decode} from 'utf8'; @@ -65,6 +66,7 @@ function parseGpx(txt, name) { return waypoints; }; + txt = stripBom(txt); // remove namespaces txt = txt.replace(/<([^ >]+):([^ >]+)/g, '<$1_$2'); var dom = (new DOMParser()).parseFromString(txt, "text/xml"); @@ -248,6 +250,7 @@ function parseKml(txt, name) { return points; } + txt = stripBom(txt); txt = txt.replace(/<([^ >]+):([^ >]+)/g, '<$1_$2'); var dom = (new DOMParser()).parseFromString(txt, "text/xml"); if (dom.documentElement.nodeName === 'parsererror') { diff --git a/src/lib/leaflet.control.track-list/track-list.js b/src/lib/leaflet.control.track-list/track-list.js @@ -241,7 +241,7 @@ L.Control.TrackList = L.Control.extend({ .pop(); fetch(url_for_request, {responseType: 'binarystring'}) .then(function(xhr) { - var geodata = parseGeoFile(name, xhr.response); + var geodata = parseGeoFile(name, xhr.responseBinaryText); this.addTracksFromGeodataArray(geodata); }.bind(this), function() { diff --git a/src/lib/stripBom/index.js b/src/lib/stripBom/index.js @@ -0,0 +1,6 @@ +export default function stripBom(s) { + if (s.substr(0, 3) === '\xef\xbb\xbf') { + s = s.substr(3); + } + return s; +} diff --git a/src/lib/xhr-promise/index.js b/src/lib/xhr-promise/index.js @@ -6,6 +6,20 @@ function retryIfNetworkErrorOrServerError(xhr) { return (xhr.status === 0 || xhr.status >= 500); } + +function arrayBufferToString(arBuf) { + const result = []; + const arr = new Uint8Array(arBuf); + let chunk; + for (let i = 0; i < arr.length; i += 4096) { + chunk = arr.subarray(i, i + 4096); + chunk = String.fromCharCode.apply(null, chunk); + result.push(chunk); + } + return result.join(''); +} + + class XMLHttpRequestPromise { constructor( url, {method='GET', data=null, responseType='', timeout=30000, maxTries=3, retryTimeWait=1000, @@ -20,6 +34,7 @@ class XMLHttpRequestPromise { this.catch = promise.catch.bind(promise); this.method = method; this.url = url; + this.responseType = responseType; this.postData = data; this._isResponseSuccess = isResponseSuccess; this._responseNeedsRetry = responseNeedsRetry; @@ -31,8 +46,7 @@ class XMLHttpRequestPromise { this._open(); xhr.timeout = timeout; if (responseType === 'binarystring') { - xhr.responseType = 'text'; - xhr.overrideMimeType('text/plain; charset=x-user-defined'); + xhr.responseType = 'arraybuffer'; } else { xhr.responseType = responseType; } @@ -47,6 +61,9 @@ class XMLHttpRequestPromise { const xhr = this.xhr; if (xhr.readyState === 4 && !this._aborted) { // console.log('ready state 4', this.url); + if (this.responseType === 'binarystring' && xhr.response && xhr.response.byteLength) { + xhr.responseBinaryText = arrayBufferToString(xhr.response); + } if (this._isResponseSuccess(xhr)) { // console.log('success', this.url); this._resolve(xhr);